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@apache.org">Remy Maucherat</a> 54 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> 55 * @author <a href="mailto:jsdever@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 */ initBuffer(CharArrayBuffer buffer)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 formatProtocolVersion(final ProtocolVersion version, LineFormatter formatter)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 appendProtocolVersion(final CharArrayBuffer buffer, final ProtocolVersion version)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 */ estimateProtocolVersionLen(final ProtocolVersion version)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 */ formatRequestLine(final RequestLine reqline, LineFormatter formatter)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 formatRequestLine(CharArrayBuffer buffer, RequestLine reqline)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 */ doFormatRequestLine(final CharArrayBuffer buffer, final RequestLine reqline)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 */ formatStatusLine(final StatusLine statline, LineFormatter formatter)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 formatStatusLine(final CharArrayBuffer buffer, final StatusLine statline)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 */ doFormatStatusLine(final CharArrayBuffer buffer, final StatusLine statline)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 */ formatHeader(final Header header, LineFormatter formatter)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 formatHeader(CharArrayBuffer buffer, Header header)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 */ doFormatHeader(final CharArrayBuffer buffer, final Header header)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