KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > trove > net > HttpHeaderMap


1 /* ====================================================================
2  * Trove - Copyright (c) 1997-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.trove.net;
54
55 import java.util.*;
56 import java.text.*;
57 import java.io.*;
58 import com.go.trove.io.*;
59
60 /******************************************************************************
61  *
62  * @author Brian S O'Neill
63  * @version
64  * <!--$$Revision:--> 12 <!-- $-->, <!--$$JustDate:--> 01/07/16 <!-- $-->
65  */

66 public class HttpHeaderMap implements Map, Serializable {
67     private final static TimeZone GMT_ZONE;
68     private final static DateFormat DATE_PARSER_1;
69     private final static DateFormat DATE_PARSER_2;
70     private final static String JavaDoc[] DAYS;
71     private final static String JavaDoc[] MONTHS;
72
73     static {
74         GMT_ZONE = TimeZone.getTimeZone("GMT");
75
76         DATE_PARSER_1 =
77             new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.US);
78         DATE_PARSER_1.setTimeZone(GMT_ZONE);
79         DATE_PARSER_1.setLenient(true);
80
81         DATE_PARSER_2 =
82             new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss", Locale.US);
83         DATE_PARSER_2.setTimeZone(GMT_ZONE);
84         DATE_PARSER_2.setLenient(true);
85
86         DateFormatSymbols symbols = new DateFormatSymbols(Locale.US);
87         DAYS = symbols.getShortWeekdays();
88         MONTHS = symbols.getShortMonths();
89     }
90
91     private static void appendDate(CharToByteBuffer buffer, Date d)
92         throws IOException
93     {
94         Calendar c = new GregorianCalendar(GMT_ZONE, Locale.US);
95         c.setTime(d);
96
97         buffer.append(DAYS[c.get(Calendar.DAY_OF_WEEK)]);
98         buffer.append(", ");
99         append2Digit(buffer, c.get(Calendar.DAY_OF_MONTH));
100         buffer.append(' ');
101         buffer.append(MONTHS[c.get(Calendar.MONTH)]);
102         buffer.append(' ');
103         append4Digit(buffer, c.get(Calendar.YEAR));
104         buffer.append(' ');
105         append2Digit(buffer, c.get(Calendar.HOUR_OF_DAY));
106         buffer.append(':');
107         append2Digit(buffer, c.get(Calendar.MINUTE));
108         buffer.append(':');
109         append2Digit(buffer, c.get(Calendar.SECOND));
110         buffer.append(" GMT");
111     }
112
113     private static void append2Digit(CharToByteBuffer buffer, int val)
114         throws IOException
115     {
116         buffer.append((char)(val / 10 + '0'));
117         buffer.append((char)(val % 10 + '0'));
118     }
119
120     private static void append4Digit(CharToByteBuffer buffer, int val)
121         throws IOException
122     {
123         if (val < 1000 || val > 9999) {
124             buffer.append(Integer.toString(val));
125         }
126         else {
127             buffer.append((char)(val / 1000 + '0'));
128             buffer.append((char)(val / 100 % 10 + '0'));
129             buffer.append((char)(val / 10 % 10 + '0'));
130             buffer.append((char)(val % 10 + '0'));
131         }
132     }
133
134     private Map mMap;
135
136     public HttpHeaderMap() {
137         mMap = new TreeMap(String.CASE_INSENSITIVE_ORDER);
138     }
139
140     /**
141      * Read and parse headers from the given InputStream until a blank line is
142      * reached. Except for Cookies, all other headers that contain multiple
143      * fields delimited by commas are parsed into multiple headers.
144      *
145      * @param in stream to read from
146      */

147     public void readFrom(InputStream in) throws IOException {
148         readFrom(in, new byte[80]);
149     }
150
151     /**
152      * Read and parse headers from the given InputStream until a blank line is
153      * reached. Except for Cookies, all other headers that contain multiple
154      * fields delimited by commas are parsed into multiple headers.
155      *
156      * @param in stream to read from
157      * @param buffer temporary buffer to use
158      */

159     public void readFrom(InputStream in, byte[] buffer) throws IOException {
160         String JavaDoc header;
161         while ((header = HttpUtils.readLine(in, buffer, 4000)) != null) {
162             if (header.length() == 0) {
163                 break;
164             }
165             processHeaderLine(header);
166         }
167     }
168
169     /**
170      * Read and parse headers from the given InputStream until a blank line is
171      * reached. Except for Cookies, all other headers that contain multiple
172      * fields delimited by commas are parsed into multiple headers.
173      *
174      * @param in stream to read from
175      * @param buffer temporary buffer to use
176      */

177     public void readFrom(InputStream in, char[] buffer) throws IOException {
178         String JavaDoc header;
179         while ((header = HttpUtils.readLine(in, buffer, 4000)) != null) {
180             if (header.length() == 0) {
181                 break;
182             }
183             processHeaderLine(header);
184         }
185     }
186
187     private void processHeaderLine(String JavaDoc header) {
188         int index = header.indexOf(':');
189         if (index < 0) {
190             return;
191         }
192         
193         String JavaDoc name = header.substring(0, index);
194
195         String JavaDoc value;
196         int length = header.length();
197         parseValue: {
198             do {
199                 if (++index >= length) {
200                     value = "";
201                     break parseValue;
202                 }
203             } while (header.charAt(index) == ' ');
204
205             value = header.substring(index);
206         }
207         
208         if ("Cookie".equalsIgnoreCase(name) ||
209             "Set-Cookie".equalsIgnoreCase(name) ||
210             (value.indexOf(',') == 3 &&
211              (value.startsWith("Mon") ||
212               value.startsWith("Tue") ||
213               value.startsWith("Wed") ||
214               value.startsWith("Thu") ||
215               value.startsWith("Fri") ||
216               value.startsWith("Sat") ||
217               value.startsWith("Sun")))) {
218             
219             add(name, value.trim());
220         }
221         else {
222             // Parse up header by commas unless its a Cookie or value
223
// is a date.
224
while ((index = value.indexOf(',')) >= 0) {
225                 add(name, value.substring(0, index).trim());
226                 value = value.substring(index + 1);
227             }
228             
229             add(name, value.trim());
230         }
231     }
232
233     public void writeTo(OutputStream out) throws IOException {
234         CharToByteBuffer buffer = new FastCharToByteBuffer
235             (new DefaultByteBuffer(), "8859_1");
236         buffer = new InternedCharToByteBuffer(buffer);
237         appendTo(buffer);
238         buffer.writeTo(out);
239     }
240     
241     public void appendTo(CharToByteBuffer buffer) throws IOException {
242         Iterator it = mMap.entrySet().iterator();
243         while (it.hasNext()) {
244             Map.Entry entry = (Map.Entry)it.next();
245             Object JavaDoc key = entry.getKey();
246             Object JavaDoc value = entry.getValue();
247
248             if (key == null || value == null) {
249                 continue;
250             }
251
252             String JavaDoc strKey = key.toString();
253
254             if (value instanceof List) {
255                 Iterator values = ((List)value).iterator();
256                 if ("Set-Cookie".equalsIgnoreCase(strKey)) {
257                     while (values.hasNext()) {
258                         buffer.append(strKey);
259                         buffer.append(": ");
260                         value = values.next();
261                         if (value instanceof Date) {
262                             appendDate(buffer, (Date)value);
263                         }
264                         else {
265                             buffer.append(value.toString());
266                         }
267                         buffer.append("\r\n");
268                     }
269                 }
270                 else {
271                     // Write multiple headers together except Cookies.
272
int count = 0;
273                     while (values.hasNext()) {
274                         value = values.next();
275
276                         if (count < 0) {
277                             buffer.append("\r\n");
278                             count = 0;
279                         }
280                         if (count++ == 0) {
281                             buffer.append(strKey);
282                             buffer.append(": ");
283                         }
284
285                         if (value instanceof Date) {
286                             // Comma in date, so must isolate header.
287
if (count > 1) {
288                                 buffer.append("\r\n");
289                                 buffer.append(strKey);
290                                 buffer.append(": ");
291                             }
292                             appendDate(buffer, (Date)value);
293                             count = -1;
294                         }
295                         else {
296                             String JavaDoc strVal = value.toString();
297                             if (strVal.indexOf(',') < 0) {
298                                 if (count > 1) {
299                                     buffer.append(',');
300                                 }
301                                 buffer.append(strVal);
302                             }
303                             else {
304                                 // Comma in value, so must isolate header.
305
if (count > 1) {
306                                     buffer.append("\r\n");
307                                     buffer.append(strKey);
308                                     buffer.append(": ");
309                                 }
310                                 buffer.append(strVal);
311                                 count = -1;
312                             }
313                         }
314                     }
315                     buffer.append("\r\n");
316                 }
317             }
318             else {
319                 buffer.append(strKey);
320                 buffer.append(": ");
321                 if (value instanceof Date) {
322                     appendDate(buffer, (Date)value);
323                 }
324                 else {
325                     buffer.append(value.toString());
326                 }
327                 buffer.append("\r\n");
328             }
329         }
330     }
331
332     public int size() {
333         return mMap.size();
334     }
335
336     public boolean isEmpty() {
337         return mMap.isEmpty();
338     }
339
340     public boolean containsKey(Object JavaDoc key) {
341         return mMap.containsKey(key);
342     }
343
344     public boolean containsValue(Object JavaDoc value) {
345         Iterator it = mMap.values().iterator();
346         while (it.hasNext()) {
347             Object JavaDoc obj = it.next();
348             if (obj instanceof List) {
349                 Iterator it2 = ((List)obj).iterator();
350                 while (it2.hasNext()) {
351                     obj = it2.next();
352                     return (value == null) ? obj == null : value.equals(obj);
353                 }
354             }
355             else {
356                 return (value == null) ? obj == null : value.equals(obj);
357             }
358         }
359         return false;
360     }
361     
362     /**
363      * Returns the first value associated with the given key.
364      */

365     public Object JavaDoc get(Object JavaDoc key) {
366         Object JavaDoc value = mMap.get(key);
367         if (value instanceof List) {
368             return ((List)value).get(0);
369         }
370         else {
371             return value;
372         }
373     }
374
375     public String JavaDoc getString(Object JavaDoc key) {
376         Object JavaDoc obj = get(key);
377         if (obj instanceof String JavaDoc) {
378             return (String JavaDoc)obj;
379         }
380         else if (obj != null) {
381             return obj.toString();
382         }
383         return null;
384     }
385
386     public Integer JavaDoc getInteger(Object JavaDoc key) {
387         Object JavaDoc obj = get(key);
388         if (obj instanceof Integer JavaDoc) {
389             return (Integer JavaDoc)obj;
390         }
391         else if (obj != null) {
392             try {
393                 return new Integer JavaDoc(obj.toString());
394             }
395             catch (NumberFormatException JavaDoc e) {
396             }
397         }
398         return null;
399     }
400
401     public Date getDate(Object JavaDoc key) {
402         Object JavaDoc obj = get(key);
403         if (obj instanceof Date) {
404             return (Date)obj;
405         }
406         else if (obj == null) {
407             return null;
408         }
409
410         String JavaDoc val = obj.toString();
411
412         // Trim after a possible ';' to separate the date
413
// from other optional data.
414
int index = val.indexOf(';');
415         if (index >= 0) {
416             val = val.substring(0, index);
417         }
418
419         Date date;
420
421         try {
422             synchronized (DATE_PARSER_1) {
423                 date = DATE_PARSER_1.parse(val);
424             }
425         }
426         catch (ParseException e) {
427             try {
428                 synchronized (DATE_PARSER_2) {
429                     date = DATE_PARSER_2.parse(val);
430                 }
431             }
432             catch (ParseException e2) {
433                 return null;
434             }
435         }
436
437         return date;
438     }
439     
440
441     /**
442      * Returns all the values associated with the given key. Changes to the
443      * returned list will be reflected in this map.
444      */

445     public List getAll(Object JavaDoc key) {
446         Object JavaDoc value = mMap.get(key);
447         if (value instanceof List) {
448             return ((List)value);
449         }
450         else {
451             List list = new ArrayList();
452             if (value != null || mMap.containsKey(key)) {
453                 list.add(value);
454             }
455             mMap.put(key, list);
456             return list;
457         }
458     }
459
460     /**
461      * May return a list if the key previously mapped to multiple values.
462      */

463     public Object JavaDoc put(Object JavaDoc key, Object JavaDoc value) {
464         if (value instanceof List) {
465             return mMap.put(key, new ArrayList((List)value));
466         }
467         else {
468             return mMap.put(key, value);
469         }
470     }
471
472     /**
473      * Add more than one value associated with the given key.
474      */

475     public void add(Object JavaDoc key, Object JavaDoc value) {
476         Object JavaDoc existing = mMap.get(key);
477         if (existing instanceof List) {
478             if (value instanceof List) {
479                 ((List)existing).addAll((List)value);
480             }
481             else {
482                 ((List)existing).add(value);
483             }
484         }
485         else if (existing == null && !mMap.containsKey(key)) {
486             if (value instanceof List) {
487                 mMap.put(key, new ArrayList((List)value));
488             }
489             else {
490                 mMap.put(key, value);
491             }
492         }
493         else {
494             List list = new ArrayList();
495             list.add(existing);
496             if (value instanceof List) {
497                 list.addAll((List)value);
498             }
499             else {
500                 list.add(value);
501             }
502             mMap.put(key, list);
503         }
504     }
505
506     public Object JavaDoc remove(Object JavaDoc key) {
507         return mMap.remove(key);
508     }
509
510     public void putAll(Map map) {
511         mMap.putAll(map);
512     }
513
514     public void clear() {
515         mMap.clear();
516     }
517
518     public Set keySet() {
519         return mMap.keySet();
520     }
521
522     public Collection values() {
523         return mMap.values();
524     }
525
526     public Set entrySet() {
527         return mMap.entrySet();
528     }
529
530     public boolean equals(Object JavaDoc obj) {
531         return mMap.equals(obj);
532     }
533
534     public int hashCode() {
535         return mMap.hashCode();
536     }
537
538     public String JavaDoc toString() {
539         return super.toString() + ":" + mMap.toString();
540     }
541 }
542
Popular Tags