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 java.io.Serializable; michael@0: import java.util.ArrayList; michael@0: import java.util.List; michael@0: import java.util.Locale; michael@0: michael@0: import ch.boye.httpclientandroidlib.Header; michael@0: import ch.boye.httpclientandroidlib.HeaderIterator; michael@0: import ch.boye.httpclientandroidlib.util.CharArrayBuffer; michael@0: michael@0: /** michael@0: * A class for combining a set of headers. michael@0: * This class allows for multiple headers with the same name and michael@0: * keeps track of the order in which headers were added. michael@0: * michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: public class HeaderGroup implements Cloneable, Serializable { michael@0: michael@0: private static final long serialVersionUID = 2608834160639271617L; michael@0: michael@0: /** The list of headers for this group, in the order in which they were added */ michael@0: private final List headers; michael@0: michael@0: /** michael@0: * Constructor for HeaderGroup. michael@0: */ michael@0: public HeaderGroup() { michael@0: this.headers = new ArrayList(16); michael@0: } michael@0: michael@0: /** michael@0: * Removes any contained headers. michael@0: */ michael@0: public void clear() { michael@0: headers.clear(); michael@0: } michael@0: michael@0: /** michael@0: * Adds the given header to the group. The order in which this header was michael@0: * added is preserved. michael@0: * michael@0: * @param header the header to add michael@0: */ michael@0: public void addHeader(Header header) { michael@0: if (header == null) { michael@0: return; michael@0: } michael@0: headers.add(header); michael@0: } michael@0: michael@0: /** michael@0: * Removes the given header. michael@0: * michael@0: * @param header the header to remove michael@0: */ michael@0: public void removeHeader(Header header) { michael@0: if (header == null) { michael@0: return; michael@0: } michael@0: headers.remove(header); michael@0: } michael@0: michael@0: /** michael@0: * Replaces the first occurence of the header with the same name. If no header with michael@0: * the same name is found the given header is added to the end of the list. michael@0: * michael@0: * @param header the new header that should replace the first header with the same michael@0: * name if present in the list. michael@0: */ michael@0: public void updateHeader(Header header) { michael@0: if (header == null) { michael@0: return; michael@0: } michael@0: for (int i = 0; i < this.headers.size(); i++) { michael@0: Header current = (Header) this.headers.get(i); michael@0: if (current.getName().equalsIgnoreCase(header.getName())) { michael@0: this.headers.set(i, header); michael@0: return; michael@0: } michael@0: } michael@0: this.headers.add(header); michael@0: } michael@0: michael@0: /** michael@0: * Sets all of the headers contained within this group overriding any michael@0: * existing headers. The headers are added in the order in which they appear michael@0: * in the array. michael@0: * michael@0: * @param headers the headers to set michael@0: */ michael@0: public void setHeaders(Header[] headers) { michael@0: clear(); michael@0: if (headers == null) { michael@0: return; michael@0: } michael@0: for (int i = 0; i < headers.length; i++) { michael@0: this.headers.add(headers[i]); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Gets a header representing all of the header values with the given name. michael@0: * If more that one header with the given name exists the values will be michael@0: * combined with a "," as per RFC 2616. michael@0: * michael@0: *

Header name comparison is case insensitive. michael@0: * michael@0: * @param name the name of the header(s) to get michael@0: * @return a header with a condensed value or null if no michael@0: * headers by the given name are present michael@0: */ michael@0: public Header getCondensedHeader(String name) { michael@0: Header[] headers = getHeaders(name); michael@0: michael@0: if (headers.length == 0) { michael@0: return null; michael@0: } else if (headers.length == 1) { michael@0: return headers[0]; michael@0: } else { michael@0: CharArrayBuffer valueBuffer = new CharArrayBuffer(128); michael@0: valueBuffer.append(headers[0].getValue()); michael@0: for (int i = 1; i < headers.length; i++) { michael@0: valueBuffer.append(", "); michael@0: valueBuffer.append(headers[i].getValue()); michael@0: } michael@0: michael@0: return new BasicHeader(name.toLowerCase(Locale.ENGLISH), valueBuffer.toString()); michael@0: } michael@0: } michael@0: michael@0: /** michael@0: * Gets all of the headers with the given name. The returned array michael@0: * maintains the relative order in which the headers were added. michael@0: * michael@0: *

Header name comparison is case insensitive. michael@0: * michael@0: * @param name the name of the header(s) to get michael@0: * michael@0: * @return an array of length >= 0 michael@0: */ michael@0: public Header[] getHeaders(String name) { michael@0: ArrayList headersFound = new ArrayList(); michael@0: michael@0: for (int i = 0; i < headers.size(); i++) { michael@0: Header header = (Header) headers.get(i); michael@0: if (header.getName().equalsIgnoreCase(name)) { michael@0: headersFound.add(header); michael@0: } michael@0: } michael@0: michael@0: return (Header[]) headersFound.toArray(new Header[headersFound.size()]); michael@0: } michael@0: michael@0: /** michael@0: * Gets the first header with the given name. michael@0: * michael@0: *

Header name comparison is case insensitive. michael@0: * michael@0: * @param name the name of the header to get michael@0: * @return the first header or null michael@0: */ michael@0: public Header getFirstHeader(String name) { michael@0: for (int i = 0; i < headers.size(); i++) { michael@0: Header header = (Header) headers.get(i); michael@0: if (header.getName().equalsIgnoreCase(name)) { michael@0: return header; michael@0: } michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * Gets the last header with the given name. michael@0: * michael@0: *

Header name comparison is case insensitive. michael@0: * michael@0: * @param name the name of the header to get michael@0: * @return the last header or null michael@0: */ michael@0: public Header getLastHeader(String name) { michael@0: // start at the end of the list and work backwards michael@0: for (int i = headers.size() - 1; i >= 0; i--) { michael@0: Header header = (Header) headers.get(i); michael@0: if (header.getName().equalsIgnoreCase(name)) { michael@0: return header; michael@0: } michael@0: } michael@0: michael@0: return null; michael@0: } michael@0: michael@0: /** michael@0: * Gets all of the headers contained within this group. michael@0: * michael@0: * @return an array of length >= 0 michael@0: */ michael@0: public Header[] getAllHeaders() { michael@0: return (Header[]) headers.toArray(new Header[headers.size()]); michael@0: } michael@0: michael@0: /** michael@0: * Tests if headers with the given name are contained within this group. michael@0: * michael@0: *

Header name comparison is case insensitive. michael@0: * michael@0: * @param name the header name to test for michael@0: * @return true if at least one header with the name is michael@0: * contained, false otherwise michael@0: */ michael@0: public boolean containsHeader(String name) { michael@0: for (int i = 0; i < headers.size(); i++) { michael@0: Header header = (Header) headers.get(i); michael@0: if (header.getName().equalsIgnoreCase(name)) { michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: /** michael@0: * Returns an iterator over this group of headers. michael@0: * michael@0: * @return iterator over this group of headers. michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: public HeaderIterator iterator() { michael@0: return new BasicListHeaderIterator(this.headers, null); michael@0: } michael@0: michael@0: /** michael@0: * Returns an iterator over the headers with a given name in this group. michael@0: * michael@0: * @param name the name of the headers over which to iterate, or michael@0: * null for all headers michael@0: * michael@0: * @return iterator over some headers in this group. michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: public HeaderIterator iterator(final String name) { michael@0: return new BasicListHeaderIterator(this.headers, name); michael@0: } michael@0: michael@0: /** michael@0: * Returns a copy of this object michael@0: * michael@0: * @return copy of this object michael@0: * michael@0: * @since 4.0 michael@0: */ michael@0: public HeaderGroup copy() { michael@0: HeaderGroup clone = new HeaderGroup(); michael@0: clone.headers.addAll(this.headers); michael@0: return clone; michael@0: } michael@0: michael@0: public Object clone() throws CloneNotSupportedException { michael@0: HeaderGroup clone = (HeaderGroup) super.clone(); michael@0: clone.headers.clear(); michael@0: clone.headers.addAll(this.headers); michael@0: return clone; michael@0: } michael@0: michael@0: public String toString() { michael@0: return this.headers.toString(); michael@0: } michael@0: michael@0: }