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/BasicLineFormatter.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 
     35 import org.apache.http.ProtocolVersion;
     36 import org.apache.http.RequestLine;
     37 import org.apache.http.StatusLine;
     38 import org.apache.http.Header;
     39 import org.apache.http.FormattedHeader;
     40 import org.apache.http.util.CharArrayBuffer;
     41 
     42 
     43 /**
     44  * Interface for formatting elements of the HEAD section of an HTTP message.
     45  * This is the complement to {@link LineParser}.
     46  * There are individual methods for formatting a request line, a
     47  * status line, or a header line. The formatting does <i>not</i> include the
     48  * trailing line break sequence CR-LF.
     49  * The formatted lines are returned in memory, the formatter does not depend
     50  * on any specific IO mechanism.
     51  * Instances of this interface are expected to be stateless and thread-safe.
     52  *
     53  * @author <a href="mailto:remm (at) apache.org">Remy Maucherat</a>
     54  * @author <a href="mailto:mbowler (at) GargoyleSoftware.com">Mike Bowler</a>
     55  * @author <a href="mailto:jsdever (at) apache.org">Jeff Dever</a>
     56  * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
     57  * @author and others
     58  *
     59  *
     60  * <!-- empty lines above to avoid 'svn diff' context problems -->
     61  * @version $Revision: 574185 $
     62  *
     63  * @since 4.0
     64  */
     65 public class BasicLineFormatter implements LineFormatter {
     66 
     67     /**
     68      * A default instance of this class, for use as default or fallback.
     69      * Note that {@link BasicLineFormatter} is not a singleton, there can
     70      * be many instances of the class itself and of derived classes.
     71      * The instance here provides non-customized, default behavior.
     72      */
     73     public final static BasicLineFormatter DEFAULT = new BasicLineFormatter();
     74 
     75 
     76 
     77     // public default constructor
     78 
     79 
     80     /**
     81      * Obtains a buffer for formatting.
     82      *
     83      * @param buffer    a buffer already available, or <code>null</code>
     84      *
     85      * @return  the cleared argument buffer if there is one, or
     86      *          a new empty buffer that can be used for formatting
     87      */
     88     protected CharArrayBuffer initBuffer(CharArrayBuffer buffer) {
     89         if (buffer != null) {
     90             buffer.clear();
     91         } else {
     92             buffer = new CharArrayBuffer(64);
     93         }
     94         return buffer;
     95     }
     96 
     97 
     98     /**
     99      * Formats a protocol version.
    100      *
    101      * @param version           the protocol version to format
    102      * @param formatter         the formatter to use, or
    103      *                          <code>null</code> for the
    104      *                          {@link #DEFAULT default}
    105      *
    106      * @return  the formatted protocol version
    107      */
    108     public final static
    109         String formatProtocolVersion(final ProtocolVersion version,
    110                                      LineFormatter formatter) {
    111         if (formatter == null)
    112             formatter = BasicLineFormatter.DEFAULT;
    113         return formatter.appendProtocolVersion(null, version).toString();
    114     }
    115 
    116 
    117     // non-javadoc, see interface LineFormatter
    118     public CharArrayBuffer appendProtocolVersion(final CharArrayBuffer buffer,
    119                                                  final ProtocolVersion version) {
    120         if (version == null) {
    121             throw new IllegalArgumentException
    122                 ("Protocol version may not be null");
    123         }
    124 
    125         // can't use initBuffer, that would clear the argument!
    126         CharArrayBuffer result = buffer;
    127         final int len = estimateProtocolVersionLen(version);
    128         if (result == null) {
    129             result = new CharArrayBuffer(len);
    130         } else {
    131             result.ensureCapacity(len);
    132         }
    133 
    134         result.append(version.getProtocol());
    135         result.append('/');
    136         result.append(Integer.toString(version.getMajor()));
    137         result.append('.');
    138         result.append(Integer.toString(version.getMinor()));
    139 
    140         return result;
    141     }
    142 
    143 
    144     /**
    145      * Guesses the length of a formatted protocol version.
    146      * Needed to guess the length of a formatted request or status line.
    147      *
    148      * @param version   the protocol version to format, or <code>null</code>
    149      *
    150      * @return  the estimated length of the formatted protocol version,
    151      *          in characters
    152      */
    153     protected int estimateProtocolVersionLen(final ProtocolVersion version) {
    154         return version.getProtocol().length() + 4; // room for "HTTP/1.1"
    155     }
    156 
    157 
    158     /**
    159      * Formats a request line.
    160      *
    161      * @param reqline           the request line to format
    162      * @param formatter         the formatter to use, or
    163      *                          <code>null</code> for the
    164      *                          {@link #DEFAULT default}
    165      *
    166      * @return  the formatted request line
    167      */
    168     public final static String formatRequestLine(final RequestLine reqline,
    169                                                  LineFormatter formatter) {
    170         if (formatter == null)
    171             formatter = BasicLineFormatter.DEFAULT;
    172         return formatter.formatRequestLine(null, reqline).toString();
    173     }
    174 
    175 
    176     // non-javadoc, see interface LineFormatter
    177     public CharArrayBuffer formatRequestLine(CharArrayBuffer buffer,
    178                                              RequestLine reqline) {
    179         if (reqline == null) {
    180             throw new IllegalArgumentException
    181                 ("Request line may not be null");
    182         }
    183 
    184         CharArrayBuffer result = initBuffer(buffer);
    185         doFormatRequestLine(result, reqline);
    186 
    187         return result;
    188     }
    189 
    190 
    191     /**
    192      * Actually formats a request line.
    193      * Called from {@link #formatRequestLine}.
    194      *
    195      * @param buffer    the empty buffer into which to format,
    196      *                  never <code>null</code>
    197      * @param reqline   the request line to format, never <code>null</code>
    198      */
    199     protected void doFormatRequestLine(final CharArrayBuffer buffer,
    200                                        final RequestLine reqline) {
    201         final String method = reqline.getMethod();
    202         final String uri    = reqline.getUri();
    203 
    204         // room for "GET /index.html HTTP/1.1"
    205         int len = method.length() + 1 + uri.length() + 1 +
    206             estimateProtocolVersionLen(reqline.getProtocolVersion());
    207         buffer.ensureCapacity(len);
    208 
    209         buffer.append(method);
    210         buffer.append(' ');
    211         buffer.append(uri);
    212         buffer.append(' ');
    213         appendProtocolVersion(buffer, reqline.getProtocolVersion());
    214     }
    215 
    216 
    217 
    218     /**
    219      * Formats a status line.
    220      *
    221      * @param statline          the status line to format
    222      * @param formatter         the formatter to use, or
    223      *                          <code>null</code> for the
    224      *                          {@link #DEFAULT default}
    225      *
    226      * @return  the formatted status line
    227      */
    228     public final static String formatStatusLine(final StatusLine statline,
    229                                                 LineFormatter formatter) {
    230         if (formatter == null)
    231             formatter = BasicLineFormatter.DEFAULT;
    232         return formatter.formatStatusLine(null, statline).toString();
    233     }
    234 
    235 
    236     // non-javadoc, see interface LineFormatter
    237     public CharArrayBuffer formatStatusLine(final CharArrayBuffer buffer,
    238                                             final StatusLine statline) {
    239         if (statline == null) {
    240             throw new IllegalArgumentException
    241                 ("Status line may not be null");
    242         }
    243 
    244         CharArrayBuffer result = initBuffer(buffer);
    245         doFormatStatusLine(result, statline);
    246 
    247         return result;
    248     }
    249 
    250 
    251     /**
    252      * Actually formats a status line.
    253      * Called from {@link #formatStatusLine}.
    254      *
    255      * @param buffer    the empty buffer into which to format,
    256      *                  never <code>null</code>
    257      * @param statline  the status line to format, never <code>null</code>
    258      */
    259     protected void doFormatStatusLine(final CharArrayBuffer buffer,
    260                                       final StatusLine statline) {
    261 
    262         int len = estimateProtocolVersionLen(statline.getProtocolVersion())
    263             + 1 + 3 + 1; // room for "HTTP/1.1 200 "
    264         final String reason = statline.getReasonPhrase();
    265         if (reason != null) {
    266             len += reason.length();
    267         }
    268         buffer.ensureCapacity(len);
    269 
    270         appendProtocolVersion(buffer, statline.getProtocolVersion());
    271         buffer.append(' ');
    272         buffer.append(Integer.toString(statline.getStatusCode()));
    273         buffer.append(' '); // keep whitespace even if reason phrase is empty
    274         if (reason != null) {
    275             buffer.append(reason);
    276         }
    277     }
    278 
    279 
    280     /**
    281      * Formats a header.
    282      *
    283      * @param header            the header to format
    284      * @param formatter         the formatter to use, or
    285      *                          <code>null</code> for the
    286      *                          {@link #DEFAULT default}
    287      *
    288      * @return  the formatted header
    289      */
    290     public final static String formatHeader(final Header header,
    291                                             LineFormatter formatter) {
    292         if (formatter == null)
    293             formatter = BasicLineFormatter.DEFAULT;
    294         return formatter.formatHeader(null, header).toString();
    295     }
    296 
    297 
    298     // non-javadoc, see interface LineFormatter
    299     public CharArrayBuffer formatHeader(CharArrayBuffer buffer,
    300                                         Header header) {
    301         if (header == null) {
    302             throw new IllegalArgumentException
    303                 ("Header may not be null");
    304         }
    305         CharArrayBuffer result = null;
    306 
    307         if (header instanceof FormattedHeader) {
    308             // If the header is backed by a buffer, re-use the buffer
    309             result = ((FormattedHeader)header).getBuffer();
    310         } else {
    311             result = initBuffer(buffer);
    312             doFormatHeader(result, header);
    313         }
    314         return result;
    315 
    316     } // formatHeader
    317 
    318 
    319     /**
    320      * Actually formats a header.
    321      * Called from {@link #formatHeader}.
    322      *
    323      * @param buffer    the empty buffer into which to format,
    324      *                  never <code>null</code>
    325      * @param header    the header to format, never <code>null</code>
    326      */
    327     protected void doFormatHeader(final CharArrayBuffer buffer,
    328                                   final Header header) {
    329         final String name = header.getName();
    330         final String value = header.getValue();
    331 
    332         int len = name.length() + 2;
    333         if (value != null) {
    334             len += value.length();
    335         }
    336         buffer.ensureCapacity(len);
    337 
    338         buffer.append(name);
    339         buffer.append(": ");
    340         if (value != null) {
    341             buffer.append(value);
    342         }
    343     }
    344 
    345 
    346 } // class BasicLineFormatter
    347