1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty;
16
17 import java.io.IOException;
18 import java.text.SimpleDateFormat;
19 import java.util.ArrayList;
20 import java.util.Calendar;
21 import java.util.Collections;
22 import java.util.Date;
23 import java.util.Enumeration;
24 import java.util.GregorianCalendar;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.NoSuchElementException;
31 import java.util.StringTokenizer;
32 import java.util.TimeZone;
33
34 import javax.servlet.http.Cookie;
35
36 import org.mortbay.io.Buffer;
37 import org.mortbay.io.BufferCache;
38 import org.mortbay.io.BufferDateCache;
39 import org.mortbay.io.BufferUtil;
40 import org.mortbay.io.ByteArrayBuffer;
41 import org.mortbay.io.View;
42 import org.mortbay.io.BufferCache.CachedBuffer;
43 import org.mortbay.util.LazyList;
44 import org.mortbay.util.QuotedStringTokenizer;
45 import org.mortbay.util.StringMap;
46 import org.mortbay.util.StringUtil;
47 import org.mortbay.util.URIUtil;
48
49
50
51
52
53
54
55
56
57
58
59 public class HttpFields
60 {
61
62 public final static String __separators = ", \t";
63
64
65 private static String[] DAYS =
66 { "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
67 private static String[] MONTHS =
68 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "Jan"};
69
70
71
72
73
74
75 public static String formatDate(long date, boolean cookie)
76 {
77 StringBuffer buf = new StringBuffer(32);
78 GregorianCalendar gc = new GregorianCalendar(__GMT);
79 gc.setTimeInMillis(date);
80 formatDate(buf, gc, cookie);
81 return buf.toString();
82 }
83
84
85
86
87
88
89 public static String formatDate(Calendar calendar, boolean cookie)
90 {
91 StringBuffer buf = new StringBuffer(32);
92 formatDate(buf, calendar, cookie);
93 return buf.toString();
94 }
95
96
97
98
99
100
101 public static String formatDate(StringBuffer buf, long date, boolean cookie)
102 {
103 GregorianCalendar gc = new GregorianCalendar(__GMT);
104 gc.setTimeInMillis(date);
105 formatDate(buf, gc, cookie);
106 return buf.toString();
107 }
108
109
110
111
112
113
114 public static void formatDate(StringBuffer buf, Calendar calendar, boolean cookie)
115 {
116
117
118
119 int day_of_week = calendar.get(Calendar.DAY_OF_WEEK);
120 int day_of_month = calendar.get(Calendar.DAY_OF_MONTH);
121 int month = calendar.get(Calendar.MONTH);
122 int year = calendar.get(Calendar.YEAR);
123 int century = year / 100;
124 year = year % 100;
125
126 int epoch = (int) ((calendar.getTimeInMillis() / 1000) % (60 * 60 * 24));
127 int seconds = epoch % 60;
128 epoch = epoch / 60;
129 int minutes = epoch % 60;
130 int hours = epoch / 60;
131
132 buf.append(DAYS[day_of_week]);
133 buf.append(',');
134 buf.append(' ');
135 StringUtil.append2digits(buf, day_of_month);
136
137 if (cookie)
138 {
139 buf.append('-');
140 buf.append(MONTHS[month]);
141 buf.append('-');
142 StringUtil.append2digits(buf, year);
143 }
144 else
145 {
146 buf.append(' ');
147 buf.append(MONTHS[month]);
148 buf.append(' ');
149 StringUtil.append2digits(buf, century);
150 StringUtil.append2digits(buf, year);
151 }
152 buf.append(' ');
153 StringUtil.append2digits(buf, hours);
154 buf.append(':');
155 StringUtil.append2digits(buf, minutes);
156 buf.append(':');
157 StringUtil.append2digits(buf, seconds);
158 buf.append(" GMT");
159 }
160
161
162 private static TimeZone __GMT = TimeZone.getTimeZone("GMT");
163 public final static BufferDateCache __dateCache = new BufferDateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
164
165
166 private final static String __dateReceiveFmt[] =
167 { "EEE, dd MMM yyyy HH:mm:ss zzz",
168 "EEE, dd-MMM-yy HH:mm:ss",
169 "EEE MMM dd HH:mm:ss yyyy",
170
171 "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
172 "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
173 "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
174 "dd MMM yyyy HH:mm:ss", "dd-MMM-yy HH:mm:ss zzz", "dd-MMM-yy HH:mm:ss", "MMM dd HH:mm:ss yyyy zzz",
175 "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
176 "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
177 "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
178 };
179 private static int __dateReceiveInit=3;
180 private static SimpleDateFormat __dateReceive[];
181 static
182 {
183 __GMT.setID("GMT");
184 __dateCache.setTimeZone(__GMT);
185 __dateReceive = new SimpleDateFormat[__dateReceiveFmt.length];
186
187 for (int i = 0; i < __dateReceiveInit; i++)
188 {
189 __dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
190 __dateReceive[i].setTimeZone(__GMT);
191 }
192 }
193 public final static String __01Jan1970 = formatDate(0, false);
194 public final static Buffer __01Jan1970_BUFFER = new ByteArrayBuffer(__01Jan1970);
195
196
197 protected ArrayList<Field> _fields = new ArrayList<Field>(20);
198 protected int _revision;
199 protected HashMap _bufferMap = new HashMap(32);
200 protected SimpleDateFormat _dateReceive[] = new SimpleDateFormat[__dateReceive.length];
201 private StringBuffer _dateBuffer;
202 private Calendar _calendar;
203
204
205
206
207
208 public HttpFields()
209 {
210 }
211
212
213
214
215
216
217 public Enumeration getFieldNames()
218 {
219 final int revision=_revision;
220 return new Enumeration()
221 {
222 int i = 0;
223 Field field = null;
224
225 public boolean hasMoreElements()
226 {
227 if (field != null) return true;
228 while (i < _fields.size())
229 {
230 Field f = (Field) _fields.get(i++);
231 if (f != null && f._prev == null && f._revision == revision)
232 {
233 field = f;
234 return true;
235 }
236 }
237 return false;
238 }
239
240 public Object nextElement() throws NoSuchElementException
241 {
242 if (field != null || hasMoreElements())
243 {
244 String n = BufferUtil.to8859_1_String(field._name);
245 field = null;
246 return n;
247 }
248 throw new NoSuchElementException();
249 }
250 };
251 }
252
253
254
255
256
257 public Iterator getFields()
258 {
259 final int revision=_revision;
260 return new Iterator()
261 {
262 int i = 0;
263 Field field = null;
264
265 public boolean hasNext()
266 {
267 if (field != null) return true;
268 List<Field> fields=_fields;
269 while (fields!=null &&i < fields.size())
270 {
271 Field f = fields.get(i++);
272 if (f != null && f._revision == revision)
273 {
274 field = f;
275 return true;
276 }
277 }
278 return false;
279 }
280
281 public Object next()
282 {
283 if (field != null || hasNext())
284 {
285 final Field f = field;
286 field = null;
287 return f;
288 }
289 throw new NoSuchElementException();
290 }
291
292 public void remove()
293 {
294 throw new UnsupportedOperationException();
295 }
296 };
297 }
298
299
300 private Field getField(String name)
301 {
302 return (Field) _bufferMap.get(HttpHeaders.CACHE.lookup(name));
303 }
304
305
306 private Field getField(Buffer name)
307 {
308 return (Field) _bufferMap.get(name);
309 }
310
311
312 public boolean containsKey(Buffer name)
313 {
314 Field f = getField(name);
315 return (f != null && f._revision == _revision);
316 }
317
318
319 public boolean containsKey(String name)
320 {
321 Field f = getField(name);
322 return (f != null && f._revision == _revision);
323 }
324
325
326
327
328
329
330
331 public String getStringField(String name)
332 {
333
334 Field field = getField(name);
335 if (field != null && field._revision == _revision) return field.getValue();
336 return null;
337 }
338
339
340
341
342
343
344
345 public String getStringField(Buffer name)
346 {
347
348 Field field = getField(name);
349 if (field != null && field._revision == _revision)
350 return BufferUtil.to8859_1_String(field._value);
351 return null;
352 }
353
354
355
356
357
358
359
360 public Buffer get(Buffer name)
361 {
362 Field field = getField(name);
363 if (field != null && field._revision == _revision)
364 return field._value;
365 return null;
366 }
367
368
369
370
371
372
373
374
375 public Enumeration getValues(String name)
376 {
377 final Field field = getField(name);
378 if (field == null)
379 return null;
380 final int revision=_revision;
381
382 return new Enumeration()
383 {
384 Field f = field;
385
386 public boolean hasMoreElements()
387 {
388 while (f != null && f._revision != revision)
389 f = f._next;
390 return f != null;
391 }
392
393 public Object nextElement() throws NoSuchElementException
394 {
395 if (f == null) throw new NoSuchElementException();
396 Field n = f;
397 do
398 f = f._next;
399 while (f != null && f._revision != revision);
400 return n.getValue();
401 }
402 };
403 }
404
405
406
407
408
409
410
411
412 public Enumeration getValues(Buffer name)
413 {
414 final Field field = getField(name);
415 if (field == null)
416 return null;
417 final int revision=_revision;
418
419 return new Enumeration()
420 {
421 Field f = field;
422
423 public boolean hasMoreElements()
424 {
425 while (f != null && f._revision != revision)
426 f = f._next;
427 return f != null;
428 }
429
430 public Object nextElement() throws NoSuchElementException
431 {
432 if (f == null) throw new NoSuchElementException();
433 Field n = f;
434 f = f._next;
435 while (f != null && f._revision != revision)
436 f = f._next;
437 return n.getValue();
438 }
439 };
440 }
441
442
443
444
445
446
447
448
449
450
451
452 public Enumeration getValues(String name, final String separators)
453 {
454 final Enumeration e = getValues(name);
455 if (e == null)
456 return null;
457 return new Enumeration()
458 {
459 QuotedStringTokenizer tok = null;
460
461 public boolean hasMoreElements()
462 {
463 if (tok != null && tok.hasMoreElements()) return true;
464 while (e.hasMoreElements())
465 {
466 String value = (String) e.nextElement();
467 tok = new QuotedStringTokenizer(value, separators, false, false);
468 if (tok.hasMoreElements()) return true;
469 }
470 tok = null;
471 return false;
472 }
473
474 public Object nextElement() throws NoSuchElementException
475 {
476 if (!hasMoreElements()) throw new NoSuchElementException();
477 String next = (String) tok.nextElement();
478 if (next != null) next = next.trim();
479 return next;
480 }
481 };
482 }
483
484
485
486
487
488
489
490
491 public void put(String name, String value)
492 {
493 Buffer n = HttpHeaders.CACHE.lookup(name);
494 Buffer v = null;
495 if (value != null)
496 v = HttpHeaderValues.CACHE.lookup(value);
497 put(n, v, -1);
498 }
499
500
501
502
503
504
505
506
507 public void put(Buffer name, String value)
508 {
509 Buffer v = HttpHeaderValues.CACHE.lookup(value);
510 put(name, v, -1);
511 }
512
513
514
515
516
517
518
519
520 public void put(Buffer name, Buffer value)
521 {
522 put(name, value, -1);
523 }
524
525
526
527
528
529
530
531
532
533 public void put(Buffer name, Buffer value, long numValue)
534 {
535 if (value == null)
536 {
537 remove(name);
538 return;
539 }
540
541 if (!(name instanceof BufferCache.CachedBuffer)) name = HttpHeaders.CACHE.lookup(name);
542
543 Field field = (Field) _bufferMap.get(name);
544
545
546 if (field != null)
547 {
548 field.reset(value, numValue, _revision);
549 field = field._next;
550 while (field != null)
551 {
552 field.clear();
553 field = field._next;
554 }
555 return;
556 }
557 else
558 {
559
560 field = new Field(name, value, numValue, _revision);
561 _fields.add(field);
562 _bufferMap.put(field.getNameBuffer(), field);
563 }
564 }
565
566
567
568
569
570
571
572
573 public void put(String name, List list)
574 {
575 if (list == null || list.size() == 0)
576 {
577 remove(name);
578 return;
579 }
580 Buffer n = HttpHeaders.CACHE.lookup(name);
581
582 Object v = list.get(0);
583 if (v != null)
584 put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
585 else
586 remove(n);
587
588 if (list.size() > 1)
589 {
590 java.util.Iterator iter = list.iterator();
591 iter.next();
592 while (iter.hasNext())
593 {
594 v = iter.next();
595 if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
596 }
597 }
598 }
599
600
601
602
603
604
605
606
607
608
609
610 public void add(String name, String value) throws IllegalArgumentException
611 {
612 Buffer n = HttpHeaders.CACHE.lookup(name);
613 Buffer v = HttpHeaderValues.CACHE.lookup(value);
614 add(n, v, -1);
615 }
616
617
618
619
620
621
622
623
624
625
626
627 public void add(Buffer name, Buffer value) throws IllegalArgumentException
628 {
629 add(name, value, -1);
630 }
631
632
633
634
635
636
637
638
639
640
641
642 private void add(Buffer name, Buffer value, long numValue) throws IllegalArgumentException
643 {
644 if (value == null) throw new IllegalArgumentException("null value");
645
646 if (!(name instanceof BufferCache.CachedBuffer)) name = HttpHeaders.CACHE.lookup(name);
647
648 Field field = (Field) _bufferMap.get(name);
649 Field last = null;
650 if (field != null)
651 {
652 while (field != null && field._revision == _revision)
653 {
654 last = field;
655 field = field._next;
656 }
657 }
658
659 if (field != null)
660 field.reset(value, numValue, _revision);
661 else
662 {
663
664 field = new Field(name, value, numValue, _revision);
665
666
667 if (last != null)
668 {
669 field._prev = last;
670 last._next = field;
671 }
672 else
673 _bufferMap.put(field.getNameBuffer(), field);
674
675 _fields.add(field);
676 }
677 }
678
679
680
681
682
683
684
685 public void remove(String name)
686 {
687 remove(HttpHeaders.CACHE.lookup(name));
688 }
689
690
691
692
693
694
695
696 public void remove(Buffer name)
697 {
698 Field field = (Field) _bufferMap.get(name);
699
700 if (field != null)
701 {
702 while (field != null)
703 {
704 field.clear();
705 field = field._next;
706 }
707 }
708 }
709
710
711
712
713
714
715
716
717
718 public long getLongField(String name) throws NumberFormatException
719 {
720 Field field = getField(name);
721 if (field != null && field._revision == _revision) return field.getLongValue();
722
723 return -1L;
724 }
725
726
727
728
729
730
731
732
733
734 public long getLongField(Buffer name) throws NumberFormatException
735 {
736 Field field = getField(name);
737 if (field != null && field._revision == _revision) return field.getLongValue();
738 return -1L;
739 }
740
741
742
743
744
745
746
747
748 public long getDateField(String name)
749 {
750 Field field = getField(name);
751 if (field == null || field._revision != _revision) return -1;
752
753 if (field._numValue != -1) return field._numValue;
754
755 String val = valueParameters(BufferUtil.to8859_1_String(field._value), null);
756 if (val == null) return -1;
757
758
759
760 for (int i = 0; i < __dateReceiveInit; i++)
761 {
762 if (_dateReceive[i] == null) _dateReceive[i] = (SimpleDateFormat) __dateReceive[i].clone();
763
764 try
765 {
766 Date date = (Date) _dateReceive[i].parseObject(val);
767 return field._numValue = date.getTime();
768 }
769 catch (java.lang.Exception e)
770 {
771 }
772 }
773 if (val.endsWith(" GMT"))
774 {
775 val = val.substring(0, val.length() - 4);
776 for (int i = 0; i < __dateReceiveInit; i++)
777 {
778 try
779 {
780 Date date = (Date) _dateReceive[i].parseObject(val);
781 return field._numValue = date.getTime();
782 }
783 catch (java.lang.Exception e)
784 {
785 }
786 }
787 }
788
789
790
791 synchronized (__dateReceive)
792 {
793 for (int i = __dateReceiveInit; i < _dateReceive.length; i++)
794 {
795 if (_dateReceive[i] == null)
796 {
797 if (__dateReceive[i]==null)
798 {
799 __dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
800 __dateReceive[i].setTimeZone(__GMT);
801 }
802 _dateReceive[i] = (SimpleDateFormat) __dateReceive[i].clone();
803 }
804
805 try
806 {
807 Date date = (Date) _dateReceive[i].parseObject(val);
808 return field._numValue = date.getTime();
809 }
810 catch (java.lang.Exception e)
811 {
812 }
813 }
814 if (val.endsWith(" GMT"))
815 {
816 val = val.substring(0, val.length() - 4);
817 for (int i = 0; i < _dateReceive.length; i++)
818 {
819 try
820 {
821 Date date = (Date) _dateReceive[i].parseObject(val);
822 return field._numValue = date.getTime();
823 }
824 catch (java.lang.Exception e)
825 {
826 }
827 }
828 }
829 }
830
831
832 throw new IllegalArgumentException("Cannot convert date: " + val);
833 }
834
835
836
837
838
839
840
841
842 public void putLongField(Buffer name, long value)
843 {
844 Buffer v = BufferUtil.toBuffer(value);
845 put(name, v, value);
846 }
847
848
849
850
851
852
853
854
855 public void putLongField(String name, long value)
856 {
857 Buffer n = HttpHeaders.CACHE.lookup(name);
858 Buffer v = BufferUtil.toBuffer(value);
859 put(n, v, value);
860 }
861
862
863
864
865
866
867
868
869 public void addLongField(String name, long value)
870 {
871 Buffer n = HttpHeaders.CACHE.lookup(name);
872 Buffer v = BufferUtil.toBuffer(value);
873 add(n, v, value);
874 }
875
876
877
878
879
880
881
882
883 public void addLongField(Buffer name, long value)
884 {
885 Buffer v = BufferUtil.toBuffer(value);
886 add(name, v, value);
887 }
888
889
890
891
892
893
894
895
896 public void putDateField(Buffer name, long date)
897 {
898 if (_dateBuffer == null)
899 {
900 _dateBuffer = new StringBuffer(32);
901 _calendar = new GregorianCalendar(__GMT);
902 }
903 _dateBuffer.setLength(0);
904 _calendar.setTimeInMillis(date);
905 formatDate(_dateBuffer, _calendar, false);
906 Buffer v = new ByteArrayBuffer(_dateBuffer.toString());
907 put(name, v, date);
908 }
909
910
911
912
913
914
915
916
917 public void putDateField(String name, long date)
918 {
919 Buffer n = HttpHeaders.CACHE.lookup(name);
920 putDateField(n,date);
921 }
922
923
924
925
926
927
928
929
930 public void addDateField(String name, long date)
931 {
932 if (_dateBuffer == null)
933 {
934 _dateBuffer = new StringBuffer(32);
935 _calendar = new GregorianCalendar(__GMT);
936 }
937 _dateBuffer.setLength(0);
938 _calendar.setTimeInMillis(date);
939 formatDate(_dateBuffer, _calendar, false);
940 Buffer n = HttpHeaders.CACHE.lookup(name);
941 Buffer v = new ByteArrayBuffer(_dateBuffer.toString());
942 add(n, v, date);
943 }
944
945
946
947
948
949
950
951
952 public void addSetCookie(Cookie cookie)
953 {
954 String name = cookie.getName();
955 String value = cookie.getValue();
956 int version = cookie.getVersion();
957
958
959 if (name == null || name.length() == 0) throw new IllegalArgumentException("Bad cookie name");
960
961
962 StringBuffer buf = new StringBuffer(128);
963 String name_value_params = null;
964 synchronized (buf)
965 {
966 QuotedStringTokenizer.quoteIfNeeded(buf, name);
967 buf.append('=');
968 if (value != null && value.length() > 0)
969 QuotedStringTokenizer.quoteIfNeeded(buf, value);
970
971 if (version > 0)
972 {
973 buf.append(";Version=");
974 buf.append(version);
975 String comment = cookie.getComment();
976 if (comment != null && comment.length() > 0)
977 {
978 buf.append(";Comment=");
979 QuotedStringTokenizer.quoteIfNeeded(buf, comment);
980 }
981 }
982 String path = cookie.getPath();
983 if (path != null && path.length() > 0)
984 {
985 buf.append(";Path=");
986 buf.append(URIUtil.encodePath(path));
987 }
988 String domain = cookie.getDomain();
989 if (domain != null && domain.length() > 0)
990 {
991 buf.append(";Domain=");
992 buf.append(domain.toLowerCase());
993 }
994
995 long maxAge = cookie.getMaxAge();
996 if (maxAge >= 0)
997 {
998 if (version == 0)
999 {
1000 buf.append(";Expires=");
1001 if (maxAge == 0)
1002 buf.append(__01Jan1970);
1003 else
1004 formatDate(buf, System.currentTimeMillis() + 1000L * maxAge, true);
1005 }
1006 else
1007 {
1008 buf.append(";Max-Age=");
1009 buf.append(maxAge);
1010 }
1011 }
1012 else if (version > 0)
1013 {
1014 buf.append(";Discard");
1015 }
1016
1017 if (cookie.getSecure())
1018 {
1019 buf.append(";Secure");
1020 }
1021 if (cookie.isHttpOnly())
1022 buf.append(";HttpOnly");
1023
1024
1025 name_value_params = buf.toString();
1026 }
1027 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
1028 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params));
1029 }
1030
1031
1032 public void put(Buffer buffer) throws IOException
1033 {
1034 for (int i = 0; i < _fields.size(); i++)
1035 {
1036 Field field = (Field) _fields.get(i);
1037 if (field != null && field._revision == _revision) field.put(buffer);
1038 }
1039 BufferUtil.putCRLF(buffer);
1040 }
1041
1042
1043 public String toString()
1044 {
1045 try
1046 {
1047 ByteArrayBuffer buffer = new ByteArrayBuffer(4096);
1048 put(buffer);
1049 return BufferUtil.to8859_1_String(buffer);
1050 }
1051 catch (Exception e)
1052 {
1053 e.printStackTrace();
1054 }
1055
1056 return null;
1057 }
1058
1059
1060
1061
1062
1063 public void clear()
1064 {
1065 _revision++;
1066 if (_revision > 1000000)
1067 {
1068 _revision = 0;
1069 for (int i = _fields.size(); i-- > 0;)
1070 {
1071 Field field = (Field) _fields.get(i);
1072 if (field != null) field.clear();
1073 }
1074 }
1075 }
1076
1077
1078
1079
1080
1081 public void destroy()
1082 {
1083 if (_fields != null)
1084 {
1085 for (int i = _fields.size(); i-- > 0;)
1086 {
1087 Field field = (Field) _fields.get(i);
1088 if (field != null) field.destroy();
1089 }
1090 }
1091 _fields = null;
1092 _dateBuffer = null;
1093 _calendar = null;
1094 _dateReceive = null;
1095 }
1096
1097
1098
1099
1100
1101
1102
1103
1104 public void add(HttpFields fields)
1105 {
1106 if (fields == null) return;
1107
1108 Enumeration e = fields.getFieldNames();
1109 while (e.hasMoreElements())
1110 {
1111 String name = (String) e.nextElement();
1112 Enumeration values = fields.getValues(name);
1113 while (values.hasMoreElements())
1114 add(name, (String) values.nextElement());
1115 }
1116 }
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 public static String valueParameters(String value, Map parameters)
1134 {
1135 if (value == null) return null;
1136
1137 int i = value.indexOf(';');
1138 if (i < 0) return value;
1139 if (parameters == null) return value.substring(0, i).trim();
1140
1141 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
1142 while (tok1.hasMoreTokens())
1143 {
1144 String token = tok1.nextToken();
1145 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
1146 if (tok2.hasMoreTokens())
1147 {
1148 String paramName = tok2.nextToken();
1149 String paramVal = null;
1150 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1151 parameters.put(paramName, paramVal);
1152 }
1153 }
1154
1155 return value.substring(0, i).trim();
1156 }
1157
1158
1159 private static Float __one = new Float("1.0");
1160 private static Float __zero = new Float("0.0");
1161 private static StringMap __qualities = new StringMap();
1162 static
1163 {
1164 __qualities.put(null, __one);
1165 __qualities.put("1.0", __one);
1166 __qualities.put("1", __one);
1167 __qualities.put("0.9", new Float("0.9"));
1168 __qualities.put("0.8", new Float("0.8"));
1169 __qualities.put("0.7", new Float("0.7"));
1170 __qualities.put("0.66", new Float("0.66"));
1171 __qualities.put("0.6", new Float("0.6"));
1172 __qualities.put("0.5", new Float("0.5"));
1173 __qualities.put("0.4", new Float("0.4"));
1174 __qualities.put("0.33", new Float("0.33"));
1175 __qualities.put("0.3", new Float("0.3"));
1176 __qualities.put("0.2", new Float("0.2"));
1177 __qualities.put("0.1", new Float("0.1"));
1178 __qualities.put("0", __zero);
1179 __qualities.put("0.0", __zero);
1180 }
1181
1182
1183 public static Float getQuality(String value)
1184 {
1185 if (value == null) return __zero;
1186
1187 int qe = value.indexOf(";");
1188 if (qe++ < 0 || qe == value.length()) return __one;
1189
1190 if (value.charAt(qe++) == 'q')
1191 {
1192 qe++;
1193 Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe);
1194 if (entry != null) return (Float) entry.getValue();
1195 }
1196
1197 HashMap params = new HashMap(3);
1198 valueParameters(value, params);
1199 String qs = (String) params.get("q");
1200 Float q = (Float) __qualities.get(qs);
1201 if (q == null)
1202 {
1203 try
1204 {
1205 q = new Float(qs);
1206 }
1207 catch (Exception e)
1208 {
1209 q = __one;
1210 }
1211 }
1212 return q;
1213 }
1214
1215
1216
1217
1218
1219
1220
1221
1222 public static List qualityList(Enumeration e)
1223 {
1224 if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST;
1225
1226 Object list = null;
1227 Object qual = null;
1228
1229
1230 while (e.hasMoreElements())
1231 {
1232 String v = e.nextElement().toString();
1233 Float q = getQuality(v);
1234
1235 if (q.floatValue() >= 0.001)
1236 {
1237 list = LazyList.add(list, v);
1238 qual = LazyList.add(qual, q);
1239 }
1240 }
1241
1242 List vl = LazyList.getList(list, false);
1243 if (vl.size() < 2) return vl;
1244
1245 List ql = LazyList.getList(qual, false);
1246
1247
1248 Float last = __zero;
1249 for (int i = vl.size(); i-- > 0;)
1250 {
1251 Float q = (Float) ql.get(i);
1252 if (last.compareTo(q) > 0)
1253 {
1254 Object tmp = vl.get(i);
1255 vl.set(i, vl.get(i + 1));
1256 vl.set(i + 1, tmp);
1257 ql.set(i, ql.get(i + 1));
1258 ql.set(i + 1, q);
1259 last = __zero;
1260 i = vl.size();
1261 continue;
1262 }
1263 last = q;
1264 }
1265 ql.clear();
1266 return vl;
1267 }
1268
1269
1270
1271
1272 public static final class Field
1273 {
1274 private Buffer _name;
1275 private Buffer _value;
1276 private String _stringValue;
1277 private long _numValue;
1278 private Field _next;
1279 private Field _prev;
1280 private int _revision;
1281
1282
1283 private Field(Buffer name, Buffer value, long numValue, int revision)
1284 {
1285 _name = name.asImmutableBuffer();
1286 _value = value.isImmutable() ? value : new View(value);
1287 _next = null;
1288 _prev = null;
1289 _revision = revision;
1290 _numValue = numValue;
1291 _stringValue=null;
1292 }
1293
1294
1295 private void clear()
1296 {
1297 _revision = -1;
1298 }
1299
1300
1301 private void destroy()
1302 {
1303 _name = null;
1304 _value = null;
1305 _next = null;
1306 _prev = null;
1307 _stringValue=null;
1308 }
1309
1310
1311
1312
1313
1314
1315 private void reset(Buffer value, long numValue, int revision)
1316 {
1317 _revision = revision;
1318 if (_value == null)
1319 {
1320 _value = value.isImmutable() ? value : new View(value);
1321 _numValue = numValue;
1322 _stringValue=null;
1323 }
1324 else if (value.isImmutable())
1325 {
1326 _value = value;
1327 _numValue = numValue;
1328 _stringValue=null;
1329 }
1330 else
1331 {
1332 if (_value instanceof View)
1333 ((View) _value).update(value);
1334 else
1335 _value = new View(value);
1336 _numValue = numValue;
1337
1338
1339 if (_stringValue!=null)
1340 {
1341 if (_stringValue.length()!=value.length())
1342 _stringValue=null;
1343 else
1344 {
1345 for (int i=value.length();i-->0;)
1346 {
1347 if (value.peek(value.getIndex()+i)!=_stringValue.charAt(i))
1348 {
1349 _stringValue=null;
1350 break;
1351 }
1352 }
1353 }
1354 }
1355 }
1356 }
1357
1358
1359
1360
1361 public void put(Buffer buffer) throws IOException
1362 {
1363 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
1364 if (o>=0)
1365 buffer.put(_name);
1366 else
1367 {
1368 int s=_name.getIndex();
1369 int e=_name.putIndex();
1370 while (s<e)
1371 {
1372 byte b=_name.peek(s++);
1373 switch(b)
1374 {
1375 case '\r':
1376 case '\n':
1377 case ':' :
1378 continue;
1379 default:
1380 buffer.put(b);
1381 }
1382 }
1383 }
1384
1385 buffer.put((byte) ':');
1386 buffer.put((byte) ' ');
1387
1388 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1;
1389 if (o>=0 || _numValue>=0)
1390 buffer.put(_value);
1391 else
1392 {
1393 int s=_value.getIndex();
1394 int e=_value.putIndex();
1395 while (s<e)
1396 {
1397 byte b=_value.peek(s++);
1398 switch(b)
1399 {
1400 case '\r':
1401 case '\n':
1402 continue;
1403 default:
1404 buffer.put(b);
1405 }
1406 }
1407 }
1408
1409 BufferUtil.putCRLF(buffer);
1410 }
1411
1412
1413 public String getName()
1414 {
1415 return BufferUtil.to8859_1_String(_name);
1416 }
1417
1418
1419 Buffer getNameBuffer()
1420 {
1421 return _name;
1422 }
1423
1424
1425 public int getNameOrdinal()
1426 {
1427 return HttpHeaders.CACHE.getOrdinal(_name);
1428 }
1429
1430
1431 public String getValue()
1432 {
1433 if (_stringValue==null)
1434 _stringValue=BufferUtil.to8859_1_String(_value);
1435 return _stringValue;
1436 }
1437
1438
1439 public Buffer getValueBuffer()
1440 {
1441 return _value;
1442 }
1443
1444
1445 public int getValueOrdinal()
1446 {
1447 return HttpHeaderValues.CACHE.getOrdinal(_value);
1448 }
1449
1450
1451 public int getIntValue()
1452 {
1453 return (int) getLongValue();
1454 }
1455
1456
1457 public long getLongValue()
1458 {
1459 if (_numValue == -1) _numValue = BufferUtil.toLong(_value);
1460 return _numValue;
1461 }
1462
1463
1464 public String toString()
1465 {
1466 return ("[" + (_prev == null ? "" : "<-") + getName() + "="+_revision+"=" + _value + (_next == null ? "" : "->") + "]");
1467 }
1468 }
1469
1470 }