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)
336 return field.getValue();
337 return null;
338 }
339
340
341
342
343
344
345
346 public String getStringField(Buffer name)
347 {
348
349 Field field = getField(name);
350 if (field != null && field._revision == _revision)
351 return BufferUtil.to8859_1_String(field._value);
352 return null;
353 }
354
355
356
357
358
359
360
361 public Buffer get(Buffer name)
362 {
363 Field field = getField(name);
364 if (field != null && field._revision == _revision)
365 return field._value;
366 return null;
367 }
368
369
370
371
372
373
374
375
376 public Enumeration getValues(String name)
377 {
378 final Field field = getField(name);
379 if (field == null)
380 return null;
381 final int revision=_revision;
382
383 return new Enumeration()
384 {
385 Field f = field;
386
387 public boolean hasMoreElements()
388 {
389 while (f != null && f._revision != revision)
390 f = f._next;
391 return f != null;
392 }
393
394 public Object nextElement() throws NoSuchElementException
395 {
396 if (f == null) throw new NoSuchElementException();
397 Field n = f;
398 do
399 f = f._next;
400 while (f != null && f._revision != revision);
401 return n.getValue();
402 }
403 };
404 }
405
406
407
408
409
410
411
412
413 public Enumeration getValues(Buffer name)
414 {
415 final Field field = getField(name);
416 if (field == null)
417 return null;
418 final int revision=_revision;
419
420 return new Enumeration()
421 {
422 Field f = field;
423
424 public boolean hasMoreElements()
425 {
426 while (f != null && f._revision != revision)
427 f = f._next;
428 return f != null;
429 }
430
431 public Object nextElement() throws NoSuchElementException
432 {
433 if (f == null) throw new NoSuchElementException();
434 Field n = f;
435 f = f._next;
436 while (f != null && f._revision != revision)
437 f = f._next;
438 return n.getValue();
439 }
440 };
441 }
442
443
444
445
446
447
448
449
450
451
452
453 public Enumeration getValues(String name, final String separators)
454 {
455 final Enumeration e = getValues(name);
456 if (e == null)
457 return null;
458 return new Enumeration()
459 {
460 QuotedStringTokenizer tok = null;
461
462 public boolean hasMoreElements()
463 {
464 if (tok != null && tok.hasMoreElements()) return true;
465 while (e.hasMoreElements())
466 {
467 String value = (String) e.nextElement();
468 tok = new QuotedStringTokenizer(value, separators, false, false);
469 if (tok.hasMoreElements()) return true;
470 }
471 tok = null;
472 return false;
473 }
474
475 public Object nextElement() throws NoSuchElementException
476 {
477 if (!hasMoreElements()) throw new NoSuchElementException();
478 String next = (String) tok.nextElement();
479 if (next != null) next = next.trim();
480 return next;
481 }
482 };
483 }
484
485
486
487
488
489
490
491
492 public void put(String name, String value)
493 {
494 Buffer n = HttpHeaders.CACHE.lookup(name);
495 Buffer v = null;
496 if (value != null)
497 v = HttpHeaderValues.CACHE.lookup(value);
498 put(n, v, -1);
499 }
500
501
502
503
504
505
506
507
508 public void put(Buffer name, String value)
509 {
510 Buffer v = HttpHeaderValues.CACHE.lookup(value);
511 put(name, v, -1);
512 }
513
514
515
516
517
518
519
520
521 public void put(Buffer name, Buffer value)
522 {
523 put(name, value, -1);
524 }
525
526
527
528
529
530
531
532
533
534 public void put(Buffer name, Buffer value, long numValue)
535 {
536 if (value == null)
537 {
538 remove(name);
539 return;
540 }
541
542 if (!(name instanceof BufferCache.CachedBuffer)) name = HttpHeaders.CACHE.lookup(name);
543
544 Field field = (Field) _bufferMap.get(name);
545
546
547 if (field != null)
548 {
549 field.reset(value, numValue, _revision);
550 field = field._next;
551 while (field != null)
552 {
553 field.clear();
554 field = field._next;
555 }
556 return;
557 }
558 else
559 {
560
561 field = new Field(name, value, numValue, _revision);
562 _fields.add(field);
563 _bufferMap.put(field.getNameBuffer(), field);
564 }
565 }
566
567
568
569
570
571
572
573
574 public void put(String name, List list)
575 {
576 if (list == null || list.size() == 0)
577 {
578 remove(name);
579 return;
580 }
581 Buffer n = HttpHeaders.CACHE.lookup(name);
582
583 Object v = list.get(0);
584 if (v != null)
585 put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
586 else
587 remove(n);
588
589 if (list.size() > 1)
590 {
591 java.util.Iterator iter = list.iterator();
592 iter.next();
593 while (iter.hasNext())
594 {
595 v = iter.next();
596 if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
597 }
598 }
599 }
600
601
602
603
604
605
606
607
608
609
610
611 public void add(String name, String value) throws IllegalArgumentException
612 {
613 Buffer n = HttpHeaders.CACHE.lookup(name);
614 Buffer v = HttpHeaderValues.CACHE.lookup(value);
615 add(n, v, -1);
616 }
617
618
619
620
621
622
623
624
625
626
627
628 public void add(Buffer name, Buffer value) throws IllegalArgumentException
629 {
630 add(name, value, -1);
631 }
632
633
634
635
636
637
638
639
640
641
642
643 private void add(Buffer name, Buffer value, long numValue) throws IllegalArgumentException
644 {
645 if (value == null) throw new IllegalArgumentException("null value");
646
647 if (!(name instanceof BufferCache.CachedBuffer)) name = HttpHeaders.CACHE.lookup(name);
648
649 Field field = (Field) _bufferMap.get(name);
650 Field last = null;
651 if (field != null)
652 {
653 while (field != null && field._revision == _revision)
654 {
655 last = field;
656 field = field._next;
657 }
658 }
659
660 if (field != null)
661 field.reset(value, numValue, _revision);
662 else
663 {
664
665 field = new Field(name, value, numValue, _revision);
666
667
668 if (last != null)
669 {
670 field._prev = last;
671 last._next = field;
672 }
673 else
674 _bufferMap.put(field.getNameBuffer(), field);
675
676 _fields.add(field);
677 }
678 }
679
680
681
682
683
684
685
686 public void remove(String name)
687 {
688 remove(HttpHeaders.CACHE.lookup(name));
689 }
690
691
692
693
694
695
696
697 public void remove(Buffer name)
698 {
699 Field field = (Field) _bufferMap.get(name);
700
701 if (field != null)
702 {
703 while (field != null)
704 {
705 field.clear();
706 field = field._next;
707 }
708 }
709 }
710
711
712
713
714
715
716
717
718
719 public long getLongField(String name) throws NumberFormatException
720 {
721 Field field = getField(name);
722 if (field != null && field._revision == _revision) return field.getLongValue();
723
724 return -1L;
725 }
726
727
728
729
730
731
732
733
734
735 public long getLongField(Buffer name) throws NumberFormatException
736 {
737 Field field = getField(name);
738 if (field != null && field._revision == _revision) return field.getLongValue();
739 return -1L;
740 }
741
742
743
744
745
746
747
748
749 public long getDateField(String name)
750 {
751 Field field = getField(name);
752 if (field == null || field._revision != _revision) return -1;
753
754 if (field._numValue != -1) return field._numValue;
755
756 String val = valueParameters(BufferUtil.to8859_1_String(field._value), null);
757 if (val == null) return -1;
758
759
760
761 for (int i = 0; i < __dateReceiveInit; i++)
762 {
763 if (_dateReceive[i] == null) _dateReceive[i] = (SimpleDateFormat) __dateReceive[i].clone();
764
765 try
766 {
767 Date date = (Date) _dateReceive[i].parseObject(val);
768 return field._numValue = date.getTime();
769 }
770 catch (java.lang.Exception e)
771 {
772 }
773 }
774 if (val.endsWith(" GMT"))
775 {
776 val = val.substring(0, val.length() - 4);
777 for (int i = 0; i < __dateReceiveInit; i++)
778 {
779 try
780 {
781 Date date = (Date) _dateReceive[i].parseObject(val);
782 return field._numValue = date.getTime();
783 }
784 catch (java.lang.Exception e)
785 {
786 }
787 }
788 }
789
790
791
792 synchronized (__dateReceive)
793 {
794 for (int i = __dateReceiveInit; i < _dateReceive.length; i++)
795 {
796 if (_dateReceive[i] == null)
797 {
798 if (__dateReceive[i]==null)
799 {
800 __dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
801 __dateReceive[i].setTimeZone(__GMT);
802 }
803 _dateReceive[i] = (SimpleDateFormat) __dateReceive[i].clone();
804 }
805
806 try
807 {
808 Date date = (Date) _dateReceive[i].parseObject(val);
809 return field._numValue = date.getTime();
810 }
811 catch (java.lang.Exception e)
812 {
813 }
814 }
815 if (val.endsWith(" GMT"))
816 {
817 val = val.substring(0, val.length() - 4);
818 for (int i = 0; i < _dateReceive.length; i++)
819 {
820 try
821 {
822 Date date = (Date) _dateReceive[i].parseObject(val);
823 return field._numValue = date.getTime();
824 }
825 catch (java.lang.Exception e)
826 {
827 }
828 }
829 }
830 }
831
832
833 throw new IllegalArgumentException("Cannot convert date: " + val);
834 }
835
836
837
838
839
840
841
842
843 public void putLongField(Buffer name, long value)
844 {
845 Buffer v = BufferUtil.toBuffer(value);
846 put(name, v, value);
847 }
848
849
850
851
852
853
854
855
856 public void putLongField(String name, long value)
857 {
858 Buffer n = HttpHeaders.CACHE.lookup(name);
859 Buffer v = BufferUtil.toBuffer(value);
860 put(n, v, value);
861 }
862
863
864
865
866
867
868
869
870 public void addLongField(String name, long value)
871 {
872 Buffer n = HttpHeaders.CACHE.lookup(name);
873 Buffer v = BufferUtil.toBuffer(value);
874 add(n, v, value);
875 }
876
877
878
879
880
881
882
883
884 public void addLongField(Buffer name, long value)
885 {
886 Buffer v = BufferUtil.toBuffer(value);
887 add(name, v, value);
888 }
889
890
891
892
893
894
895
896
897 public void putDateField(Buffer name, long date)
898 {
899 if (_dateBuffer == null)
900 {
901 _dateBuffer = new StringBuffer(32);
902 _calendar = new GregorianCalendar(__GMT);
903 }
904 _dateBuffer.setLength(0);
905 _calendar.setTimeInMillis(date);
906 formatDate(_dateBuffer, _calendar, false);
907 Buffer v = new ByteArrayBuffer(_dateBuffer.toString());
908 put(name, v, date);
909 }
910
911
912
913
914
915
916
917
918 public void putDateField(String name, long date)
919 {
920 Buffer n = HttpHeaders.CACHE.lookup(name);
921 putDateField(n,date);
922 }
923
924
925
926
927
928
929
930
931 public void addDateField(String name, long date)
932 {
933 if (_dateBuffer == null)
934 {
935 _dateBuffer = new StringBuffer(32);
936 _calendar = new GregorianCalendar(__GMT);
937 }
938 _dateBuffer.setLength(0);
939 _calendar.setTimeInMillis(date);
940 formatDate(_dateBuffer, _calendar, false);
941 Buffer n = HttpHeaders.CACHE.lookup(name);
942 Buffer v = new ByteArrayBuffer(_dateBuffer.toString());
943 add(n, v, date);
944 }
945
946
947
948
949
950
951
952
953 public void addSetCookie(Cookie cookie)
954 {
955 String name = cookie.getName();
956 String value = cookie.getValue();
957 int version = cookie.getVersion();
958
959
960 if (name == null || name.length() == 0) throw new IllegalArgumentException("Bad cookie name");
961
962
963 StringBuffer buf = new StringBuffer(128);
964 String name_value_params = null;
965 synchronized (buf)
966 {
967 QuotedStringTokenizer.quoteIfNeeded(buf, name);
968 buf.append('=');
969 if (value != null && value.length() > 0)
970 QuotedStringTokenizer.quoteIfNeeded(buf, value);
971
972 if (version > 0)
973 {
974 buf.append(";Version=");
975 buf.append(version);
976 String comment = cookie.getComment();
977 if (comment != null && comment.length() > 0)
978 {
979 buf.append(";Comment=");
980 QuotedStringTokenizer.quoteIfNeeded(buf, comment);
981 }
982 }
983 String path = cookie.getPath();
984 if (path != null && path.length() > 0)
985 {
986 buf.append(";Path=");
987 buf.append(URIUtil.encodePath(path));
988 }
989 String domain = cookie.getDomain();
990 if (domain != null && domain.length() > 0)
991 {
992 buf.append(";Domain=");
993 buf.append(domain.toLowerCase());
994 }
995
996 long maxAge = cookie.getMaxAge();
997 if (maxAge >= 0)
998 {
999 if (version == 0)
1000 {
1001 buf.append(";Expires=");
1002 if (maxAge == 0)
1003 buf.append(__01Jan1970);
1004 else
1005 formatDate(buf, System.currentTimeMillis() + 1000L * maxAge, true);
1006 }
1007 else
1008 {
1009 buf.append(";Max-Age=");
1010 buf.append(maxAge);
1011 }
1012 }
1013 else if (version > 0)
1014 {
1015 buf.append(";Discard");
1016 }
1017
1018 if (cookie.getSecure())
1019 {
1020 buf.append(";Secure");
1021 }
1022 if (cookie.isHttpOnly())
1023 buf.append(";HttpOnly");
1024
1025
1026 name_value_params = buf.toString();
1027 }
1028 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
1029 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params));
1030 }
1031
1032
1033 public void put(Buffer buffer) throws IOException
1034 {
1035 for (int i = 0; i < _fields.size(); i++)
1036 {
1037 Field field = (Field) _fields.get(i);
1038 if (field != null && field._revision == _revision) field.put(buffer);
1039 }
1040 BufferUtil.putCRLF(buffer);
1041 }
1042
1043
1044 public String toString()
1045 {
1046 try
1047 {
1048 ByteArrayBuffer buffer = new ByteArrayBuffer(4096);
1049 put(buffer);
1050 return BufferUtil.to8859_1_String(buffer);
1051 }
1052 catch (Exception e)
1053 {
1054 e.printStackTrace();
1055 }
1056
1057 return null;
1058 }
1059
1060
1061
1062
1063
1064 public void clear()
1065 {
1066 _revision++;
1067 if (_revision > 1000000)
1068 {
1069 _revision = 0;
1070 for (int i = _fields.size(); i-- > 0;)
1071 {
1072 Field field = (Field) _fields.get(i);
1073 if (field != null) field.clear();
1074 }
1075 }
1076 }
1077
1078
1079
1080
1081
1082 public void destroy()
1083 {
1084 if (_fields != null)
1085 {
1086 for (int i = _fields.size(); i-- > 0;)
1087 {
1088 Field field = (Field) _fields.get(i);
1089 if (field != null) field.destroy();
1090 }
1091 }
1092 _fields = null;
1093 _dateBuffer = null;
1094 _calendar = null;
1095 _dateReceive = null;
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105 public void add(HttpFields fields)
1106 {
1107 if (fields == null) return;
1108
1109 Enumeration e = fields.getFieldNames();
1110 while (e.hasMoreElements())
1111 {
1112 String name = (String) e.nextElement();
1113 Enumeration values = fields.getValues(name);
1114 while (values.hasMoreElements())
1115 add(name, (String) values.nextElement());
1116 }
1117 }
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134 public static String valueParameters(String value, Map parameters)
1135 {
1136 if (value == null) return null;
1137
1138 int i = value.indexOf(';');
1139 if (i < 0) return value;
1140 if (parameters == null) return value.substring(0, i).trim();
1141
1142 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
1143 while (tok1.hasMoreTokens())
1144 {
1145 String token = tok1.nextToken();
1146 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
1147 if (tok2.hasMoreTokens())
1148 {
1149 String paramName = tok2.nextToken();
1150 String paramVal = null;
1151 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1152 parameters.put(paramName, paramVal);
1153 }
1154 }
1155
1156 return value.substring(0, i).trim();
1157 }
1158
1159
1160 private static Float __one = new Float("1.0");
1161 private static Float __zero = new Float("0.0");
1162 private static StringMap __qualities = new StringMap();
1163 static
1164 {
1165 __qualities.put(null, __one);
1166 __qualities.put("1.0", __one);
1167 __qualities.put("1", __one);
1168 __qualities.put("0.9", new Float("0.9"));
1169 __qualities.put("0.8", new Float("0.8"));
1170 __qualities.put("0.7", new Float("0.7"));
1171 __qualities.put("0.66", new Float("0.66"));
1172 __qualities.put("0.6", new Float("0.6"));
1173 __qualities.put("0.5", new Float("0.5"));
1174 __qualities.put("0.4", new Float("0.4"));
1175 __qualities.put("0.33", new Float("0.33"));
1176 __qualities.put("0.3", new Float("0.3"));
1177 __qualities.put("0.2", new Float("0.2"));
1178 __qualities.put("0.1", new Float("0.1"));
1179 __qualities.put("0", __zero);
1180 __qualities.put("0.0", __zero);
1181 }
1182
1183
1184 public static Float getQuality(String value)
1185 {
1186 if (value == null) return __zero;
1187
1188 int qe = value.indexOf(";");
1189 if (qe++ < 0 || qe == value.length()) return __one;
1190
1191 if (value.charAt(qe++) == 'q')
1192 {
1193 qe++;
1194 Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe);
1195 if (entry != null) return (Float) entry.getValue();
1196 }
1197
1198 HashMap params = new HashMap(3);
1199 valueParameters(value, params);
1200 String qs = (String) params.get("q");
1201 Float q = (Float) __qualities.get(qs);
1202 if (q == null)
1203 {
1204 try
1205 {
1206 q = new Float(qs);
1207 }
1208 catch (Exception e)
1209 {
1210 q = __one;
1211 }
1212 }
1213 return q;
1214 }
1215
1216
1217
1218
1219
1220
1221
1222
1223 public static List qualityList(Enumeration e)
1224 {
1225 if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST;
1226
1227 Object list = null;
1228 Object qual = null;
1229
1230
1231 while (e.hasMoreElements())
1232 {
1233 String v = e.nextElement().toString();
1234 Float q = getQuality(v);
1235
1236 if (q.floatValue() >= 0.001)
1237 {
1238 list = LazyList.add(list, v);
1239 qual = LazyList.add(qual, q);
1240 }
1241 }
1242
1243 List vl = LazyList.getList(list, false);
1244 if (vl.size() < 2) return vl;
1245
1246 List ql = LazyList.getList(qual, false);
1247
1248
1249 Float last = __zero;
1250 for (int i = vl.size(); i-- > 0;)
1251 {
1252 Float q = (Float) ql.get(i);
1253 if (last.compareTo(q) > 0)
1254 {
1255 Object tmp = vl.get(i);
1256 vl.set(i, vl.get(i + 1));
1257 vl.set(i + 1, tmp);
1258 ql.set(i, ql.get(i + 1));
1259 ql.set(i + 1, q);
1260 last = __zero;
1261 i = vl.size();
1262 continue;
1263 }
1264 last = q;
1265 }
1266 ql.clear();
1267 return vl;
1268 }
1269
1270
1271
1272
1273 public static final class Field
1274 {
1275 private Buffer _name;
1276 private Buffer _value;
1277 private String _stringValue;
1278 private long _numValue;
1279 private Field _next;
1280 private Field _prev;
1281 private int _revision;
1282
1283
1284 private Field(Buffer name, Buffer value, long numValue, int revision)
1285 {
1286 _name = name.asImmutableBuffer();
1287 _value = value.isImmutable() ? value : new View(value);
1288 _next = null;
1289 _prev = null;
1290 _revision = revision;
1291 _numValue = numValue;
1292 _stringValue=null;
1293 }
1294
1295
1296 private void clear()
1297 {
1298 _revision = -1;
1299 }
1300
1301
1302 private void destroy()
1303 {
1304 _name = null;
1305 _value = null;
1306 _next = null;
1307 _prev = null;
1308 _stringValue=null;
1309 }
1310
1311
1312
1313
1314
1315
1316 private void reset(Buffer value, long numValue, int revision)
1317 {
1318 _revision = revision;
1319 if (_value == null)
1320 {
1321 _value = value.isImmutable() ? value : new View(value);
1322 _numValue = numValue;
1323 _stringValue=null;
1324 }
1325 else if (value.isImmutable())
1326 {
1327 _value = value;
1328 _numValue = numValue;
1329 _stringValue=null;
1330 }
1331 else
1332 {
1333 if (_value instanceof View)
1334 ((View) _value).update(value);
1335 else
1336 _value = new View(value);
1337 _numValue = numValue;
1338
1339
1340 if (_stringValue!=null)
1341 {
1342 if (_stringValue.length()!=value.length())
1343 _stringValue=null;
1344 else
1345 {
1346 for (int i=value.length();i-->0;)
1347 {
1348 if (value.peek(value.getIndex()+i)!=_stringValue.charAt(i))
1349 {
1350 _stringValue=null;
1351 break;
1352 }
1353 }
1354 }
1355 }
1356 }
1357 }
1358
1359
1360
1361
1362 public void put(Buffer buffer) throws IOException
1363 {
1364 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
1365 if (o>=0)
1366 buffer.put(_name);
1367 else
1368 {
1369 int s=_name.getIndex();
1370 int e=_name.putIndex();
1371 while (s<e)
1372 {
1373 byte b=_name.peek(s++);
1374 switch(b)
1375 {
1376 case '\r':
1377 case '\n':
1378 case ':' :
1379 continue;
1380 default:
1381 buffer.put(b);
1382 }
1383 }
1384 }
1385
1386 buffer.put((byte) ':');
1387 buffer.put((byte) ' ');
1388
1389 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1;
1390 if (o>=0 || _numValue>=0)
1391 buffer.put(_value);
1392 else
1393 {
1394 int s=_value.getIndex();
1395 int e=_value.putIndex();
1396 while (s<e)
1397 {
1398 byte b=_value.peek(s++);
1399 switch(b)
1400 {
1401 case '\r':
1402 case '\n':
1403 continue;
1404 default:
1405 buffer.put(b);
1406 }
1407 }
1408 }
1409
1410 BufferUtil.putCRLF(buffer);
1411 }
1412
1413
1414 public String getName()
1415 {
1416 return BufferUtil.to8859_1_String(_name);
1417 }
1418
1419
1420 Buffer getNameBuffer()
1421 {
1422 return _name;
1423 }
1424
1425
1426 public int getNameOrdinal()
1427 {
1428 return HttpHeaders.CACHE.getOrdinal(_name);
1429 }
1430
1431
1432 public String getValue()
1433 {
1434 if (_stringValue==null)
1435 {
1436 _stringValue=(_value instanceof CachedBuffer)
1437 ?_value.toString()
1438 :BufferUtil.to8859_1_String(_value);
1439 }
1440 return _stringValue;
1441 }
1442
1443
1444 public Buffer getValueBuffer()
1445 {
1446 return _value;
1447 }
1448
1449
1450 public int getValueOrdinal()
1451 {
1452 return HttpHeaderValues.CACHE.getOrdinal(_value);
1453 }
1454
1455
1456 public int getIntValue()
1457 {
1458 return (int) getLongValue();
1459 }
1460
1461
1462 public long getLongValue()
1463 {
1464 if (_numValue == -1) _numValue = BufferUtil.toLong(_value);
1465 return _numValue;
1466 }
1467
1468
1469 public String toString()
1470 {
1471 return ("[" + (_prev == null ? "" : "<-") + getName() + "="+_revision+"=" + _value + (_next == null ? "" : "->") + "]");
1472 }
1473 }
1474
1475 }