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, century);
143 StringUtil.append2digits(buf, year);
144 }
145 else
146 {
147 buf.append(' ');
148 buf.append(MONTHS[month]);
149 buf.append(' ');
150 StringUtil.append2digits(buf, century);
151 StringUtil.append2digits(buf, year);
152 }
153 buf.append(' ');
154 StringUtil.append2digits(buf, hours);
155 buf.append(':');
156 StringUtil.append2digits(buf, minutes);
157 buf.append(':');
158 StringUtil.append2digits(buf, seconds);
159 buf.append(" GMT");
160 }
161
162
163 private static TimeZone __GMT = TimeZone.getTimeZone("GMT");
164 public final static BufferDateCache __dateCache = new BufferDateCache("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
165
166
167 private final static String __dateReceiveFmt[] =
168 { "EEE, dd MMM yyyy HH:mm:ss zzz",
169 "EEE, dd-MMM-yy HH:mm:ss",
170 "EEE MMM dd HH:mm:ss yyyy",
171
172 "EEE, dd MMM yyyy HH:mm:ss", "EEE dd MMM yyyy HH:mm:ss zzz",
173 "EEE dd MMM yyyy HH:mm:ss", "EEE MMM dd yyyy HH:mm:ss zzz", "EEE MMM dd yyyy HH:mm:ss",
174 "EEE MMM-dd-yyyy HH:mm:ss zzz", "EEE MMM-dd-yyyy HH:mm:ss", "dd MMM yyyy HH:mm:ss zzz",
175 "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",
176 "MMM dd HH:mm:ss yyyy", "EEE MMM dd HH:mm:ss yyyy zzz",
177 "EEE, MMM dd HH:mm:ss yyyy zzz", "EEE, MMM dd HH:mm:ss yyyy", "EEE, dd-MMM-yy HH:mm:ss zzz",
178 "EEE dd-MMM-yy HH:mm:ss zzz", "EEE dd-MMM-yy HH:mm:ss",
179 };
180 private static int __dateReceiveInit=3;
181 private static SimpleDateFormat __dateReceive[];
182 static
183 {
184 __GMT.setID("GMT");
185 __dateCache.setTimeZone(__GMT);
186 __dateReceive = new SimpleDateFormat[__dateReceiveFmt.length];
187
188 for (int i = 0; i < __dateReceiveInit; i++)
189 {
190 __dateReceive[i] = new SimpleDateFormat(__dateReceiveFmt[i], Locale.US);
191 __dateReceive[i].setTimeZone(__GMT);
192 }
193 }
194 public final static String __01Jan1970 = formatDate(0, true).trim();
195 public final static Buffer __01Jan1970_BUFFER = new ByteArrayBuffer(__01Jan1970);
196
197
198 protected ArrayList _fields = new ArrayList(20);
199 protected int _revision;
200 protected HashMap _bufferMap = new HashMap(32);
201 protected SimpleDateFormat _dateReceive[] = new SimpleDateFormat[__dateReceive.length];
202 private StringBuffer _dateBuffer;
203 private Calendar _calendar;
204
205
206
207
208
209 public HttpFields()
210 {
211 }
212
213
214
215
216
217
218 public Enumeration getFieldNames()
219 {
220 final int revision=_revision;
221 return new Enumeration()
222 {
223 int i = 0;
224 Field field = null;
225
226 public boolean hasMoreElements()
227 {
228 if (field != null) return true;
229 while (i < _fields.size())
230 {
231 Field f = (Field) _fields.get(i++);
232 if (f != null && f._prev == null && f._revision == revision)
233 {
234 field = f;
235 return true;
236 }
237 }
238 return false;
239 }
240
241 public Object nextElement() throws NoSuchElementException
242 {
243 if (field != null || hasMoreElements())
244 {
245 String n = BufferUtil.to8859_1_String(field._name);
246 field = null;
247 return n;
248 }
249 throw new NoSuchElementException();
250 }
251 };
252 }
253
254
255
256
257
258 public Iterator getFields()
259 {
260 final int revision=_revision;
261 return new Iterator()
262 {
263 int i = 0;
264 Field field = null;
265
266 public boolean hasNext()
267 {
268 if (field != null) return true;
269 while (i < _fields.size())
270 {
271 Field f = (Field) _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 if (path.startsWith("\""))
987 buf.append(path);
988 else
989 QuotedStringTokenizer.quoteIfNeeded(buf,path);
990 }
991 String domain = cookie.getDomain();
992 if (domain != null && domain.length() > 0)
993 {
994 buf.append(";Domain=");
995 QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase());
996 }
997
998 long maxAge = cookie.getMaxAge();
999 if (maxAge >= 0)
1000 {
1001 if (version == 0)
1002 {
1003 buf.append(";Expires=");
1004 if (maxAge == 0)
1005 buf.append(__01Jan1970);
1006 else
1007 formatDate(buf, System.currentTimeMillis() + 1000L * maxAge, true);
1008 }
1009 else
1010 {
1011 buf.append(";Max-Age=");
1012 buf.append(maxAge);
1013 }
1014 }
1015 else if (version > 0)
1016 {
1017 buf.append(";Discard");
1018 }
1019
1020 if (cookie.getSecure())
1021 {
1022 buf.append(";Secure");
1023 }
1024 if (cookie instanceof HttpOnlyCookie)
1025 buf.append(";HttpOnly");
1026
1027
1028 name_value_params = buf.toString();
1029 }
1030 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
1031 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params));
1032 }
1033
1034
1035 public void put(Buffer buffer) throws IOException
1036 {
1037 for (int i = 0; i < _fields.size(); i++)
1038 {
1039 Field field = (Field) _fields.get(i);
1040 if (field != null && field._revision == _revision) field.put(buffer);
1041 }
1042 BufferUtil.putCRLF(buffer);
1043 }
1044
1045
1046 public String toString()
1047 {
1048 try
1049 {
1050 StringBuffer buffer = new StringBuffer();
1051
1052 for (int i = 0; i < _fields.size(); i++)
1053 {
1054 Field field = (Field) _fields.get(i);
1055 if (field != null && field._revision == _revision)
1056 {
1057 String tmp = field.getName();
1058 if (tmp != null) buffer.append(tmp);
1059 buffer.append(": ");
1060 tmp = field.getValue();
1061 if (tmp != null) buffer.append(tmp);
1062 buffer.append("\r\n");
1063 }
1064 }
1065 buffer.append("\r\n");
1066 return buffer.toString();
1067
1068 }
1069 catch (Exception e)
1070 {
1071 e.printStackTrace();
1072 }
1073
1074 return null;
1075 }
1076
1077
1078
1079
1080
1081 public void clear()
1082 {
1083 _revision++;
1084 if (_revision > 1000000)
1085 {
1086 _revision = 0;
1087 for (int i = _fields.size(); i-- > 0;)
1088 {
1089 Field field = (Field) _fields.get(i);
1090 if (field != null) field.clear();
1091 }
1092 }
1093 }
1094
1095
1096
1097
1098
1099 public void destroy()
1100 {
1101 if (_fields != null)
1102 {
1103 for (int i = _fields.size(); i-- > 0;)
1104 {
1105 Field field = (Field) _fields.get(i);
1106 if (field != null) {
1107 _bufferMap.remove(field.getNameBuffer());
1108 field.destroy();
1109 }
1110 }
1111 }
1112 _fields = null;
1113 _dateBuffer = null;
1114 _calendar = null;
1115 _dateReceive = null;
1116 }
1117
1118
1119
1120
1121
1122
1123
1124
1125 public void add(HttpFields fields)
1126 {
1127 if (fields == null) return;
1128
1129 Enumeration e = fields.getFieldNames();
1130 while (e.hasMoreElements())
1131 {
1132 String name = (String) e.nextElement();
1133 Enumeration values = fields.getValues(name);
1134 while (values.hasMoreElements())
1135 add(name, (String) values.nextElement());
1136 }
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154 public static String valueParameters(String value, Map parameters)
1155 {
1156 if (value == null) return null;
1157
1158 int i = value.indexOf(';');
1159 if (i < 0) return value;
1160 if (parameters == null) return value.substring(0, i).trim();
1161
1162 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
1163 while (tok1.hasMoreTokens())
1164 {
1165 String token = tok1.nextToken();
1166 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
1167 if (tok2.hasMoreTokens())
1168 {
1169 String paramName = tok2.nextToken();
1170 String paramVal = null;
1171 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1172 parameters.put(paramName, paramVal);
1173 }
1174 }
1175
1176 return value.substring(0, i).trim();
1177 }
1178
1179
1180 private static Float __one = new Float("1.0");
1181 private static Float __zero = new Float("0.0");
1182 private static StringMap __qualities = new StringMap();
1183 static
1184 {
1185 __qualities.put(null, __one);
1186 __qualities.put("1.0", __one);
1187 __qualities.put("1", __one);
1188 __qualities.put("0.9", new Float("0.9"));
1189 __qualities.put("0.8", new Float("0.8"));
1190 __qualities.put("0.7", new Float("0.7"));
1191 __qualities.put("0.66", new Float("0.66"));
1192 __qualities.put("0.6", new Float("0.6"));
1193 __qualities.put("0.5", new Float("0.5"));
1194 __qualities.put("0.4", new Float("0.4"));
1195 __qualities.put("0.33", new Float("0.33"));
1196 __qualities.put("0.3", new Float("0.3"));
1197 __qualities.put("0.2", new Float("0.2"));
1198 __qualities.put("0.1", new Float("0.1"));
1199 __qualities.put("0", __zero);
1200 __qualities.put("0.0", __zero);
1201 }
1202
1203
1204 public static Float getQuality(String value)
1205 {
1206 if (value == null) return __zero;
1207
1208 int qe = value.indexOf(";");
1209 if (qe++ < 0 || qe == value.length()) return __one;
1210
1211 if (value.charAt(qe++) == 'q')
1212 {
1213 qe++;
1214 Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe);
1215 if (entry != null) return (Float) entry.getValue();
1216 }
1217
1218 HashMap params = new HashMap(3);
1219 valueParameters(value, params);
1220 String qs = (String) params.get("q");
1221 Float q = (Float) __qualities.get(qs);
1222 if (q == null)
1223 {
1224 try
1225 {
1226 q = new Float(qs);
1227 }
1228 catch (Exception e)
1229 {
1230 q = __one;
1231 }
1232 }
1233 return q;
1234 }
1235
1236
1237
1238
1239
1240
1241
1242
1243 public static List qualityList(Enumeration e)
1244 {
1245 if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST;
1246
1247 Object list = null;
1248 Object qual = null;
1249
1250
1251 while (e.hasMoreElements())
1252 {
1253 String v = e.nextElement().toString();
1254 Float q = getQuality(v);
1255
1256 if (q.floatValue() >= 0.001)
1257 {
1258 list = LazyList.add(list, v);
1259 qual = LazyList.add(qual, q);
1260 }
1261 }
1262
1263 List vl = LazyList.getList(list, false);
1264 if (vl.size() < 2) return vl;
1265
1266 List ql = LazyList.getList(qual, false);
1267
1268
1269 Float last = __zero;
1270 for (int i = vl.size(); i-- > 0;)
1271 {
1272 Float q = (Float) ql.get(i);
1273 if (last.compareTo(q) > 0)
1274 {
1275 Object tmp = vl.get(i);
1276 vl.set(i, vl.get(i + 1));
1277 vl.set(i + 1, tmp);
1278 ql.set(i, ql.get(i + 1));
1279 ql.set(i + 1, q);
1280 last = __zero;
1281 i = vl.size();
1282 continue;
1283 }
1284 last = q;
1285 }
1286 ql.clear();
1287 return vl;
1288 }
1289
1290
1291
1292
1293 public static final class Field
1294 {
1295 private Buffer _name;
1296 private Buffer _value;
1297 private String _stringValue;
1298 private long _numValue;
1299 private Field _next;
1300 private Field _prev;
1301 private int _revision;
1302
1303
1304 private Field(Buffer name, Buffer value, long numValue, int revision)
1305 {
1306 _name = name.asImmutableBuffer();
1307 _value = value.isImmutable() ? value : new View(value);
1308 _next = null;
1309 _prev = null;
1310 _revision = revision;
1311 _numValue = numValue;
1312 _stringValue=null;
1313 }
1314
1315
1316 private void clear()
1317 {
1318 _revision = -1;
1319 }
1320
1321
1322 private void destroy()
1323 {
1324 _name = null;
1325 _value = null;
1326 _next = null;
1327 _prev = null;
1328 _stringValue=null;
1329 }
1330
1331
1332
1333
1334
1335
1336 private void reset(Buffer value, long numValue, int revision)
1337 {
1338 _revision = revision;
1339 if (_value == null)
1340 {
1341 _value = value.isImmutable() ? value : new View(value);
1342 _numValue = numValue;
1343 _stringValue=null;
1344 }
1345 else if (value.isImmutable())
1346 {
1347 _value = value;
1348 _numValue = numValue;
1349 _stringValue=null;
1350 }
1351 else
1352 {
1353 if (_value instanceof View)
1354 ((View) _value).update(value);
1355 else
1356 _value = new View(value);
1357 _numValue = numValue;
1358
1359
1360 if (_stringValue!=null)
1361 {
1362 if (_stringValue.length()!=value.length())
1363 _stringValue=null;
1364 else
1365 {
1366 for (int i=value.length();i-->0;)
1367 {
1368 if (value.peek(value.getIndex()+i)!=_stringValue.charAt(i))
1369 {
1370 _stringValue=null;
1371 break;
1372 }
1373 }
1374 }
1375 }
1376 }
1377 }
1378
1379
1380
1381
1382 public void put(Buffer buffer) throws IOException
1383 {
1384 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
1385 if (o>=0)
1386 buffer.put(_name);
1387 else
1388 {
1389 int s=_name.getIndex();
1390 int e=_name.putIndex();
1391 while (s<e)
1392 {
1393 byte b=_name.peek(s++);
1394 switch(b)
1395 {
1396 case '\r':
1397 case '\n':
1398 case ':' :
1399 continue;
1400 default:
1401 buffer.put(b);
1402 }
1403 }
1404 }
1405
1406 buffer.put((byte) ':');
1407 buffer.put((byte) ' ');
1408
1409 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1;
1410 if (o>=0 || _numValue>=0)
1411 buffer.put(_value);
1412 else
1413 {
1414 int s=_value.getIndex();
1415 int e=_value.putIndex();
1416 while (s<e)
1417 {
1418 byte b=_value.peek(s++);
1419 switch(b)
1420 {
1421 case '\r':
1422 case '\n':
1423 continue;
1424 default:
1425 buffer.put(b);
1426 }
1427 }
1428 }
1429
1430 BufferUtil.putCRLF(buffer);
1431 }
1432
1433
1434 public String getName()
1435 {
1436 return BufferUtil.to8859_1_String(_name);
1437 }
1438
1439
1440 Buffer getNameBuffer()
1441 {
1442 return _name;
1443 }
1444
1445
1446 public int getNameOrdinal()
1447 {
1448 return HttpHeaders.CACHE.getOrdinal(_name);
1449 }
1450
1451
1452 public String getValue()
1453 {
1454 if (_stringValue==null)
1455 _stringValue=BufferUtil.to8859_1_String(_value);
1456 return _stringValue;
1457 }
1458
1459
1460 public Buffer getValueBuffer()
1461 {
1462 return _value;
1463 }
1464
1465
1466 public int getValueOrdinal()
1467 {
1468 return HttpHeaderValues.CACHE.getOrdinal(_value);
1469 }
1470
1471
1472 public int getIntValue()
1473 {
1474 return (int) getLongValue();
1475 }
1476
1477
1478 public long getLongValue()
1479 {
1480 if (_numValue == -1) _numValue = BufferUtil.toLong(_value);
1481 return _numValue;
1482 }
1483
1484
1485 public String toString()
1486 {
1487 return ("[" + (_prev == null ? "" : "<-") + getName() + "="+_revision+"=" + _value + (_next == null ? "" : "->") + "]");
1488 }
1489 }
1490
1491 }