Home | History | Annotate | Download | only in message
      1 /*
      2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderValueFormatter.java $
      3  * $Revision: 574185 $
      4  * $Date: 2007-09-10 02:19:47 -0700 (Mon, 10 Sep 2007) $
      5  *
      6  * ====================================================================
      7  * Licensed to the Apache Software Foundation (ASF) under one
      8  * or more contributor license agreements.  See the NOTICE file
      9  * distributed with this work for additional information
     10  * regarding copyright ownership.  The ASF licenses this file
     11  * to you under the Apache License, Version 2.0 (the
     12  * "License"); you may not use this file except in compliance
     13  * with the License.  You may obtain a copy of the License at
     14  *
     15  *   http://www.apache.org/licenses/LICENSE-2.0
     16  *
     17  * Unless required by applicable law or agreed to in writing,
     18  * software distributed under the License is distributed on an
     19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     20  * KIND, either express or implied.  See the License for the
     21  * specific language governing permissions and limitations
     22  * under the License.
     23  * ====================================================================
     24  *
     25  * This software consists of voluntary contributions made by many
     26  * individuals on behalf of the Apache Software Foundation.  For more
     27  * information on the Apache Software Foundation, please see
     28  * <http://www.apache.org/>.
     29  *
     30  */
     31 
     32 package org.apache.http.message;
     33 
     34 import org.apache.http.HeaderElement;
     35 import org.apache.http.NameValuePair;
     36 import org.apache.http.util.CharArrayBuffer;
     37 
     38 
     39 /**
     40  * Basic implementation for formatting header value elements.
     41  * Instances of this class are stateless and thread-safe.
     42  * Derived classes are expected to maintain these properties.
     43  *
     44  * @author <a href="mailto:oleg at ural.com">Oleg Kalnichevski</a>
     45  * @author and others
     46  *
     47  *
     48  * <!-- empty lines above to avoid 'svn diff' context problems -->
     49  * @version $Revision: 574185 $
     50  *
     51  * @since 4.0
     52  *
     53  * @deprecated Please use {@link java.net.URL#openConnection} instead.
     54  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
     55  *     for further details.
     56  */
     57 @Deprecated
     58 public class BasicHeaderValueFormatter implements HeaderValueFormatter {
     59 
     60     /**
     61      * A default instance of this class, for use as default or fallback.
     62      * Note that {@link BasicHeaderValueFormatter} is not a singleton, there
     63      * can be many instances of the class itself and of derived classes.
     64      * The instance here provides non-customized, default behavior.
     65      */
     66     public final static
     67         BasicHeaderValueFormatter DEFAULT = new BasicHeaderValueFormatter();
     68 
     69 
     70     /**
     71      * Special characters that can be used as separators in HTTP parameters.
     72      * These special characters MUST be in a quoted string to be used within
     73      * a parameter value .
     74      */
     75     public final static String SEPARATORS = " ;,:@()<>\\\"/[]?={}\t";
     76 
     77 
     78     /**
     79      * Unsafe special characters that must be escaped using the backslash
     80      * character
     81      */
     82     public final static String UNSAFE_CHARS = "\"\\";
     83 
     84 
     85 
     86     // public default constructor
     87 
     88 
     89 
     90     /**
     91      * Formats an array of header elements.
     92      *
     93      * @param elems     the header elements to format
     94      * @param quote     <code>true</code> to always format with quoted values,
     95      *                  <code>false</code> to use quotes only when necessary
     96      * @param formatter         the formatter to use, or <code>null</code>
     97      *                          for the {@link #DEFAULT default}
     98      *
     99      * @return  the formatted header elements
    100      */
    101     public final static
    102         String formatElements(final HeaderElement[] elems,
    103                               final boolean quote,
    104                               HeaderValueFormatter formatter) {
    105         if (formatter == null)
    106             formatter = BasicHeaderValueFormatter.DEFAULT;
    107         return formatter.formatElements(null, elems, quote).toString();
    108     }
    109 
    110 
    111     // non-javadoc, see interface HeaderValueFormatter
    112     public CharArrayBuffer formatElements(CharArrayBuffer buffer,
    113                                           final HeaderElement[] elems,
    114                                           final boolean quote) {
    115         if (elems == null) {
    116             throw new IllegalArgumentException
    117                 ("Header element array must not be null.");
    118         }
    119 
    120         int len = estimateElementsLen(elems);
    121         if (buffer == null) {
    122             buffer = new CharArrayBuffer(len);
    123         } else {
    124             buffer.ensureCapacity(len);
    125         }
    126 
    127         for (int i=0; i<elems.length; i++) {
    128             if (i > 0) {
    129                 buffer.append(", ");
    130             }
    131             formatHeaderElement(buffer, elems[i], quote);
    132         }
    133 
    134         return buffer;
    135     }
    136 
    137 
    138     /**
    139      * Estimates the length of formatted header elements.
    140      *
    141      * @param elems     the header elements to format, or <code>null</code>
    142      *
    143      * @return  a length estimate, in number of characters
    144      */
    145     protected int estimateElementsLen(final HeaderElement[] elems) {
    146         if ((elems == null) || (elems.length < 1))
    147             return 0;
    148 
    149         int result = (elems.length-1) * 2; // elements separated by ", "
    150         for (int i=0; i<elems.length; i++) {
    151             result += estimateHeaderElementLen(elems[i]);
    152         }
    153 
    154         return result;
    155     }
    156 
    157 
    158 
    159     /**
    160      * Formats a header element.
    161      *
    162      * @param elem      the header element to format
    163      * @param quote     <code>true</code> to always format with quoted values,
    164      *                  <code>false</code> to use quotes only when necessary
    165      * @param formatter         the formatter to use, or <code>null</code>
    166      *                          for the {@link #DEFAULT default}
    167      *
    168      * @return  the formatted header element
    169      */
    170     public final static
    171         String formatHeaderElement(final HeaderElement elem,
    172                                    boolean quote,
    173                                    HeaderValueFormatter formatter) {
    174         if (formatter == null)
    175             formatter = BasicHeaderValueFormatter.DEFAULT;
    176         return formatter.formatHeaderElement(null, elem, quote).toString();
    177     }
    178 
    179 
    180     // non-javadoc, see interface HeaderValueFormatter
    181     public CharArrayBuffer formatHeaderElement(CharArrayBuffer buffer,
    182                                                final HeaderElement elem,
    183                                                final boolean quote) {
    184         if (elem == null) {
    185             throw new IllegalArgumentException
    186                 ("Header element must not be null.");
    187         }
    188 
    189         int len = estimateHeaderElementLen(elem);
    190         if (buffer == null) {
    191             buffer = new CharArrayBuffer(len);
    192         } else {
    193             buffer.ensureCapacity(len);
    194         }
    195 
    196         buffer.append(elem.getName());
    197         final String value = elem.getValue();
    198         if (value != null) {
    199             buffer.append('=');
    200             doFormatValue(buffer, value, quote);
    201         }
    202 
    203         final int parcnt = elem.getParameterCount();
    204         if (parcnt > 0) {
    205             for (int i=0; i<parcnt; i++) {
    206                 buffer.append("; ");
    207                 formatNameValuePair(buffer, elem.getParameter(i), quote);
    208             }
    209         }
    210 
    211         return buffer;
    212     }
    213 
    214 
    215     /**
    216      * Estimates the length of a formatted header element.
    217      *
    218      * @param elem      the header element to format, or <code>null</code>
    219      *
    220      * @return  a length estimate, in number of characters
    221      */
    222     protected int estimateHeaderElementLen(final HeaderElement elem) {
    223         if (elem == null)
    224             return 0;
    225 
    226         int result = elem.getName().length(); // name
    227         final String value = elem.getValue();
    228         if (value != null) {
    229             // assume quotes, but no escaped characters
    230             result += 3 + value.length(); // ="value"
    231         }
    232 
    233         final int parcnt = elem.getParameterCount();
    234         if (parcnt > 0) {
    235             for (int i=0; i<parcnt; i++) {
    236                 result += 2 +                   // ; <param>
    237                     estimateNameValuePairLen(elem.getParameter(i));
    238             }
    239         }
    240 
    241         return result;
    242     }
    243 
    244 
    245 
    246 
    247     /**
    248      * Formats a set of parameters.
    249      *
    250      * @param nvps      the parameters to format
    251      * @param quote     <code>true</code> to always format with quoted values,
    252      *                  <code>false</code> to use quotes only when necessary
    253      * @param formatter         the formatter to use, or <code>null</code>
    254      *                          for the {@link #DEFAULT default}
    255      *
    256      * @return  the formatted parameters
    257      */
    258     public final static
    259         String formatParameters(final NameValuePair[] nvps,
    260                                 final boolean quote,
    261                                 HeaderValueFormatter formatter) {
    262         if (formatter == null)
    263             formatter = BasicHeaderValueFormatter.DEFAULT;
    264         return formatter.formatParameters(null, nvps, quote).toString();
    265     }
    266 
    267 
    268     // non-javadoc, see interface HeaderValueFormatter
    269     public CharArrayBuffer formatParameters(CharArrayBuffer buffer,
    270                                             NameValuePair[] nvps,
    271                                             boolean quote) {
    272         if (nvps == null) {
    273             throw new IllegalArgumentException
    274                 ("Parameters must not be null.");
    275         }
    276 
    277         int len = estimateParametersLen(nvps);
    278         if (buffer == null) {
    279             buffer = new CharArrayBuffer(len);
    280         } else {
    281             buffer.ensureCapacity(len);
    282         }
    283 
    284         for (int i = 0; i < nvps.length; i++) {
    285             if (i > 0) {
    286                 buffer.append("; ");
    287             }
    288             formatNameValuePair(buffer, nvps[i], quote);
    289         }
    290 
    291         return buffer;
    292     }
    293 
    294 
    295     /**
    296      * Estimates the length of formatted parameters.
    297      *
    298      * @param nvps      the parameters to format, or <code>null</code>
    299      *
    300      * @return  a length estimate, in number of characters
    301      */
    302     protected int estimateParametersLen(final NameValuePair[] nvps) {
    303         if ((nvps == null) || (nvps.length < 1))
    304             return 0;
    305 
    306         int result = (nvps.length-1) * 2; // "; " between the parameters
    307         for (int i=0; i<nvps.length; i++) {
    308             result += estimateNameValuePairLen(nvps[i]);
    309         }
    310 
    311         return result;
    312     }
    313 
    314 
    315     /**
    316      * Formats a name-value pair.
    317      *
    318      * @param nvp       the name-value pair to format
    319      * @param quote     <code>true</code> to always format with a quoted value,
    320      *                  <code>false</code> to use quotes only when necessary
    321      * @param formatter         the formatter to use, or <code>null</code>
    322      *                          for the {@link #DEFAULT default}
    323      *
    324      * @return  the formatted name-value pair
    325      */
    326     public final static
    327         String formatNameValuePair(final NameValuePair nvp,
    328                                    final boolean quote,
    329                                    HeaderValueFormatter formatter) {
    330         if (formatter == null)
    331             formatter = BasicHeaderValueFormatter.DEFAULT;
    332         return formatter.formatNameValuePair(null, nvp, quote).toString();
    333     }
    334 
    335 
    336     // non-javadoc, see interface HeaderValueFormatter
    337     public CharArrayBuffer formatNameValuePair(CharArrayBuffer buffer,
    338                                                final NameValuePair nvp,
    339                                                final boolean quote) {
    340         if (nvp == null) {
    341             throw new IllegalArgumentException
    342                 ("NameValuePair must not be null.");
    343         }
    344 
    345         int len = estimateNameValuePairLen(nvp);
    346         if (buffer == null) {
    347             buffer = new CharArrayBuffer(len);
    348         } else {
    349             buffer.ensureCapacity(len);
    350         }
    351 
    352         buffer.append(nvp.getName());
    353         final String value = nvp.getValue();
    354         if (value != null) {
    355             buffer.append('=');
    356             doFormatValue(buffer, value, quote);
    357         }
    358 
    359         return buffer;
    360     }
    361 
    362 
    363     /**
    364      * Estimates the length of a formatted name-value pair.
    365      *
    366      * @param nvp       the name-value pair to format, or <code>null</code>
    367      *
    368      * @return  a length estimate, in number of characters
    369      */
    370     protected int estimateNameValuePairLen(final NameValuePair nvp) {
    371         if (nvp == null)
    372             return 0;
    373 
    374         int result = nvp.getName().length(); // name
    375         final String value = nvp.getValue();
    376         if (value != null) {
    377             // assume quotes, but no escaped characters
    378             result += 3 + value.length(); // ="value"
    379         }
    380         return result;
    381     }
    382 
    383 
    384     /**
    385      * Actually formats the value of a name-value pair.
    386      * This does not include a leading = character.
    387      * Called from {@link #formatNameValuePair formatNameValuePair}.
    388      *
    389      * @param buffer    the buffer to append to, never <code>null</code>
    390      * @param value     the value to append, never <code>null</code>
    391      * @param quote     <code>true</code> to always format with quotes,
    392      *                  <code>false</code> to use quotes only when necessary
    393      */
    394     protected void doFormatValue(final CharArrayBuffer buffer,
    395                                  final String value,
    396                                  boolean quote) {
    397 
    398         if (!quote) {
    399             for (int i = 0; (i < value.length()) && !quote; i++) {
    400                 quote = isSeparator(value.charAt(i));
    401             }
    402         }
    403 
    404         if (quote) {
    405             buffer.append('"');
    406         }
    407         for (int i = 0; i < value.length(); i++) {
    408             char ch = value.charAt(i);
    409             if (isUnsafe(ch)) {
    410                 buffer.append('\\');
    411             }
    412             buffer.append(ch);
    413         }
    414         if (quote) {
    415             buffer.append('"');
    416         }
    417     }
    418 
    419 
    420     /**
    421      * Checks whether a character is a {@link #SEPARATORS separator}.
    422      *
    423      * @param ch        the character to check
    424      *
    425      * @return  <code>true</code> if the character is a separator,
    426      *          <code>false</code> otherwise
    427      */
    428     protected boolean isSeparator(char ch) {
    429         return SEPARATORS.indexOf(ch) >= 0;
    430     }
    431 
    432 
    433     /**
    434      * Checks whether a character is {@link #UNSAFE_CHARS unsafe}.
    435      *
    436      * @param ch        the character to check
    437      *
    438      * @return  <code>true</code> if the character is unsafe,
    439      *          <code>false</code> otherwise
    440      */
    441     protected boolean isUnsafe(char ch) {
    442         return UNSAFE_CHARS.indexOf(ch) >= 0;
    443     }
    444 
    445 
    446 } // class BasicHeaderValueFormatter
    447