1/* 2 * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/HeaderGroup.java $ 3 * $Revision: 659185 $ 4 * $Date: 2008-05-22 11:07:36 -0700 (Thu, 22 May 2008) $ 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 32package org.apache.http.message; 33 34import java.util.ArrayList; 35import java.util.List; 36import java.util.Locale; 37 38import org.apache.http.Header; 39import org.apache.http.HeaderIterator; 40import org.apache.http.util.CharArrayBuffer; 41 42/** 43 * A class for combining a set of headers. 44 * This class allows for multiple headers with the same name and 45 * keeps track of the order in which headers were added. 46 * 47 * @author Michael Becke 48 * 49 * @since 4.0 50 */ 51public class HeaderGroup implements Cloneable { 52 53 /** The list of headers for this group, in the order in which they were added */ 54 private List headers; 55 56 /** 57 * Constructor for HeaderGroup. 58 */ 59 public HeaderGroup() { 60 this.headers = new ArrayList(16); 61 } 62 63 /** 64 * Removes any contained headers. 65 */ 66 public void clear() { 67 headers.clear(); 68 } 69 70 /** 71 * Adds the given header to the group. The order in which this header was 72 * added is preserved. 73 * 74 * @param header the header to add 75 */ 76 public void addHeader(Header header) { 77 if (header == null) { 78 return; 79 } 80 headers.add(header); 81 } 82 83 /** 84 * Removes the given header. 85 * 86 * @param header the header to remove 87 */ 88 public void removeHeader(Header header) { 89 if (header == null) { 90 return; 91 } 92 headers.remove(header); 93 } 94 95 /** 96 * Replaces the first occurence of the header with the same name. If no header with 97 * the same name is found the given header is added to the end of the list. 98 * 99 * @param header the new header that should replace the first header with the same 100 * name if present in the list. 101 */ 102 public void updateHeader(Header header) { 103 if (header == null) { 104 return; 105 } 106 for (int i = 0; i < this.headers.size(); i++) { 107 Header current = (Header) this.headers.get(i); 108 if (current.getName().equalsIgnoreCase(header.getName())) { 109 this.headers.set(i, header); 110 return; 111 } 112 } 113 this.headers.add(header); 114 } 115 116 /** 117 * Sets all of the headers contained within this group overriding any 118 * existing headers. The headers are added in the order in which they appear 119 * in the array. 120 * 121 * @param headers the headers to set 122 */ 123 public void setHeaders(Header[] headers) { 124 clear(); 125 if (headers == null) { 126 return; 127 } 128 for (int i = 0; i < headers.length; i++) { 129 this.headers.add(headers[i]); 130 } 131 } 132 133 /** 134 * Gets a header representing all of the header values with the given name. 135 * If more that one header with the given name exists the values will be 136 * combined with a "," as per RFC 2616. 137 * 138 * <p>Header name comparison is case insensitive. 139 * 140 * @param name the name of the header(s) to get 141 * @return a header with a condensed value or <code>null</code> if no 142 * headers by the given name are present 143 */ 144 public Header getCondensedHeader(String name) { 145 Header[] headers = getHeaders(name); 146 147 if (headers.length == 0) { 148 return null; 149 } else if (headers.length == 1) { 150 return headers[0]; 151 } else { 152 CharArrayBuffer valueBuffer = new CharArrayBuffer(128); 153 valueBuffer.append(headers[0].getValue()); 154 for (int i = 1; i < headers.length; i++) { 155 valueBuffer.append(", "); 156 valueBuffer.append(headers[i].getValue()); 157 } 158 159 return new BasicHeader(name.toLowerCase(Locale.ENGLISH), valueBuffer.toString()); 160 } 161 } 162 163 /** 164 * Gets all of the headers with the given name. The returned array 165 * maintains the relative order in which the headers were added. 166 * 167 * <p>Header name comparison is case insensitive. 168 * 169 * @param name the name of the header(s) to get 170 * 171 * @return an array of length >= 0 172 */ 173 public Header[] getHeaders(String name) { 174 ArrayList headersFound = new ArrayList(); 175 176 for (int i = 0; i < headers.size(); i++) { 177 Header header = (Header) headers.get(i); 178 if (header.getName().equalsIgnoreCase(name)) { 179 headersFound.add(header); 180 } 181 } 182 183 return (Header[]) headersFound.toArray(new Header[headersFound.size()]); 184 } 185 186 /** 187 * Gets the first header with the given name. 188 * 189 * <p>Header name comparison is case insensitive. 190 * 191 * @param name the name of the header to get 192 * @return the first header or <code>null</code> 193 */ 194 public Header getFirstHeader(String name) { 195 for (int i = 0; i < headers.size(); i++) { 196 Header header = (Header) headers.get(i); 197 if (header.getName().equalsIgnoreCase(name)) { 198 return header; 199 } 200 } 201 return null; 202 } 203 204 /** 205 * Gets the last header with the given name. 206 * 207 * <p>Header name comparison is case insensitive. 208 * 209 * @param name the name of the header to get 210 * @return the last header or <code>null</code> 211 */ 212 public Header getLastHeader(String name) { 213 // start at the end of the list and work backwards 214 for (int i = headers.size() - 1; i >= 0; i--) { 215 Header header = (Header) headers.get(i); 216 if (header.getName().equalsIgnoreCase(name)) { 217 return header; 218 } 219 } 220 221 return null; 222 } 223 224 /** 225 * Gets all of the headers contained within this group. 226 * 227 * @return an array of length >= 0 228 */ 229 public Header[] getAllHeaders() { 230 return (Header[]) headers.toArray(new Header[headers.size()]); 231 } 232 233 /** 234 * Tests if headers with the given name are contained within this group. 235 * 236 * <p>Header name comparison is case insensitive. 237 * 238 * @param name the header name to test for 239 * @return <code>true</code> if at least one header with the name is 240 * contained, <code>false</code> otherwise 241 */ 242 public boolean containsHeader(String name) { 243 for (int i = 0; i < headers.size(); i++) { 244 Header header = (Header) headers.get(i); 245 if (header.getName().equalsIgnoreCase(name)) { 246 return true; 247 } 248 } 249 250 return false; 251 } 252 253 /** 254 * Returns an iterator over this group of headers. 255 * 256 * @return iterator over this group of headers. 257 * 258 * @since 4.0 259 */ 260 public HeaderIterator iterator() { 261 return new BasicListHeaderIterator(this.headers, null); 262 } 263 264 /** 265 * Returns an iterator over the headers with a given name in this group. 266 * 267 * @param name the name of the headers over which to iterate, or 268 * <code>null</code> for all headers 269 * 270 * @return iterator over some headers in this group. 271 * 272 * @since 4.0 273 */ 274 public HeaderIterator iterator(final String name) { 275 return new BasicListHeaderIterator(this.headers, name); 276 } 277 278 /** 279 * Returns a copy of this object 280 * 281 * @return copy of this object 282 */ 283 public HeaderGroup copy() { 284 HeaderGroup clone = new HeaderGroup(); 285 clone.headers.addAll(this.headers); 286 return clone; 287 } 288 289 public Object clone() throws CloneNotSupportedException { 290 HeaderGroup clone = (HeaderGroup) super.clone(); 291 clone.headers = new ArrayList(this.headers); 292 return clone; 293 } 294 295} 296