michael@0: /* michael@0: * ==================================================================== michael@0: * Licensed to the Apache Software Foundation (ASF) under one michael@0: * or more contributor license agreements. See the NOTICE file michael@0: * distributed with this work for additional information michael@0: * regarding copyright ownership. The ASF licenses this file michael@0: * to you under the Apache License, Version 2.0 (the michael@0: * "License"); you may not use this file except in compliance michael@0: * with the License. You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, michael@0: * software distributed under the License is distributed on an michael@0: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY michael@0: * KIND, either express or implied. See the License for the michael@0: * specific language governing permissions and limitations michael@0: * under the License. michael@0: * ==================================================================== michael@0: * michael@0: * This software consists of voluntary contributions made by many michael@0: * individuals on behalf of the Apache Software Foundation. For more michael@0: * information on the Apache Software Foundation, please see michael@0: * . michael@0: * michael@0: */ michael@0: michael@0: package ch.boye.httpclientandroidlib.message; michael@0: michael@0: import ch.boye.httpclientandroidlib.ProtocolVersion; michael@0: import ch.boye.httpclientandroidlib.RequestLine; michael@0: import ch.boye.httpclientandroidlib.StatusLine; michael@0: import ch.boye.httpclientandroidlib.Header; michael@0: import ch.boye.httpclientandroidlib.FormattedHeader; michael@0: import ch.boye.httpclientandroidlib.util.CharArrayBuffer; michael@0: michael@0: /** michael@0: * Interface for formatting elements of the HEAD section of an HTTP message. michael@0: * This is the complement to {@link LineParser}. michael@0: * There are individual methods for formatting a request line, a michael@0: * status line, or a header line. The formatting does not include the michael@0: * trailing line break sequence CR-LF. michael@0: * The formatted lines are returned in memory, the formatter does not depend michael@0: * on any specific IO mechanism. michael@0: * Instances of this interface are expected to be stateless and thread-safe. michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: public class BasicLineFormatter implements LineFormatter { michael@0: michael@0: /** michael@0: * A default instance of this class, for use as default or fallback. michael@0: * Note that {@link BasicLineFormatter} is not a singleton, there can michael@0: * be many instances of the class itself and of derived classes. michael@0: * The instance here provides non-customized, default behavior. michael@0: */ michael@0: public final static BasicLineFormatter DEFAULT = new BasicLineFormatter(); michael@0: michael@0: michael@0: michael@0: // public default constructor michael@0: michael@0: michael@0: /** michael@0: * Obtains a buffer for formatting. michael@0: * michael@0: * @param buffer a buffer already available, or null michael@0: * michael@0: * @return the cleared argument buffer if there is one, or michael@0: * a new empty buffer that can be used for formatting michael@0: */ michael@0: protected CharArrayBuffer initBuffer(CharArrayBuffer buffer) { michael@0: if (buffer != null) { michael@0: buffer.clear(); michael@0: } else { michael@0: buffer = new CharArrayBuffer(64); michael@0: } michael@0: return buffer; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Formats a protocol version. michael@0: * michael@0: * @param version the protocol version to format michael@0: * @param formatter the formatter to use, or michael@0: * null for the michael@0: * {@link #DEFAULT default} michael@0: * michael@0: * @return the formatted protocol version michael@0: */ michael@0: public final static michael@0: String formatProtocolVersion(final ProtocolVersion version, michael@0: LineFormatter formatter) { michael@0: if (formatter == null) michael@0: formatter = BasicLineFormatter.DEFAULT; michael@0: return formatter.appendProtocolVersion(null, version).toString(); michael@0: } michael@0: michael@0: michael@0: // non-javadoc, see interface LineFormatter michael@0: public CharArrayBuffer appendProtocolVersion(final CharArrayBuffer buffer, michael@0: final ProtocolVersion version) { michael@0: if (version == null) { michael@0: throw new IllegalArgumentException michael@0: ("Protocol version may not be null"); michael@0: } michael@0: michael@0: // can't use initBuffer, that would clear the argument! michael@0: CharArrayBuffer result = buffer; michael@0: final int len = estimateProtocolVersionLen(version); michael@0: if (result == null) { michael@0: result = new CharArrayBuffer(len); michael@0: } else { michael@0: result.ensureCapacity(len); michael@0: } michael@0: michael@0: result.append(version.getProtocol()); michael@0: result.append('/'); michael@0: result.append(Integer.toString(version.getMajor())); michael@0: result.append('.'); michael@0: result.append(Integer.toString(version.getMinor())); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Guesses the length of a formatted protocol version. michael@0: * Needed to guess the length of a formatted request or status line. michael@0: * michael@0: * @param version the protocol version to format, or null michael@0: * michael@0: * @return the estimated length of the formatted protocol version, michael@0: * in characters michael@0: */ michael@0: protected int estimateProtocolVersionLen(final ProtocolVersion version) { michael@0: return version.getProtocol().length() + 4; // room for "HTTP/1.1" michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Formats a request line. michael@0: * michael@0: * @param reqline the request line to format michael@0: * @param formatter the formatter to use, or michael@0: * null for the michael@0: * {@link #DEFAULT default} michael@0: * michael@0: * @return the formatted request line michael@0: */ michael@0: public final static String formatRequestLine(final RequestLine reqline, michael@0: LineFormatter formatter) { michael@0: if (formatter == null) michael@0: formatter = BasicLineFormatter.DEFAULT; michael@0: return formatter.formatRequestLine(null, reqline).toString(); michael@0: } michael@0: michael@0: michael@0: // non-javadoc, see interface LineFormatter michael@0: public CharArrayBuffer formatRequestLine(CharArrayBuffer buffer, michael@0: RequestLine reqline) { michael@0: if (reqline == null) { michael@0: throw new IllegalArgumentException michael@0: ("Request line may not be null"); michael@0: } michael@0: michael@0: CharArrayBuffer result = initBuffer(buffer); michael@0: doFormatRequestLine(result, reqline); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Actually formats a request line. michael@0: * Called from {@link #formatRequestLine}. michael@0: * michael@0: * @param buffer the empty buffer into which to format, michael@0: * never null michael@0: * @param reqline the request line to format, never null michael@0: */ michael@0: protected void doFormatRequestLine(final CharArrayBuffer buffer, michael@0: final RequestLine reqline) { michael@0: final String method = reqline.getMethod(); michael@0: final String uri = reqline.getUri(); michael@0: michael@0: // room for "GET /index.html HTTP/1.1" michael@0: int len = method.length() + 1 + uri.length() + 1 + michael@0: estimateProtocolVersionLen(reqline.getProtocolVersion()); michael@0: buffer.ensureCapacity(len); michael@0: michael@0: buffer.append(method); michael@0: buffer.append(' '); michael@0: buffer.append(uri); michael@0: buffer.append(' '); michael@0: appendProtocolVersion(buffer, reqline.getProtocolVersion()); michael@0: } michael@0: michael@0: michael@0: michael@0: /** michael@0: * Formats a status line. michael@0: * michael@0: * @param statline the status line to format michael@0: * @param formatter the formatter to use, or michael@0: * null for the michael@0: * {@link #DEFAULT default} michael@0: * michael@0: * @return the formatted status line michael@0: */ michael@0: public final static String formatStatusLine(final StatusLine statline, michael@0: LineFormatter formatter) { michael@0: if (formatter == null) michael@0: formatter = BasicLineFormatter.DEFAULT; michael@0: return formatter.formatStatusLine(null, statline).toString(); michael@0: } michael@0: michael@0: michael@0: // non-javadoc, see interface LineFormatter michael@0: public CharArrayBuffer formatStatusLine(final CharArrayBuffer buffer, michael@0: final StatusLine statline) { michael@0: if (statline == null) { michael@0: throw new IllegalArgumentException michael@0: ("Status line may not be null"); michael@0: } michael@0: michael@0: CharArrayBuffer result = initBuffer(buffer); michael@0: doFormatStatusLine(result, statline); michael@0: michael@0: return result; michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Actually formats a status line. michael@0: * Called from {@link #formatStatusLine}. michael@0: * michael@0: * @param buffer the empty buffer into which to format, michael@0: * never null michael@0: * @param statline the status line to format, never null michael@0: */ michael@0: protected void doFormatStatusLine(final CharArrayBuffer buffer, michael@0: final StatusLine statline) { michael@0: michael@0: int len = estimateProtocolVersionLen(statline.getProtocolVersion()) michael@0: + 1 + 3 + 1; // room for "HTTP/1.1 200 " michael@0: final String reason = statline.getReasonPhrase(); michael@0: if (reason != null) { michael@0: len += reason.length(); michael@0: } michael@0: buffer.ensureCapacity(len); michael@0: michael@0: appendProtocolVersion(buffer, statline.getProtocolVersion()); michael@0: buffer.append(' '); michael@0: buffer.append(Integer.toString(statline.getStatusCode())); michael@0: buffer.append(' '); // keep whitespace even if reason phrase is empty michael@0: if (reason != null) { michael@0: buffer.append(reason); michael@0: } michael@0: } michael@0: michael@0: michael@0: /** michael@0: * Formats a header. michael@0: * michael@0: * @param header the header to format michael@0: * @param formatter the formatter to use, or michael@0: * null for the michael@0: * {@link #DEFAULT default} michael@0: * michael@0: * @return the formatted header michael@0: */ michael@0: public final static String formatHeader(final Header header, michael@0: LineFormatter formatter) { michael@0: if (formatter == null) michael@0: formatter = BasicLineFormatter.DEFAULT; michael@0: return formatter.formatHeader(null, header).toString(); michael@0: } michael@0: michael@0: michael@0: // non-javadoc, see interface LineFormatter michael@0: public CharArrayBuffer formatHeader(CharArrayBuffer buffer, michael@0: Header header) { michael@0: if (header == null) { michael@0: throw new IllegalArgumentException michael@0: ("Header may not be null"); michael@0: } michael@0: CharArrayBuffer result = null; michael@0: michael@0: if (header instanceof FormattedHeader) { michael@0: // If the header is backed by a buffer, re-use the buffer michael@0: result = ((FormattedHeader)header).getBuffer(); michael@0: } else { michael@0: result = initBuffer(buffer); michael@0: doFormatHeader(result, header); michael@0: } michael@0: return result; michael@0: michael@0: } // formatHeader michael@0: michael@0: michael@0: /** michael@0: * Actually formats a header. michael@0: * Called from {@link #formatHeader}. michael@0: * michael@0: * @param buffer the empty buffer into which to format, michael@0: * never null michael@0: * @param header the header to format, never null michael@0: */ michael@0: protected void doFormatHeader(final CharArrayBuffer buffer, michael@0: final Header header) { michael@0: final String name = header.getName(); michael@0: final String value = header.getValue(); michael@0: michael@0: int len = name.length() + 2; michael@0: if (value != null) { michael@0: len += value.length(); michael@0: } michael@0: buffer.ensureCapacity(len); michael@0: michael@0: buffer.append(name); michael@0: buffer.append(": "); michael@0: if (value != null) { michael@0: buffer.append(value); michael@0: } michael@0: } michael@0: michael@0: michael@0: } // class BasicLineFormatter