View Javadoc

1   /*
2    * Copyright 2009 Red Hat, Inc.
3    *
4    * Red Hat licenses this file to you under the Apache License, version 2.0
5    * (the "License"); you may not use this file except in compliance with the
6    * License.  You may obtain a copy of the License at:
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package org.jboss.netty.handler.codec.http2;
17  
18  import java.io.UnsupportedEncodingException;
19  import java.net.URI;
20  import java.net.URISyntaxException;
21  import java.net.URLEncoder;
22  import java.nio.charset.Charset;
23  import java.nio.charset.UnsupportedCharsetException;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  /**
28   * Creates an URL-encoded URI from a path string and key-value parameter pairs.
29   * This encoder is for one time use only.  Create a new instance for each URI.
30   *
31   * <pre>
32   * {@link QueryStringEncoder} encoder = new {@link QueryStringDecoder}("/hello");
33   * encoder.addParam("recipient", "world");
34   * assert encoder.toString().equals("/hello?recipient=world");
35   * </pre>
36   *
37   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
38   * @author Andy Taylor (andy.taylor@jboss.org)
39   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
40   * @version $Rev: 1107 $, $Date: 2012-04-15 19:00:57 +0200 (dim., 15 avr. 2012) $
41   *
42   * @see QueryStringDecoder
43   *
44   * @apiviz.stereotype utility
45   * @apiviz.has        org.jboss.netty.handler.codec.http2.HttpRequest oneway - - encodes
46   */
47  public class QueryStringEncoder {
48  
49      private final Charset charset;
50      private final String uri;
51      private final List<Param> params = new ArrayList<Param>();
52  
53      /**
54       * Creates a new encoder that encodes a URI that starts with the specified
55       * path string.  The encoder will encode the URI in UTF-8.
56       */
57      public QueryStringEncoder(String uri) {
58          this(uri, HttpCodecUtil.DEFAULT_CHARSET);
59      }
60  
61      /**
62       * Creates a new encoder that encodes a URI that starts with the specified
63       * path string in the specified charset.
64       */
65      public QueryStringEncoder(String uri, Charset charset) {
66          if (uri == null) {
67              throw new NullPointerException("uri");
68          }
69          if (charset == null) {
70              throw new NullPointerException("charset");
71          }
72  
73          this.uri = uri;
74          this.charset = charset;
75      }
76  
77      /**
78       * @deprecated Use {@link #QueryStringEncoder(String, Charset)} instead.
79       */
80      @Deprecated
81      public QueryStringEncoder(String uri, String charset) {
82          this(uri, Charset.forName(charset));
83      }
84  
85      /**
86       * Adds a parameter with the specified name and value to this encoder.
87       */
88      public void addParam(String name, String value) {
89          if (name == null) {
90              throw new NullPointerException("name");
91          }
92          if (value == null) {
93              throw new NullPointerException("value");
94          }
95          params.add(new Param(name, value));
96      }
97  
98      /**
99       * Returns the URL-encoded URI object which was created from the path string
100      * specified in the constructor and the parameters added by
101      * {@link #addParam(String, String)} method.
102      */
103     public URI toUri() throws URISyntaxException {
104         return new URI(toString());
105     }
106 
107     /**
108      * Returns the URL-encoded URI which was created from the path string
109      * specified in the constructor and the parameters added by
110      * {@link #addParam(String, String)} method.
111      */
112     @Override
113     public String toString() {
114         if (params.isEmpty()) {
115             return uri;
116         } else {
117             StringBuilder sb = new StringBuilder(uri).append("?");
118             for (int i = 0; i < params.size(); i++) {
119                 Param param = params.get(i);
120                 sb.append(encodeComponent(param.name, charset));
121                 sb.append("=");
122                 sb.append(encodeComponent(param.value, charset));
123                 if (i != params.size() - 1) {
124                     sb.append("&");
125                 }
126             }
127             return sb.toString();
128         }
129     }
130 
131     private static String encodeComponent(String s, Charset charset) {
132         try {
133             return URLEncoder.encode(s, charset.name()).replaceAll("\\+", "%20");
134         } catch (UnsupportedEncodingException e) {
135             throw new UnsupportedCharsetException(charset.name());
136         }
137     }
138 
139     private static final class Param {
140 
141         final String name;
142         final String value;
143 
144         Param(String name, String value) {
145             this.value = value;
146             this.name = name;
147         }
148     }
149 }