View Javadoc

1   /*
2    * $HeadURL: https://svn.apache.org/repos/asf/httpcomponents/oac.hc3x/trunk/src/java/org/apache/commons/httpclient/HeaderElement.java $
3    * $Revision: 1425331 $
4    * $Date: 2012-12-22 18:29:41 +0000 (Sat, 22 Dec 2012) $
5    *
6    * ====================================================================
7    *
8    *  Licensed to the Apache Software Foundation (ASF) under one or more
9    *  contributor license agreements.  See the NOTICE file distributed with
10   *  this work for additional information regarding copyright ownership.
11   *  The ASF licenses this file to You under the Apache License, Version 2.0
12   *  (the "License"); you may not use this file except in compliance with
13   *  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, software
18   *  distributed under the License is distributed on an "AS IS" BASIS,
19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   *  See the License for the specific language governing permissions and
21   *  limitations under the License.
22   * ====================================================================
23   *
24   * This software consists of voluntary contributions made by many
25   * individuals on behalf of the Apache Software Foundation.  For more
26   * information on the Apache Software Foundation, please see
27   * <http://www.apache.org/>.
28   *
29   */
30  
31  package org.apache.commons.httpclient;
32  
33  import java.util.ArrayList;
34  import java.util.List;
35  
36  import org.apache.commons.httpclient.util.ParameterParser;
37  import org.apache.commons.logging.Log;
38  import org.apache.commons.logging.LogFactory;
39  
40  /***
41   * <p>One element of an HTTP header's value.</p>
42   * <p>
43   * Some HTTP headers (such as the set-cookie header) have values that
44   * can be decomposed into multiple elements.  Such headers must be in the
45   * following form:
46   * </p>
47   * <pre>
48   * header  = [ element ] *( "," [ element ] )
49   * element = name [ "=" [ value ] ] *( ";" [ param ] )
50   * param   = name [ "=" [ value ] ]
51   *
52   * name    = token
53   * value   = ( token | quoted-string )
54   *
55   * token         = 1*&lt;any char except "=", ",", ";", &lt;"&gt; and
56   *                       white space&gt;
57   * quoted-string = &lt;"&gt; *( text | quoted-char ) &lt;"&gt;
58   * text          = any char except &lt;"&gt;
59   * quoted-char   = "\" char
60   * </pre>
61   * <p>
62   * Any amount of white space is allowed between any part of the
63   * header, element or param and is ignored. A missing value in any
64   * element or param will be stored as the empty {@link String};
65   * if the "=" is also missing <var>null</var> will be stored instead.
66   * </p>
67   * <p>
68   * This class represents an individual header element, containing
69   * both a name/value pair (value may be <tt>null</tt>) and optionally
70   * a set of additional parameters.
71   * </p>
72   * <p>
73   * This class also exposes a {@link #parse} method for parsing a
74   * {@link Header} value into an array of elements.
75   * </p>
76   *
77   * @see Header
78   *
79   * @author <a href="mailto:bcholmes@interlog.com">B.C. Holmes</a>
80   * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a>
81   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
82   * @author <a href="mailto:oleg@ural.com">Oleg Kalnichevski</a>
83   * 
84   * @since 1.0
85   * @version $Revision: 1425331 $ $Date: 2012-12-22 18:29:41 +0000 (Sat, 22 Dec 2012) $
86   */
87  public class HeaderElement extends NameValuePair {
88  
89      // ----------------------------------------------------------- Constructors
90  
91      /***
92       * Default constructor.
93       */
94      public HeaderElement() {
95          this(null, null, null);
96      }
97  
98      /***
99        * Constructor.
100       * @param name my name
101       * @param value my (possibly <tt>null</tt>) value
102       */
103     public HeaderElement(String name, String value) {
104         this(name, value, null);
105     }
106 
107     /***
108      * Constructor with name, value and parameters.
109      *
110      * @param name my name
111      * @param value my (possibly <tt>null</tt>) value
112      * @param parameters my (possibly <tt>null</tt>) parameters
113      */
114     public HeaderElement(String name, String value,
115             NameValuePair[] parameters) {
116         super(name, value);
117         this.parameters = parameters;
118     }
119 
120     /***
121      * Constructor with array of characters.
122      *
123      * @param chars the array of characters
124      * @param offset - the initial offset.
125      * @param length - the length.
126      * 
127      * @since 3.0
128      */
129     public HeaderElement(char[] chars, int offset, int length) {
130         this();
131         if (chars == null) {
132             return;
133         }
134         ParameterParser parser = new ParameterParser();
135         List params = parser.parse(chars, offset, length, ';');
136         if (params.size() > 0) {
137             NameValuePair element = (NameValuePair) params.remove(0);
138             setName(element.getName());  
139             setValue(element.getValue());
140             if (params.size() > 0) {
141                 this.parameters = (NameValuePair[])
142                     params.toArray(new NameValuePair[params.size()]);    
143             }
144         }
145     }
146 
147     /***
148      * Constructor with array of characters.
149      *
150      * @param chars the array of characters
151      * 
152      * @since 3.0
153      */
154     public HeaderElement(char[] chars) {
155         this(chars, 0, chars.length);
156     }
157 
158     // -------------------------------------------------------- Constants
159 
160     /*** Log object for this class. */
161     private static final Log LOG = LogFactory.getLog(HeaderElement.class);
162 
163     // ----------------------------------------------------- Instance Variables
164 
165     /*** My parameters, if any. */
166     private NameValuePair[] parameters = null;
167 
168     // ------------------------------------------------------------- Properties
169 
170     /***
171      * Get parameters, if any.
172      *
173      * @since 2.0
174      * @return parameters as an array of {@link NameValuePair}s
175      */
176     public NameValuePair[] getParameters() {
177         return this.parameters;
178     }
179 
180     // --------------------------------------------------------- Public Methods
181 
182     /***
183      * This parses the value part of a header. The result is an array of
184      * HeaderElement objects.
185      *
186      * @param headerValue  the array of char representation of the header value
187      *                     (as received from the web server).
188      * @return array of {@link HeaderElement}s.
189      * 
190      * @since 3.0
191      */
192     public static final HeaderElement[] parseElements(char[] headerValue) {
193             
194         LOG.trace("enter HeaderElement.parseElements(char[])");
195 
196         if (headerValue == null) {
197             return new HeaderElement[] {};
198         }
199         List elements = new ArrayList(); 
200         
201         int i = 0;
202         int from = 0;
203         int len = headerValue.length;
204         boolean qouted = false;
205         while (i < len) {
206             char ch = headerValue[i];
207             if (ch == '"') {
208                 qouted = !qouted;
209             }
210             HeaderElement element = null;
211             if ((!qouted) && (ch == ',')) {
212                 element = new HeaderElement(headerValue, from, i);
213                 from = i + 1;
214             } else if (i == len - 1) {
215                 element = new HeaderElement(headerValue, from, len);
216             }
217             if ((element != null) && (element.getName() != null)) {
218                 elements.add(element);
219             }
220             i++;
221         }
222         return (HeaderElement[])
223             elements.toArray(new HeaderElement[elements.size()]);
224     }
225 
226     /***
227      * This parses the value part of a header. The result is an array of
228      * HeaderElement objects.
229      *
230      * @param headerValue  the string representation of the header value
231      *                     (as received from the web server).
232      * @return array of {@link HeaderElement}s.
233      * 
234      * @since 3.0
235      */
236     public static final HeaderElement[] parseElements(String headerValue) {
237             
238         LOG.trace("enter HeaderElement.parseElements(String)");
239 
240         if (headerValue == null) {
241             return new HeaderElement[] {};
242         }
243         return parseElements(headerValue.toCharArray());
244     }
245 
246     /***
247      * This parses the value part of a header. The result is an array of
248      * HeaderElement objects.
249      *
250      * @param headerValue  the string representation of the header value
251      *                     (as received from the web server).
252      * @return array of {@link HeaderElement}s.
253      * @throws HttpException if the above syntax rules are violated.
254      * 
255      * @deprecated Use #parseElements(String).
256      */
257     public static final HeaderElement[] parse(String headerValue)
258         throws HttpException {
259             
260         LOG.trace("enter HeaderElement.parse(String)");
261 
262         if (headerValue == null) {
263             return new HeaderElement[] {};
264         }
265         return parseElements(headerValue.toCharArray());
266     }
267          
268 
269     /***
270      * Returns parameter with the given name, if found. Otherwise null 
271      * is returned
272      *
273      * @param name The name to search by.
274      * @return NameValuePair parameter with the given name
275      */
276 
277     public NameValuePair getParameterByName(String name) {
278 
279         LOG.trace("enter HeaderElement.getParameterByName(String)");
280 
281         if (name == null) {
282             throw new IllegalArgumentException("Name may not be null");
283         } 
284         NameValuePair found = null;
285         NameValuePair parameters[] = getParameters();
286         if (parameters != null) {
287             for (int i = 0; i < parameters.length; i++) {
288                 NameValuePair current = parameters[ i ];
289                 if (current.getName().equalsIgnoreCase(name)) {
290                     found = current;
291                     break;
292                 }
293             }
294         }
295         return found;
296     }
297 
298 }
299