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).trim();
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 if (path.startsWith("\""))
986 buf.append(path);
987 else
988 QuotedStringTokenizer.quoteIfNeeded(buf,path);
989 }
990 String domain = cookie.getDomain();
991 if (domain != null && domain.length() > 0)
992 {
993 buf.append(";Domain=");
994 QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase());
995 }
996
997 long maxAge = cookie.getMaxAge();
998 if (maxAge >= 0)
999 {
1000 if (version == 0)
1001 {
1002 buf.append(";Expires=");
1003 if (maxAge == 0)
1004 buf.append(__01Jan1970);
1005 else
1006 formatDate(buf, System.currentTimeMillis() + 1000L * maxAge, true);
1007 }
1008 else
1009 {
1010 buf.append(";Max-Age=");
1011 buf.append(maxAge);
1012 }
1013 }
1014 else if (version > 0)
1015 {
1016 buf.append(";Discard");
1017 }
1018
1019 if (cookie.getSecure())
1020 {
1021 buf.append(";Secure");
1022 }
1023 if (cookie instanceof HttpOnlyCookie)
1024 buf.append(";HttpOnly");
1025
1026
1027 name_value_params = buf.toString();
1028 }
1029 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
1030 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params));
1031 }
1032
1033
1034 public void put(Buffer buffer) throws IOException
1035 {
1036 for (int i = 0; i < _fields.size(); i++)
1037 {
1038 Field field = (Field) _fields.get(i);
1039 if (field != null && field._revision == _revision) field.put(buffer);
1040 }
1041 BufferUtil.putCRLF(buffer);
1042 }
1043
1044
1045 public String toString()
1046 {
1047 try
1048 {
1049 ByteArrayBuffer buffer = new ByteArrayBuffer(4096);
1050 put(buffer);
1051 return BufferUtil.to8859_1_String(buffer);
1052 }
1053 catch (Exception e)
1054 {
1055 e.printStackTrace();
1056 }
1057
1058 return null;
1059 }
1060
1061
1062
1063
1064
1065 public void clear()
1066 {
1067 _revision++;
1068 if (_revision > 1000000)
1069 {
1070 _revision = 0;
1071 for (int i = _fields.size(); i-- > 0;)
1072 {
1073 Field field = (Field) _fields.get(i);
1074 if (field != null) field.clear();
1075 }
1076 }
1077 }
1078
1079
1080
1081
1082
1083 public void destroy()
1084 {
1085 if (_fields != null)
1086 {
1087 for (int i = _fields.size(); i-- > 0;)
1088 {
1089 Field field = (Field) _fields.get(i);
1090 if (field != null) {
1091 _bufferMap.remove(field.getNameBuffer());
1092 field.destroy();
1093 }
1094 }
1095 }
1096 _fields = null;
1097 _dateBuffer = null;
1098 _calendar = null;
1099 _dateReceive = null;
1100 }
1101
1102
1103
1104
1105
1106
1107
1108
1109 public void add(HttpFields fields)
1110 {
1111 if (fields == null) return;
1112
1113 Enumeration e = fields.getFieldNames();
1114 while (e.hasMoreElements())
1115 {
1116 String name = (String) e.nextElement();
1117 Enumeration values = fields.getValues(name);
1118 while (values.hasMoreElements())
1119 add(name, (String) values.nextElement());
1120 }
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138 public static String valueParameters(String value, Map parameters)
1139 {
1140 if (value == null) return null;
1141
1142 int i = value.indexOf(';');
1143 if (i < 0) return value;
1144 if (parameters == null) return value.substring(0, i).trim();
1145
1146 StringTokenizer tok1 = new QuotedStringTokenizer(value.substring(i), ";", false, true);
1147 while (tok1.hasMoreTokens())
1148 {
1149 String token = tok1.nextToken();
1150 StringTokenizer tok2 = new QuotedStringTokenizer(token, "= ");
1151 if (tok2.hasMoreTokens())
1152 {
1153 String paramName = tok2.nextToken();
1154 String paramVal = null;
1155 if (tok2.hasMoreTokens()) paramVal = tok2.nextToken();
1156 parameters.put(paramName, paramVal);
1157 }
1158 }
1159
1160 return value.substring(0, i).trim();
1161 }
1162
1163
1164 private static Float __one = new Float("1.0");
1165 private static Float __zero = new Float("0.0");
1166 private static StringMap __qualities = new StringMap();
1167 static
1168 {
1169 __qualities.put(null, __one);
1170 __qualities.put("1.0", __one);
1171 __qualities.put("1", __one);
1172 __qualities.put("0.9", new Float("0.9"));
1173 __qualities.put("0.8", new Float("0.8"));
1174 __qualities.put("0.7", new Float("0.7"));
1175 __qualities.put("0.66", new Float("0.66"));
1176 __qualities.put("0.6", new Float("0.6"));
1177 __qualities.put("0.5", new Float("0.5"));
1178 __qualities.put("0.4", new Float("0.4"));
1179 __qualities.put("0.33", new Float("0.33"));
1180 __qualities.put("0.3", new Float("0.3"));
1181 __qualities.put("0.2", new Float("0.2"));
1182 __qualities.put("0.1", new Float("0.1"));
1183 __qualities.put("0", __zero);
1184 __qualities.put("0.0", __zero);
1185 }
1186
1187
1188 public static Float getQuality(String value)
1189 {
1190 if (value == null) return __zero;
1191
1192 int qe = value.indexOf(";");
1193 if (qe++ < 0 || qe == value.length()) return __one;
1194
1195 if (value.charAt(qe++) == 'q')
1196 {
1197 qe++;
1198 Map.Entry entry = __qualities.getEntry(value, qe, value.length() - qe);
1199 if (entry != null) return (Float) entry.getValue();
1200 }
1201
1202 HashMap params = new HashMap(3);
1203 valueParameters(value, params);
1204 String qs = (String) params.get("q");
1205 Float q = (Float) __qualities.get(qs);
1206 if (q == null)
1207 {
1208 try
1209 {
1210 q = new Float(qs);
1211 }
1212 catch (Exception e)
1213 {
1214 q = __one;
1215 }
1216 }
1217 return q;
1218 }
1219
1220
1221
1222
1223
1224
1225
1226
1227 public static List qualityList(Enumeration e)
1228 {
1229 if (e == null || !e.hasMoreElements()) return Collections.EMPTY_LIST;
1230
1231 Object list = null;
1232 Object qual = null;
1233
1234
1235 while (e.hasMoreElements())
1236 {
1237 String v = e.nextElement().toString();
1238 Float q = getQuality(v);
1239
1240 if (q.floatValue() >= 0.001)
1241 {
1242 list = LazyList.add(list, v);
1243 qual = LazyList.add(qual, q);
1244 }
1245 }
1246
1247 List vl = LazyList.getList(list, false);
1248 if (vl.size() < 2) return vl;
1249
1250 List ql = LazyList.getList(qual, false);
1251
1252
1253 Float last = __zero;
1254 for (int i = vl.size(); i-- > 0;)
1255 {
1256 Float q = (Float) ql.get(i);
1257 if (last.compareTo(q) > 0)
1258 {
1259 Object tmp = vl.get(i);
1260 vl.set(i, vl.get(i + 1));
1261 vl.set(i + 1, tmp);
1262 ql.set(i, ql.get(i + 1));
1263 ql.set(i + 1, q);
1264 last = __zero;
1265 i = vl.size();
1266 continue;
1267 }
1268 last = q;
1269 }
1270 ql.clear();
1271 return vl;
1272 }
1273
1274
1275
1276
1277 public static final class Field
1278 {
1279 private Buffer _name;
1280 private Buffer _value;
1281 private String _stringValue;
1282 private long _numValue;
1283 private Field _next;
1284 private Field _prev;
1285 private int _revision;
1286
1287
1288 private Field(Buffer name, Buffer value, long numValue, int revision)
1289 {
1290 _name = name.asImmutableBuffer();
1291 _value = value.isImmutable() ? value : new View(value);
1292 _next = null;
1293 _prev = null;
1294 _revision = revision;
1295 _numValue = numValue;
1296 _stringValue=null;
1297 }
1298
1299
1300 private void clear()
1301 {
1302 _revision = -1;
1303 }
1304
1305
1306 private void destroy()
1307 {
1308 _name = null;
1309 _value = null;
1310 _next = null;
1311 _prev = null;
1312 _stringValue=null;
1313 }
1314
1315
1316
1317
1318
1319
1320 private void reset(Buffer value, long numValue, int revision)
1321 {
1322 _revision = revision;
1323 if (_value == null)
1324 {
1325 _value = value.isImmutable() ? value : new View(value);
1326 _numValue = numValue;
1327 _stringValue=null;
1328 }
1329 else if (value.isImmutable())
1330 {
1331 _value = value;
1332 _numValue = numValue;
1333 _stringValue=null;
1334 }
1335 else
1336 {
1337 if (_value instanceof View)
1338 ((View) _value).update(value);
1339 else
1340 _value = new View(value);
1341 _numValue = numValue;
1342
1343
1344 if (_stringValue!=null)
1345 {
1346 if (_stringValue.length()!=value.length())
1347 _stringValue=null;
1348 else
1349 {
1350 for (int i=value.length();i-->0;)
1351 {
1352 if (value.peek(value.getIndex()+i)!=_stringValue.charAt(i))
1353 {
1354 _stringValue=null;
1355 break;
1356 }
1357 }
1358 }
1359 }
1360 }
1361 }
1362
1363
1364
1365
1366 public void put(Buffer buffer) throws IOException
1367 {
1368 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
1369 if (o>=0)
1370 buffer.put(_name);
1371 else
1372 {
1373 int s=_name.getIndex();
1374 int e=_name.putIndex();
1375 while (s<e)
1376 {
1377 byte b=_name.peek(s++);
1378 switch(b)
1379 {
1380 case '\r':
1381 case '\n':
1382 case ':' :
1383 continue;
1384 default:
1385 buffer.put(b);
1386 }
1387 }
1388 }
1389
1390 buffer.put((byte) ':');
1391 buffer.put((byte) ' ');
1392
1393 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1;
1394 if (o>=0 || _numValue>=0)
1395 buffer.put(_value);
1396 else
1397 {
1398 int s=_value.getIndex();
1399 int e=_value.putIndex();
1400 while (s<e)
1401 {
1402 byte b=_value.peek(s++);
1403 switch(b)
1404 {
1405 case '\r':
1406 case '\n':
1407 continue;
1408 default:
1409 buffer.put(b);
1410 }
1411 }
1412 }
1413
1414 BufferUtil.putCRLF(buffer);
1415 }
1416
1417
1418 public String getName()
1419 {
1420 return BufferUtil.to8859_1_String(_name);
1421 }
1422
1423
1424 Buffer getNameBuffer()
1425 {
1426 return _name;
1427 }
1428
1429
1430 public int getNameOrdinal()
1431 {
1432 return HttpHeaders.CACHE.getOrdinal(_name);
1433 }
1434
1435
1436 public String getValue()
1437 {
1438 if (_stringValue==null)
1439 _stringValue=BufferUtil.to8859_1_String(_value);
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 }