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