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 buffer    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(CharArrayBuffer buffer) {
80          if (buffer != null) {
81              buffer.clear();
82          } else {
83              buffer = new CharArrayBuffer(64);
84          }
85          return buffer;
86      }
87  
88  
89      /**
90       * Formats a protocol version.
91       *
92       * @param version           the protocol version to format
93       * @param formatter         the formatter to use, or
94       *                          <code>null</code> for the
95       *                          {@link #INSTANCE default}
96       *
97       * @return  the formatted protocol version
98       */
99      public final static
100         String formatProtocolVersion(final ProtocolVersion version,
101                                      LineFormatter formatter) {
102         if (formatter == null) {
103             formatter = BasicLineFormatter.INSTANCE;
104         }
105         return formatter.appendProtocolVersion(null, version).toString();
106     }
107 
108 
109     // non-javadoc, see interface LineFormatter
110     public CharArrayBuffer appendProtocolVersion(final CharArrayBuffer buffer,
111                                                  final ProtocolVersion version) {
112         Args.notNull(version, "Protocol version");
113         // can't use initBuffer, that would clear the argument!
114         CharArrayBuffer result = buffer;
115         final int len = estimateProtocolVersionLen(version);
116         if (result == null) {
117             result = new CharArrayBuffer(len);
118         } else {
119             result.ensureCapacity(len);
120         }
121 
122         result.append(version.getProtocol());
123         result.append('/');
124         result.append(Integer.toString(version.getMajor()));
125         result.append('.');
126         result.append(Integer.toString(version.getMinor()));
127 
128         return result;
129     }
130 
131 
132     /**
133      * Guesses the length of a formatted protocol version.
134      * Needed to guess the length of a formatted request or status line.
135      *
136      * @param version   the protocol version to format, or <code>null</code>
137      *
138      * @return  the estimated length of the formatted protocol version,
139      *          in characters
140      */
141     protected int estimateProtocolVersionLen(final ProtocolVersion version) {
142         return version.getProtocol().length() + 4; // room for "HTTP/1.1"
143     }
144 
145 
146     /**
147      * Formats a request line.
148      *
149      * @param reqline           the request line to format
150      * @param formatter         the formatter to use, or
151      *                          <code>null</code> for the
152      *                          {@link #INSTANCE default}
153      *
154      * @return  the formatted request line
155      */
156     public final static String formatRequestLine(final RequestLine reqline,
157                                                  LineFormatter formatter) {
158         if (formatter == null) {
159             formatter = BasicLineFormatter.INSTANCE;
160         }
161         return formatter.formatRequestLine(null, reqline).toString();
162     }
163 
164 
165     // non-javadoc, see interface LineFormatter
166     public CharArrayBuffer formatRequestLine(final CharArrayBuffer buffer,
167                                              final RequestLine reqline) {
168         Args.notNull(reqline, "Request line");
169         final CharArrayBuffer result = initBuffer(buffer);
170         doFormatRequestLine(result, reqline);
171 
172         return result;
173     }
174 
175 
176     /**
177      * Actually formats a request line.
178      * Called from {@link #formatRequestLine}.
179      *
180      * @param buffer    the empty buffer into which to format,
181      *                  never <code>null</code>
182      * @param reqline   the request line to format, never <code>null</code>
183      */
184     protected void doFormatRequestLine(final CharArrayBuffer buffer,
185                                        final RequestLine reqline) {
186         final String method = reqline.getMethod();
187         final String uri    = reqline.getUri();
188 
189         // room for "GET /index.html HTTP/1.1"
190         final int len = method.length() + 1 + uri.length() + 1 +
191             estimateProtocolVersionLen(reqline.getProtocolVersion());
192         buffer.ensureCapacity(len);
193 
194         buffer.append(method);
195         buffer.append(' ');
196         buffer.append(uri);
197         buffer.append(' ');
198         appendProtocolVersion(buffer, reqline.getProtocolVersion());
199     }
200 
201 
202 
203     /**
204      * Formats a status line.
205      *
206      * @param statline          the status line to format
207      * @param formatter         the formatter to use, or
208      *                          <code>null</code> for the
209      *                          {@link #INSTANCE default}
210      *
211      * @return  the formatted status line
212      */
213     public final static String formatStatusLine(final StatusLine statline,
214                                                 LineFormatter formatter) {
215         if (formatter == null) {
216             formatter = BasicLineFormatter.INSTANCE;
217         }
218         return formatter.formatStatusLine(null, statline).toString();
219     }
220 
221 
222     // non-javadoc, see interface LineFormatter
223     public CharArrayBuffer formatStatusLine(final CharArrayBuffer buffer,
224                                             final StatusLine statline) {
225         Args.notNull(statline, "Status line");
226         final CharArrayBuffer result = initBuffer(buffer);
227         doFormatStatusLine(result, statline);
228 
229         return result;
230     }
231 
232 
233     /**
234      * Actually formats a status line.
235      * Called from {@link #formatStatusLine}.
236      *
237      * @param buffer    the empty buffer into which to format,
238      *                  never <code>null</code>
239      * @param statline  the status line to format, never <code>null</code>
240      */
241     protected void doFormatStatusLine(final CharArrayBuffer buffer,
242                                       final StatusLine statline) {
243 
244         int len = estimateProtocolVersionLen(statline.getProtocolVersion())
245             + 1 + 3 + 1; // room for "HTTP/1.1 200 "
246         final String reason = statline.getReasonPhrase();
247         if (reason != null) {
248             len += reason.length();
249         }
250         buffer.ensureCapacity(len);
251 
252         appendProtocolVersion(buffer, statline.getProtocolVersion());
253         buffer.append(' ');
254         buffer.append(Integer.toString(statline.getStatusCode()));
255         buffer.append(' '); // keep whitespace even if reason phrase is empty
256         if (reason != null) {
257             buffer.append(reason);
258         }
259     }
260 
261 
262     /**
263      * Formats a header.
264      *
265      * @param header            the header to format
266      * @param formatter         the formatter to use, or
267      *                          <code>null</code> for the
268      *                          {@link #INSTANCE default}
269      *
270      * @return  the formatted header
271      */
272     public final static String formatHeader(final Header header,
273                                             LineFormatter formatter) {
274         if (formatter == null) {
275             formatter = BasicLineFormatter.INSTANCE;
276         }
277         return formatter.formatHeader(null, header).toString();
278     }
279 
280 
281     // non-javadoc, see interface LineFormatter
282     public CharArrayBuffer formatHeader(final CharArrayBuffer buffer,
283                                         final Header header) {
284         Args.notNull(header, "Header");
285         CharArrayBuffer result = null;
286 
287         if (header instanceof FormattedHeader) {
288             // If the header is backed by a buffer, re-use the buffer
289             result = ((FormattedHeader)header).getBuffer();
290         } else {
291             result = initBuffer(buffer);
292             doFormatHeader(result, header);
293         }
294         return result;
295 
296     } // formatHeader
297 
298 
299     /**
300      * Actually formats a header.
301      * Called from {@link #formatHeader}.
302      *
303      * @param buffer    the empty buffer into which to format,
304      *                  never <code>null</code>
305      * @param header    the header to format, never <code>null</code>
306      */
307     protected void doFormatHeader(final CharArrayBuffer buffer,
308                                   final Header header) {
309         final String name = header.getName();
310         final String value = header.getValue();
311 
312         int len = name.length() + 2;
313         if (value != null) {
314             len += value.length();
315         }
316         buffer.ensureCapacity(len);
317 
318         buffer.append(name);
319         buffer.append(": ");
320         if (value != null) {
321             buffer.append(value);
322         }
323     }
324 
325 
326 } // class BasicLineFormatter