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