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.http;
    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: 2122 $, $Date: 2010-02-02 11:00:04 +0900 (Tue, 02 Feb 2010) $
    41   *
    42   * @see QueryStringDecoder
    43   *
    44   * @apiviz.stereotype utility
    45   * @apiviz.has        org.jboss.netty.handler.codec.http.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 }