View Javadoc

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 org.apache.http.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 org.apache.http.Header;
36  import org.apache.http.HeaderIterator;
37  import org.apache.http.annotation.NotThreadSafe;
38  import org.apache.http.util.CharArrayBuffer;
39  
40  /**
41   * A class for combining a set of headers.
42   * This class allows for multiple headers with the same name and
43   * keeps track of the order in which headers were added.
44   *
45   *
46   * @since 4.0
47   */
48  @NotThreadSafe
49  public class HeaderGroup implements Cloneable, Serializable {
50  
51      private static final long serialVersionUID = 2608834160639271617L;
52  
53      /** The list of headers for this group, in the order in which they were added */
54      private final List<Header> headers;
55  
56      /**
57       * Constructor for HeaderGroup.
58       */
59      public HeaderGroup() {
60          this.headers = new ArrayList<Header>(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 = 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         List<Header> headersFound = new ArrayList<Header>();
175 
176         for (int i = 0; i < headers.size(); i++) {
177             Header header = headers.get(i);
178             if (header.getName().equalsIgnoreCase(name)) {
179                 headersFound.add(header);
180             }
181         }
182 
183         return 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 = 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 = 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 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 = 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      * @since 4.0
284      */
285     public HeaderGroup copy() {
286         HeaderGroup clone = new HeaderGroup();
287         clone.headers.addAll(this.headers);
288         return clone;
289     }
290 
291     @Override
292     public Object clone() throws CloneNotSupportedException {
293         return super.clone();
294     }
295 
296     @Override
297     public String toString() {
298         return this.headers.toString();
299     }
300 
301 }