libjava/ChangeLog:
[official-gcc.git] / libjava / classpath / gnu / java / net / protocol / http / Headers.java
blob690a0c65bd045a756b65c93fed426cfe013cb4ba
1 /* Headers.java --
2 Copyright (C) 2004, 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.net.protocol.http;
41 import gnu.java.lang.CPStringBuilder;
43 import gnu.java.net.LineInputStream;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.lang.Iterable;
48 import java.text.DateFormat;
49 import java.text.ParseException;
50 import java.util.ArrayList;
51 import java.util.Collections;
52 import java.util.Date;
53 import java.util.Iterator;
54 import java.util.LinkedHashMap;
55 import java.util.List;
56 import java.util.Map;
58 /**
59 * A collection of HTTP header names and associated values. The
60 * values are {@link ArrayList ArrayLists} of Strings. Retrieval of
61 * values is case insensitive. An iteration over the collection
62 * returns the header names in the order they were received.
64 * @author Chris Burdess (dog@gnu.org)
65 * @author David Daney (ddaney@avtrex.com)
67 class Headers implements Iterable<Headers.HeaderElement>
69 /**
70 * A list of HeaderElements
72 private final ArrayList<HeaderElement> headers
73 = new ArrayList<HeaderElement>();
75 /**
76 * The HTTP dateformat used to parse date header fields.
78 private static final DateFormat dateFormat = new HTTPDateFormat();
80 /**
81 * Class for a Header element consisting of
82 * a name and value String.
84 static class HeaderElement
86 String name;
87 String value;
89 HeaderElement(String name, String value)
91 this.name = name;
92 this.value = value;
96 /**
97 * Default constructor.
99 public Headers()
101 // nothing to do
105 * Return an Iterator over this collection of headers.
106 * Iterator.getNext() returns objects of type {@link HeaderElement}.
108 * @return the Iterator.
110 public Iterator<HeaderElement> iterator()
112 return headers.iterator();
116 * Returns the value of the specified header as a string. If
117 * multiple values are present, the last one is returned.
119 * @param header the header name (case insensitive search)
120 * @return The header value or <code>null</code> if not found.
122 public String getValue(String header)
124 for (int i = headers.size() - 1; i >= 0; i--)
126 HeaderElement e = headers.get(i);
127 if (e.name.equalsIgnoreCase(header))
129 return e.value;
132 return null;
136 * Returns the value of the specified header as an integer. If
137 * multiple values are present, the last one is returned.
139 * @param header the header name (case insensitive search)
140 * @return The header value or <code>-1</code> if not present or
141 * not an integer value.
143 public int getIntValue(String header)
145 String val = getValue(header);
146 if (val == null)
148 return -1;
152 return Integer.parseInt(val);
154 catch (NumberFormatException e)
156 // fall through
158 return -1;
162 * Returns the value of the specified header as a long. If
163 * multiple values are present, the last one is returned.
165 * @param header the header name (case insensitive search)
166 * @return The header value or <code>-1</code> if not present or
167 * not a long value.
169 public long getLongValue(String header)
171 String val = getValue(header);
172 if (val == null)
174 return -1;
178 return Long.parseLong(val);
180 catch (NumberFormatException e)
182 // fall through
184 return -1;
188 * Returns the value of the specified header as a date. If
189 * multiple values are present, the last one is returned.
191 * @param header the header name (case insensitive search)
192 * @return The header value or <code>null</code> if not present or
193 * not a date value.
195 public Date getDateValue(String header)
197 String val = getValue(header);
198 if (val == null)
200 return null;
204 return dateFormat.parse(val);
206 catch (ParseException e)
208 return null;
213 * Add a header to this set of headers. If there is an existing
214 * header with the same name it's value is replaced with the new value.
215 * If multiple headers of the same name exist only the last one's value
216 * is replaced.
218 * @param name the header name
219 * @param value the header value
221 * @see #addValue(String, String)
223 public void put(String name, String value)
225 for (int i = headers.size() - 1; i >= 0; i--)
227 HeaderElement e = headers.get(i);
228 if (e.name.equalsIgnoreCase(name))
230 e.value = value;
231 return;
235 // nothing was replaced so add it as new HeaderElement
236 addValue(name, value);
240 * Add all headers from a set of headers to this set. Any existing header
241 * with the same (case insensitive) name as one of the new headers will
242 * be overridden.
244 * @param o the headers to be added
246 public void putAll(Headers o)
248 for (Iterator<HeaderElement> it = o.iterator(); it.hasNext(); )
250 HeaderElement e = it.next();
251 remove(e.name);
252 addValue(e.name, e.value);
257 * Remove a header from this set of headers. If there is more than
258 * one instance of a header of the given name, they are all removed.
260 * @param name the header name
262 public void remove(String name)
264 for (Iterator<HeaderElement> it = headers.iterator(); it.hasNext(); )
266 HeaderElement e = it.next();
267 if (e.name.equalsIgnoreCase(name))
268 it.remove();
273 * Parse the specified InputStream, adding headers to this collection.
275 * @param in the InputStream.
276 * @throws IOException if I/O error occured.
278 public void parse(InputStream in)
279 throws IOException
281 LineInputStream lin = (in instanceof LineInputStream) ?
282 (LineInputStream) in : new LineInputStream(in);
284 String name = null;
285 CPStringBuilder value = new CPStringBuilder();
286 while (true)
288 String line = lin.readLine();
289 if (line == null)
291 if (name != null)
293 addValue(name, value.toString());
295 break;
297 int len = line.length();
298 if (len < 2)
300 if (name != null)
302 addValue(name, value.toString());
304 break;
306 char c1 = line.charAt(0);
307 if (c1 == ' ' || c1 == '\t')
309 // Continuation
310 int last = len - 1;
311 if (line.charAt(last) != '\r')
312 ++last;
313 value.append(line.substring(0, last));
315 else
317 if (name != null)
319 addValue(name, value.toString());
322 int di = line.indexOf(':');
323 name = line.substring(0, di);
324 value.setLength(0);
327 di++;
329 while (di < len && line.charAt(di) == ' ');
330 int last = len - 1;
331 if (line.charAt(last) != '\r')
332 ++last;
333 value.append(line.substring(di, last));
340 * Add a header to this set of headers. If there is an existing
341 * header with the same name, it is not effected.
343 * @param name the header name
344 * @param value the header value
346 * @see #put(String, String)
348 public void addValue(String name, String value)
350 headers.add(headers.size(), new HeaderElement(name, value));
354 * Get a new Map containing all the headers. The keys of the Map
355 * are Strings (the header names). The headers will be included
356 * case-sensitive in the map so that querying must be done with the
357 * correct case of the needed header name. The values of the Map are
358 * unmodifiable Lists containing Strings (the header values).
360 * <p>
361 * The returned map is modifiable. Changing it will not effect this
362 * collection of Headers in any way.</p>
364 * @return a Map containing all the headers.
366 public Map<String,List<String>> getAsMap()
368 LinkedHashMap<String,List<String>> m = new LinkedHashMap<String,List<String>>();
369 for (Iterator<HeaderElement> it = headers.iterator(); it.hasNext(); )
371 HeaderElement e = it.next();
372 ArrayList<String> l = (ArrayList<String>)m.get(e.name);
373 if (l == null)
375 l = new ArrayList<String>(1);
376 l.add(e.value);
377 m.put(e.name, l);
379 else
380 l.add(0, e.value);
382 for (Iterator<Map.Entry<String,List<String>>> it = m.entrySet().iterator(); it.hasNext(); )
384 Map.Entry<String,List<String>> me = it.next();
385 List<String> l = me.getValue();
386 me.setValue(Collections.unmodifiableList(l));
388 return m;
392 * Get the name of the Nth header.
394 * @param i the header index.
396 * @return The header name, or <code>null</code> if index outside of range.
398 * @see #getHeaderValue(int)
400 public String getHeaderName(int i)
402 if (i >= headers.size() || i < 0)
403 return null;
405 return headers.get(i).name;
409 * Get the value of the Nth header.
411 * @param i the header index.
413 * @return the header value, or <code>null</code> if index outside of range.
415 * @see #getHeaderName(int)
417 public String getHeaderValue(int i)
419 if (i >= headers.size() || i < 0)
420 return null;
422 return headers.get(i).value;