Mercurial Hosting > luan
comparison src/org/eclipse/jetty/http/HttpFields.java @ 1022:3718afd99988
HttpHeaders uses StringCache
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 01 Nov 2016 01:04:46 -0600 |
parents | e350c11242be |
children | eca26899c4bc |
comparison
equal
deleted
inserted
replaced
1021:e350c11242be | 1022:3718afd99988 |
---|---|
38 import java.util.TimeZone; | 38 import java.util.TimeZone; |
39 import java.util.concurrent.ConcurrentHashMap; | 39 import java.util.concurrent.ConcurrentHashMap; |
40 import java.util.concurrent.ConcurrentMap; | 40 import java.util.concurrent.ConcurrentMap; |
41 | 41 |
42 import org.eclipse.jetty.io.Buffer; | 42 import org.eclipse.jetty.io.Buffer; |
43 import org.eclipse.jetty.io.BufferCache; | |
44 import org.eclipse.jetty.io.BufferCache.CachedBuffer; | |
45 import org.eclipse.jetty.io.BufferUtil; | 43 import org.eclipse.jetty.io.BufferUtil; |
46 import org.eclipse.jetty.io.ByteArrayBuffer; | 44 import org.eclipse.jetty.io.ByteArrayBuffer; |
47 import org.eclipse.jetty.util.LazyList; | 45 import org.eclipse.jetty.util.LazyList; |
48 import org.eclipse.jetty.util.QuotedStringTokenizer; | 46 import org.eclipse.jetty.util.QuotedStringTokenizer; |
49 import org.eclipse.jetty.util.StringUtil; | 47 import org.eclipse.jetty.util.StringUtil; |
265 return new DateParser(); | 263 return new DateParser(); |
266 } | 264 } |
267 }; | 265 }; |
268 | 266 |
269 private final static String __01Jan1970 = formatDate(0); | 267 private final static String __01Jan1970 = formatDate(0); |
270 private final static Buffer __01Jan1970_BUFFER = new ByteArrayBuffer(__01Jan1970); | |
271 private final static String __01Jan1970_COOKIE = formatCookieDate(0).trim(); | 268 private final static String __01Jan1970_COOKIE = formatCookieDate(0).trim(); |
272 | 269 |
273 | 270 |
274 | 271 |
275 | 272 |
276 | 273 |
277 | 274 |
278 private final ArrayList<Field> _fields = new ArrayList<Field>(20); | 275 private final ArrayList<Field> _fields = new ArrayList<Field>(); |
279 private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32); | 276 private final HashMap<String,Field> _names = new HashMap<String,Field>(); |
280 /* | 277 |
281 private Buffer convertValue(String value) | |
282 { | |
283 try | |
284 { | |
285 return new ByteArrayBuffer(value,StringUtil.__ISO_8859_1); | |
286 } | |
287 catch (UnsupportedEncodingException e) | |
288 { | |
289 throw new RuntimeException(e); | |
290 } | |
291 } | |
292 */ | |
293 | 278 |
294 /* -------------------------------------------------------------- */ | 279 /* -------------------------------------------------------------- */ |
295 /** | 280 /** |
296 * Get Collection of header names. | 281 * Get Collection of header names. |
297 */ | 282 */ |
344 public Field getField(int i) | 329 public Field getField(int i) |
345 { | 330 { |
346 return _fields.get(i); | 331 return _fields.get(i); |
347 } | 332 } |
348 | 333 |
349 /* ------------------------------------------------------------ */ | |
350 private Field getField(String name) | 334 private Field getField(String name) |
351 { | 335 { |
352 return _names.get(HttpHeaders.CACHE.lookup(name)); | 336 return _names.get(name.toLowerCase()); |
353 } | 337 } |
354 | 338 |
355 /* ------------------------------------------------------------ */ | |
356 private Field getField(Buffer name) | |
357 { | |
358 return _names.get(HttpHeaders.CACHE.lookup(name)); | |
359 } | |
360 | |
361 /* ------------------------------------------------------------ */ | |
362 public boolean containsKey(Buffer name) | |
363 { | |
364 return _names.containsKey(HttpHeaders.CACHE.lookup(name)); | |
365 } | |
366 | |
367 /* ------------------------------------------------------------ */ | |
368 public boolean containsKey(String name) | 339 public boolean containsKey(String name) |
369 { | 340 { |
370 return _names.containsKey(HttpHeaders.CACHE.lookup(name)); | 341 return _names.containsKey(name.toLowerCase()); |
371 } | 342 } |
372 | 343 |
373 /* -------------------------------------------------------------- */ | 344 /* -------------------------------------------------------------- */ |
374 /** | 345 /** |
375 * @return the value of a field, or null if not found. For multiple fields of the same name, | 346 * @return the value of a field, or null if not found. For multiple fields of the same name, |
377 * @param name the case-insensitive field name | 348 * @param name the case-insensitive field name |
378 */ | 349 */ |
379 public String getStringField(String name) | 350 public String getStringField(String name) |
380 { | 351 { |
381 Field field = getField(name); | 352 Field field = getField(name); |
382 return field==null?null:field.getValue(); | 353 return field==null ? null : field.getValue(); |
383 } | |
384 | |
385 /* -------------------------------------------------------------- */ | |
386 /** | |
387 * @return the value of a field, or null if not found. For multiple fields of the same name, | |
388 * only the first is returned. | |
389 * @param name the case-insensitive field name | |
390 */ | |
391 public String getStringField(Buffer name) | |
392 { | |
393 Field field = getField(name); | |
394 return field==null?null:field.getValue(); | |
395 } | 354 } |
396 | 355 |
397 /* -------------------------------------------------------------- */ | 356 /* -------------------------------------------------------------- */ |
398 /** | 357 /** |
399 * Get multi headers | 358 * Get multi headers |
423 * | 382 * |
424 * @return Enumeration of the values | 383 * @return Enumeration of the values |
425 * @param name the case-insensitive field name | 384 * @param name the case-insensitive field name |
426 */ | 385 */ |
427 public Enumeration<String> getValues(String name) | 386 public Enumeration<String> getValues(String name) |
428 { | |
429 final Field field = getField(name); | |
430 if (field == null) | |
431 { | |
432 List<String> empty=Collections.emptyList(); | |
433 return Collections.enumeration(empty); | |
434 } | |
435 | |
436 return new Enumeration<String>() | |
437 { | |
438 Field f = field; | |
439 | |
440 public boolean hasMoreElements() | |
441 { | |
442 return f != null; | |
443 } | |
444 | |
445 public String nextElement() throws NoSuchElementException | |
446 { | |
447 if (f == null) throw new NoSuchElementException(); | |
448 Field n = f; | |
449 f = f._next; | |
450 return n.getValue(); | |
451 } | |
452 }; | |
453 } | |
454 | |
455 /* -------------------------------------------------------------- */ | |
456 /** | |
457 * Get multi headers | |
458 * | |
459 * @return Enumeration of the value Strings | |
460 * @param name the case-insensitive field name | |
461 */ | |
462 public Enumeration<String> getValues(Buffer name) | |
463 { | 387 { |
464 final Field field = getField(name); | 388 final Field field = getField(name); |
465 if (field == null) | 389 if (field == null) |
466 { | 390 { |
467 List<String> empty=Collections.emptyList(); | 391 List<String> empty=Collections.emptyList(); |
537 * @param name the name of the field | 461 * @param name the name of the field |
538 * @param value the value of the field. If null the field is cleared. | 462 * @param value the value of the field. If null the field is cleared. |
539 */ | 463 */ |
540 public void put(String name, String value) | 464 public void put(String name, String value) |
541 { | 465 { |
542 if (value==null) | 466 String nameLower = name.toLowerCase(); |
543 remove(name); | 467 removeLower(nameLower); |
544 else | |
545 { | |
546 Buffer n = HttpHeaders.CACHE.lookup(name); | |
547 put(n, value); | |
548 } | |
549 } | |
550 | |
551 /* -------------------------------------------------------------- */ | |
552 /** | |
553 * Set a field. | |
554 * | |
555 * @param name the name of the field | |
556 * @param value the value of the field. If null the field is cleared. | |
557 */ | |
558 public void put(Buffer name, String value) | |
559 { | |
560 /* | |
561 Buffer n = HttpHeaders.CACHE.lookup(name); | |
562 Buffer v = convertValue(value); | |
563 put(n, v); | |
564 */ | |
565 remove(name); | |
566 if (value == null) | 468 if (value == null) |
567 return; | 469 return; |
568 | 470 |
569 if (!(name instanceof BufferCache.CachedBuffer)) | |
570 name = HttpHeaders.CACHE.lookup(name); | |
571 int valueOrdinal = HttpHeaderValues.CACHE.getOrdinal(value); | |
572 | |
573 // new value; | |
574 Field field = new Field(name, value, valueOrdinal); | |
575 _fields.add(field); | |
576 _names.put(name, field); | |
577 } | |
578 | |
579 /* -------------------------------------------------------------- */ | |
580 /** | |
581 * Set a field. | |
582 * | |
583 * @param name the name of the field | |
584 * @param value the value of the field. If null the field is cleared. | |
585 */ | |
586 public void put(Buffer name, Buffer value) | |
587 { | |
588 /* | |
589 remove(name); | |
590 if (value == null) | |
591 return; | |
592 | |
593 if (!(name instanceof BufferCache.CachedBuffer)) | |
594 name = HttpHeaders.CACHE.lookup(name); | |
595 if (!(value instanceof CachedBuffer)) | |
596 value = HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer(); | |
597 | |
598 // new value; | 471 // new value; |
599 Field field = new Field(name, value); | 472 Field field = new Field(name, value); |
600 _fields.add(field); | 473 _fields.add(field); |
601 _names.put(name, field); | 474 _names.put(nameLower, field); |
602 */ | |
603 String s = value==null ? null : value.toString(); | |
604 put(name,s); | |
605 } | 475 } |
606 | 476 |
607 /* -------------------------------------------------------------- */ | 477 /* -------------------------------------------------------------- */ |
608 /** | 478 /** |
609 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple | 479 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple |
614 * @exception IllegalArgumentException If the name is a single valued field and already has a | 484 * @exception IllegalArgumentException If the name is a single valued field and already has a |
615 * value. | 485 * value. |
616 */ | 486 */ |
617 public void add(String name, String value) throws IllegalArgumentException | 487 public void add(String name, String value) throws IllegalArgumentException |
618 { | 488 { |
619 if (value==null) | |
620 return; | |
621 Buffer n = HttpHeaders.CACHE.lookup(name); | |
622 add(n, value); | |
623 } | |
624 | |
625 /* -------------------------------------------------------------- */ | |
626 /** | |
627 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple | |
628 * headers of the same name. | |
629 * | |
630 * @param name the name of the field | |
631 * @param value the value of the field. | |
632 * @exception IllegalArgumentException If the name is a single valued field and already has a | |
633 * value. | |
634 */ | |
635 public void add(Buffer name, String value) throws IllegalArgumentException | |
636 { | |
637 if (value == null) throw new IllegalArgumentException("null value"); | 489 if (value == null) throw new IllegalArgumentException("null value"); |
638 | 490 |
639 if (!(name instanceof CachedBuffer)) | 491 String nameLower = name.toLowerCase(); |
640 name = HttpHeaders.CACHE.lookup(name); | 492 |
641 name=name.asImmutableBuffer(); | 493 Field field = _names.get(nameLower); |
642 /* | |
643 if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name))) | |
644 value= HttpHeaderValues.CACHE.lookup(value); | |
645 value=value.asImmutableBuffer(); | |
646 */ | |
647 Field field = _names.get(name); | |
648 Field last = null; | 494 Field last = null; |
649 while (field != null) | 495 while (field != null) |
650 { | 496 { |
651 last = field; | 497 last = field; |
652 field = field._next; | 498 field = field._next; |
653 } | 499 } |
654 | 500 |
655 // create the field | 501 // create the field |
656 int valueOrdinal = HttpHeaderValues.CACHE.getOrdinal(value); | 502 field = new Field(name, value); |
657 field = new Field(name, value, valueOrdinal); | |
658 _fields.add(field); | 503 _fields.add(field); |
659 | 504 |
660 // look for chain to add too | 505 // look for chain to add too |
661 if (last != null) | 506 if (last != null) |
662 last._next = field; | 507 last._next = field; |
663 else | 508 else |
664 _names.put(name, field); | 509 _names.put(nameLower, field); |
665 } | 510 } |
666 | 511 |
667 /* ------------------------------------------------------------ */ | 512 /* ------------------------------------------------------------ */ |
668 /** | 513 /** |
669 * Remove a field. | 514 * Remove a field. |
670 * | 515 * |
671 * @param name | 516 * @param name |
672 */ | 517 */ |
673 public void remove(String name) | 518 public void remove(String name) |
674 { | 519 { |
675 remove(HttpHeaders.CACHE.lookup(name)); | 520 removeLower(name.toLowerCase()); |
676 } | 521 } |
677 | 522 |
678 /* ------------------------------------------------------------ */ | 523 private void removeLower(String nameLower) { |
679 /** | 524 Field field = _names.remove(nameLower); |
680 * Remove a field. | |
681 * | |
682 * @param name | |
683 */ | |
684 public void remove(Buffer name) | |
685 { | |
686 if (!(name instanceof BufferCache.CachedBuffer)) | |
687 name = HttpHeaders.CACHE.lookup(name); | |
688 Field field = _names.remove(name); | |
689 while (field != null) | 525 while (field != null) |
690 { | 526 { |
691 _fields.remove(field); | 527 _fields.remove(field); |
692 field = field._next; | 528 field = field._next; |
693 } | 529 } |
700 * | 536 * |
701 * @param name the case-insensitive field name | 537 * @param name the case-insensitive field name |
702 * @exception NumberFormatException If bad long found | 538 * @exception NumberFormatException If bad long found |
703 */ | 539 */ |
704 public long getLongField(String name) throws NumberFormatException | 540 public long getLongField(String name) throws NumberFormatException |
705 { | |
706 Field field = getField(name); | |
707 return field==null?-1L:field.getLongValue(); | |
708 } | |
709 | |
710 /* -------------------------------------------------------------- */ | |
711 /** | |
712 * Get a header as an long value. Returns the value of an integer field or -1 if not found. The | |
713 * case of the field name is ignored. | |
714 * | |
715 * @param name the case-insensitive field name | |
716 * @exception NumberFormatException If bad long found | |
717 */ | |
718 public long getLongField(Buffer name) throws NumberFormatException | |
719 { | 541 { |
720 Field field = getField(name); | 542 Field field = getField(name); |
721 return field==null?-1L:field.getLongValue(); | 543 return field==null?-1L:field.getLongValue(); |
722 } | 544 } |
723 | 545 |
749 * Sets the value of an long field. | 571 * Sets the value of an long field. |
750 * | 572 * |
751 * @param name the field name | 573 * @param name the field name |
752 * @param value the field long value | 574 * @param value the field long value |
753 */ | 575 */ |
754 public void putLongField(Buffer name, long value) | 576 public void putLongField(String name, long value) |
755 { | 577 { |
756 // Buffer v = BufferUtil.toBuffer(value); | |
757 String v = Long.toString(value); | 578 String v = Long.toString(value); |
758 put(name, v); | 579 put(name, v); |
759 } | 580 } |
760 | 581 |
761 /* -------------------------------------------------------------- */ | 582 /* -------------------------------------------------------------- */ |
763 * Sets the value of an long field. | 584 * Sets the value of an long field. |
764 * | 585 * |
765 * @param name the field name | 586 * @param name the field name |
766 * @param value the field long value | 587 * @param value the field long value |
767 */ | 588 */ |
768 public void putLongField(String name, long value) | |
769 { | |
770 Buffer n = HttpHeaders.CACHE.lookup(name); | |
771 // Buffer v = BufferUtil.toBuffer(value); | |
772 String v = Long.toString(value); | |
773 put(n, v); | |
774 } | |
775 | |
776 /* -------------------------------------------------------------- */ | |
777 /** | |
778 * Sets the value of an long field. | |
779 * | |
780 * @param name the field name | |
781 * @param value the field long value | |
782 */ | |
783 public void addLongField(String name, long value) | 589 public void addLongField(String name, long value) |
784 { | 590 { |
785 Buffer n = HttpHeaders.CACHE.lookup(name); | |
786 // Buffer v = BufferUtil.toBuffer(value); | |
787 String v = Long.toString(value); | |
788 add(n, v); | |
789 } | |
790 | |
791 /* -------------------------------------------------------------- */ | |
792 /** | |
793 * Sets the value of an long field. | |
794 * | |
795 * @param name the field name | |
796 * @param value the field long value | |
797 */ | |
798 public void addLongField(Buffer name, long value) | |
799 { | |
800 // Buffer v = BufferUtil.toBuffer(value); | |
801 String v = Long.toString(value); | 591 String v = Long.toString(value); |
802 add(name, v); | 592 add(name, v); |
803 } | 593 } |
804 | 594 |
805 /* -------------------------------------------------------------- */ | 595 /* -------------------------------------------------------------- */ |
807 * Sets the value of a date field. | 597 * Sets the value of a date field. |
808 * | 598 * |
809 * @param name the field name | 599 * @param name the field name |
810 * @param date the field date value | 600 * @param date the field date value |
811 */ | 601 */ |
812 public void putDateField(Buffer name, long date) | 602 public void putDateField(String name, long date) |
813 { | 603 { |
814 String d=formatDate(date); | 604 String d = formatDate(date); |
815 Buffer v = new ByteArrayBuffer(d); | 605 put(name, d); |
816 put(name, v); | |
817 } | 606 } |
818 | 607 |
819 /* -------------------------------------------------------------- */ | 608 /* -------------------------------------------------------------- */ |
820 /** | 609 /** |
821 * Sets the value of a date field. | 610 * Sets the value of a date field. |
822 * | 611 * |
823 * @param name the field name | 612 * @param name the field name |
824 * @param date the field date value | 613 * @param date the field date value |
825 */ | 614 */ |
826 public void putDateField(String name, long date) | |
827 { | |
828 Buffer n = HttpHeaders.CACHE.lookup(name); | |
829 putDateField(n,date); | |
830 } | |
831 | |
832 /* -------------------------------------------------------------- */ | |
833 /** | |
834 * Sets the value of a date field. | |
835 * | |
836 * @param name the field name | |
837 * @param date the field date value | |
838 */ | |
839 public void addDateField(String name, long date) | 615 public void addDateField(String name, long date) |
840 { | 616 { |
841 String d=formatDate(date); | 617 String d = formatDate(date); |
842 Buffer n = HttpHeaders.CACHE.lookup(name); | 618 add(name, d); |
843 // Buffer v = new ByteArrayBuffer(d); | |
844 add(n, d); | |
845 } | 619 } |
846 | 620 |
847 /* ------------------------------------------------------------ */ | 621 /* ------------------------------------------------------------ */ |
848 /** | 622 /** |
849 * Format a set cookie value | 623 * Format a set cookie value |
963 if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) && | 737 if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) && |
964 ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path)))) | 738 ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path)))) |
965 { | 739 { |
966 _fields.remove(field); | 740 _fields.remove(field); |
967 if (last==null) | 741 if (last==null) |
968 _names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next); | 742 _names.put(HttpHeaders.SET_COOKIE,field._next); |
969 else | 743 else |
970 last._next=field._next; | 744 last._next=field._next; |
971 break; | 745 break; |
972 } | 746 } |
973 } | 747 } |
974 last=field; | 748 last=field; |
975 field=field._next; | 749 field=field._next; |
976 } | 750 } |
977 | 751 |
978 add(HttpHeaders.SET_COOKIE_BUFFER, name_value_params); | 752 add(HttpHeaders.SET_COOKIE, name_value_params); |
979 | 753 |
980 // Expire responses with set-cookie headers so they do not get cached. | 754 // Expire responses with set-cookie headers so they do not get cached. |
981 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER); | 755 put(HttpHeaders.EXPIRES, __01Jan1970); |
982 } | 756 } |
983 | 757 |
984 @Override | 758 @Override |
985 public String toString() | 759 public String toString() |
986 { | 760 { |
1157 } | 931 } |
1158 | 932 |
1159 | 933 |
1160 public static final class Field | 934 public static final class Field |
1161 { | 935 { |
1162 private final Buffer _name; | 936 private final String _name; |
1163 private final String _value; | 937 private final String _value; |
1164 private final int _valueOrdinal; | |
1165 private Field _next; | 938 private Field _next; |
1166 | 939 |
1167 private Field(Buffer name, String value, int valueOrdinal) | 940 private Field(String name, String value) |
1168 { | 941 { |
1169 _name = name; | 942 _name = name; |
1170 _value = value; | 943 _value = value; |
1171 _valueOrdinal = valueOrdinal; | |
1172 _next = null; | 944 _next = null; |
1173 } | 945 } |
1174 /* | 946 |
1175 private Field(Buffer name, Buffer value) | |
1176 { | |
1177 this(name,value.toString(),HttpHeaderValues.CACHE.getOrdinal(value)); | |
1178 } | |
1179 */ | |
1180 public void putTo(Buffer buffer) throws IOException | 947 public void putTo(Buffer buffer) throws IOException |
1181 { | 948 { |
1182 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1; | 949 byte[] nameBytes = StringUtil.getBytes(_name); |
1183 if (o>=0) | 950 if (getNameOrdinal() >=0 ) |
1184 buffer.put(_name); | 951 buffer.put(nameBytes); |
1185 else | 952 else |
1186 { | 953 { |
1187 int s=_name.getIndex(); | 954 for( byte b : nameBytes ) { |
1188 int e=_name.putIndex(); | |
1189 while (s<e) | |
1190 { | |
1191 byte b=_name.peek(s++); | |
1192 switch(b) | 955 switch(b) |
1193 { | 956 { |
1194 case '\r': | 957 case '\r': |
1195 case '\n': | 958 case '\n': |
1196 case ':' : | 959 case ':' : |
1202 } | 965 } |
1203 | 966 |
1204 buffer.put((byte) ':'); | 967 buffer.put((byte) ':'); |
1205 buffer.put((byte) ' '); | 968 buffer.put((byte) ' '); |
1206 | 969 |
1207 o = _valueOrdinal; | |
1208 byte[] valueBytes = StringUtil.getBytes(_value); | 970 byte[] valueBytes = StringUtil.getBytes(_value); |
1209 if (o>=0) | 971 if (getValueOrdinal() >= 0) |
1210 buffer.put(valueBytes); | 972 buffer.put(valueBytes); |
1211 else | 973 else |
1212 { | 974 { |
1213 for( byte b : valueBytes ) { | 975 for( byte b : valueBytes ) { |
1214 switch(b) | 976 switch(b) |
1240 return _value; | 1002 return _value; |
1241 } | 1003 } |
1242 | 1004 |
1243 public int getValueOrdinal() | 1005 public int getValueOrdinal() |
1244 { | 1006 { |
1245 return _valueOrdinal; | 1007 return HttpHeaderValues.CACHE.getOrdinal(_value); |
1246 } | 1008 } |
1247 | 1009 |
1248 public int getIntValue() | 1010 public int getIntValue() |
1249 { | 1011 { |
1250 return (int) getLongValue(); | 1012 return (int) getLongValue(); |