View Javadoc

1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.http.message;
29  
30  import org.apache.http.FormattedHeader;
31  import org.apache.http.Header;
32  import org.apache.http.ProtocolVersion;
33  import org.apache.http.RequestLine;
34  import org.apache.http.StatusLine;
35  import org.apache.http.annotation.Immutable;
36  import org.apache.http.util.Args;
37  import org.apache.http.util.CharArrayBuffer;
38  
39  /**
40   * Interface for formatting elements of the HEAD section of an HTTP message.
41   * This is the complement to {@link LineParser}.
42   * There are individual methods for formatting a request line, a
43   * status line, or a header line. The formatting does <i>not</i> include the
44   * trailing line break sequence CR-LF.
45   * The formatted lines are returned in memory, the formatter does not depend
46   * on any specific IO mechanism.
47   * Instances of this interface are expected to be stateless and thread-safe.
48   *
49   * @since 4.0
50   */
51  @Immutable
52  public class BasicLineFormatter implements LineFormatter {
53  
54      /**
55       * A default instance of this class, for use as default or fallback.
56       * Note that {@link BasicLineFormatter} is not a singleton, there can
57       * be many instances of the class itself and of derived classes.
58       * The instance here provides non-customized, default behavior.
59       *
60       * @deprecated (4.3) use {@link #INSTANCE}
61       */
62      @Deprecated
63      public final static BasicLineFormatter DEFAULT = new BasicLineFormatter();
64  
65      public final static BasicLineFormatter INSTANCE = new BasicLineFormatter();
66  
67      public BasicLineFormatter() {
68          super();
69      }
70  
71      /**
72       * Obtains a buffer for formatting.
73       *
74       * @param charBuffer a buffer already available, or <code>null</code>
75       *
76       * @return  the cleared argument buffer if there is one, or
77       *          a new empty buffer that can be used for formatting
78       */
79      protected CharArrayBuffer initBuffer(final CharArrayBuffer charBuffer) {
80          CharArrayBuffer buffer = charBuffer;
81          if (buffer != null) {
82              buffer.clear();
83          } else {
84              buffer = new CharArrayBuffer(64);
85          }
86          return buffer;
87      }
88  
89  
90      /**
91       * Formats a protocol version.
92       *
93       * @param version           the protocol version to format
94       * @param formatter         the formatter to use, or
95       *                          <code>null</code> for the
96       *                          {@link #INSTANCE default}
97       *
98       * @return  the formatted protocol version
99       */
100     public static
101         String formatProtocolVersion(final ProtocolVersion version,
102                                      final LineFormatter formatter) {
103         return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
104                 .appendProtocolVersion(null, version).toString();
105     }
106 
107 
108     // non-javadoc, see interface LineFormatter
109     public CharArrayBuffer appendProtocolVersion(final CharArrayBuffer buffer,
110                                                  final ProtocolVersion version) {
111         Args.notNull(version, "Protocol version");
112         // can't use initBuffer, that would clear the argument!
113         CharArrayBuffer result = buffer;
114         final int len = estimateProtocolVersionLen(version);
115         if (result == null) {
116             result = new CharArrayBuffer(len);
117         } else {
118             result.ensureCapacity(len);
119         }
120 
121         result.append(version.getProtocol());
122         result.append('/');
123         result.append(Integer.toString(version.getMajor()));
124         result.append('.');
125         result.append(Integer.toString(version.getMinor()));
126 
127         return result;
128     }
129 
130 
131     /**
132      * Guesses the length of a formatted protocol version.
133      * Needed to guess the length of a formatted request or status line.
134      *
135      * @param version   the protocol version to format, or <code>null</code>
136      *
137      * @return  the estimated length of the formatted protocol version,
138      *          in characters
139      */
140     protected int estimateProtocolVersionLen(final ProtocolVersion version) {
141         return version.getProtocol().length() + 4; // room for "HTTP/1.1"
142     }
143 
144 
145     /**
146      * Formats a request line.
147      *
148      * @param reqline           the request line to format
149      * @param formatter         the formatter to use, or
150      *                          <code>null</code> for the
151      *                          {@link #INSTANCE default}
152      *
153      * @return  the formatted request line
154      */
155     public static String formatRequestLine(final RequestLine reqline,
156                                            final LineFormatter formatter) {
157         return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
158                 .formatRequestLine(null, reqline).toString();
159     }
160 
161 
162     // non-javadoc, see interface LineFormatter
163     public CharArrayBuffer formatRequestLine(final CharArrayBuffer buffer,
164                                              final RequestLine reqline) {
165         Args.notNull(reqline, "Request line");
166         final CharArrayBuffer result = initBuffer(buffer);
167         doFormatRequestLine(result, reqline);
168 
169         return result;
170     }
171 
172 
173     /**
174      * Actually formats a request line.
175      * Called from {@link #formatRequestLine}.
176      *
177      * @param buffer    the empty buffer into which to format,
178      *                  never <code>null</code>
179      * @param reqline   the request line to format, never <code>null</code>
180      */
181     protected void doFormatRequestLine(final CharArrayBuffer buffer,
182                                        final RequestLine reqline) {
183         final String method = reqline.getMethod();
184         final String uri    = reqline.getUri();
185 
186         // room for "GET /index.html HTTP/1.1"
187         final int len = method.length() + 1 + uri.length() + 1 +
188             estimateProtocolVersionLen(reqline.getProtocolVersion());
189         buffer.ensureCapacity(len);
190 
191         buffer.append(method);
192         buffer.append(' ');
193         buffer.append(uri);
194         buffer.append(' ');
195         appendProtocolVersion(buffer, reqline.getProtocolVersion());
196     }
197 
198 
199 
200     /**
201      * Formats a status line.
202      *
203      * @param statline          the status line to format
204      * @param formatter         the formatter to use, or
205      *                          <code>null</code> for the
206      *                          {@link #INSTANCE default}
207      *
208      * @return  the formatted status line
209      */
210     public static String formatStatusLine(final StatusLine statline,
211                                           final LineFormatter formatter) {
212         return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
213                 .formatStatusLine(null, statline).toString();
214     }
215 
216 
217     // non-javadoc, see interface LineFormatter
218     public CharArrayBuffer formatStatusLine(final CharArrayBuffer buffer,
219                                             final StatusLine statline) {
220         Args.notNull(statline, "Status line");
221         final CharArrayBuffer result = initBuffer(buffer);
222         doFormatStatusLine(result, statline);
223 
224         return result;
225     }
226 
227 
228     /**
229      * Actually formats a status line.
230      * Called from {@link #formatStatusLine}.
231      *
232      * @param buffer    the empty buffer into which to format,
233      *                  never <code>null</code>
234      * @param statline  the status line to format, never <code>null</code>
235      */
236     protected void doFormatStatusLine(final CharArrayBuffer buffer,
237                                       final StatusLine statline) {
238 
239         int len = estimateProtocolVersionLen(statline.getProtocolVersion())
240             + 1 + 3 + 1; // room for "HTTP/1.1 200 "
241         final String reason = statline.getReasonPhrase();
242         if (reason != null) {
243             len += reason.length();
244         }
245         buffer.ensureCapacity(len);
246 
247         appendProtocolVersion(buffer, statline.getProtocolVersion());
248         buffer.append(' ');
249         buffer.append(Integer.toString(statline.getStatusCode()));
250         buffer.append(' '); // keep whitespace even if reason phrase is empty
251         if (reason != null) {
252             buffer.append(reason);
253         }
254     }
255 
256 
257     /**
258      * Formats a header.
259      *
260      * @param header            the header to format
261      * @param formatter         the formatter to use, or
262      *                          <code>null</code> for the
263      *                          {@link #INSTANCE default}
264      *
265      * @return  the formatted header
266      */
267     public static String formatHeader(final Header header,
268                                       final LineFormatter formatter) {
269         return (formatter != null ? formatter : BasicLineFormatter.INSTANCE)
270                 .formatHeader(null, header).toString();
271     }
272 
273 
274     // non-javadoc, see interface LineFormatter
275     public CharArrayBuffer formatHeader(final CharArrayBuffer buffer,
276                                         final Header header) {
277         Args.notNull(header, "Header");
278         final CharArrayBuffer result;
279 
280         if (header instanceof FormattedHeader) {
281             // If the header is backed by a buffer, re-use the buffer
282             result = ((FormattedHeader)header).getBuffer();
283         } else {
284             result = initBuffer(buffer);
285             doFormatHeader(result, header);
286         }
287         return result;
288 
289     } // formatHeader
290 
291 
292     /**
293      * Actually formats a header.
294      * Called from {@link #formatHeader}.
295      *
296      * @param buffer    the empty buffer into which to format,
297      *                  never <code>null</code>
298      * @param header    the header to format, never <code>null</code>
299      */
300     protected void doFormatHeader(final CharArrayBuffer buffer,
301                                   final Header header) {
302         final String name = header.getName();
303         final String value = header.getValue();
304 
305         int len = name.length() + 2;
306         if (value != null) {
307             len += value.length();
308         }
309         buffer.ensureCapacity(len);
310 
311         buffer.append(name);
312         buffer.append(": ");
313         if (value != null) {
314             buffer.append(value);
315         }
316     }
317 
318 
319 } // class BasicLineFormatter