1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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*<any char except "=", ",", ";", <"> and
56 * white space>
57 * quoted-string = <"> *( text | quoted-char ) <">
58 * text = any char except <">
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$ $Date$
86 */
87 public class HeaderElement extends NameValuePair {
88
89
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
159
160 /*** Log object for this class. */
161 private static final Log LOG = LogFactory.getLog(HeaderElement.class);
162
163
164
165 /*** My parameters, if any. */
166 private NameValuePair[] parameters = null;
167
168
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
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