comparison src/org/eclipse/jetty/http/HttpFields.java @ 1020:6be43ef1eb96

HttpHeaderValues uses StringCache
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 31 Oct 2016 22:24:41 -0600
parents f126d30e04a4
children e350c11242be
comparison
equal deleted inserted replaced
1019:f126d30e04a4 1020:6be43ef1eb96
275 275
276 276
277 277
278 private final ArrayList<Field> _fields = new ArrayList<Field>(20); 278 private final ArrayList<Field> _fields = new ArrayList<Field>(20);
279 private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32); 279 private final HashMap<Buffer,Field> _names = new HashMap<Buffer,Field>(32);
280 280 /*
281 /* ------------------------------------------------------------ */
282 /**
283 * Constructor.
284 */
285 public HttpFields()
286 {
287 }
288
289 // TODO externalize this cache so it can be configurable
290 private static ConcurrentMap<String, Buffer> __cache = new ConcurrentHashMap<String, Buffer>();
291 private static int __cacheSize = Integer.getInteger("org.eclipse.jetty.http.HttpFields.CACHE",2000);
292
293 /* -------------------------------------------------------------- */
294 private Buffer convertValue(String value) 281 private Buffer convertValue(String value)
295 { 282 {
296 Buffer buffer = __cache.get(value);
297 if (buffer!=null)
298 return buffer;
299
300 try 283 try
301 { 284 {
302 buffer = new ByteArrayBuffer(value,StringUtil.__ISO_8859_1); 285 return new ByteArrayBuffer(value,StringUtil.__ISO_8859_1);
303
304 if (__cacheSize>0)
305 {
306 if (__cache.size()>__cacheSize)
307 __cache.clear();
308 Buffer b=__cache.putIfAbsent(value,buffer);
309 if (b!=null)
310 buffer=b;
311 }
312
313 return buffer;
314 } 286 }
315 catch (UnsupportedEncodingException e) 287 catch (UnsupportedEncodingException e)
316 { 288 {
317 throw new RuntimeException(e); 289 throw new RuntimeException(e);
318 } 290 }
319 } 291 }
292 */
320 293
321 /* -------------------------------------------------------------- */ 294 /* -------------------------------------------------------------- */
322 /** 295 /**
323 * Get Collection of header names. 296 * Get Collection of header names.
324 */ 297 */
421 return field==null?null:field.getValue(); 394 return field==null?null:field.getValue();
422 } 395 }
423 396
424 /* -------------------------------------------------------------- */ 397 /* -------------------------------------------------------------- */
425 /** 398 /**
426 * @return the value of a field, or null if not found. For multiple fields of the same name,
427 * only the first is returned.
428 * @param name the case-insensitive field name
429 */
430 public Buffer get(Buffer name)
431 {
432 Field field = getField(name);
433 return field==null?null:field._value;
434 }
435
436
437 /* -------------------------------------------------------------- */
438 /**
439 * Get multi headers 399 * Get multi headers
440 * 400 *
441 * @return Enumeration of the values, or null if no such header. 401 * @return Enumeration of the values, or null if no such header.
442 * @param name the case-insensitive field name 402 * @param name the case-insensitive field name
443 */ 403 */
444 public Collection<String> getValuesCollection(String name) 404 public Collection<String> getValuesCollection(String name)
445 { 405 {
446 Field field = getField(name); 406 Field field = getField(name);
447 if (field==null) 407 if (field==null)
448 return null; 408 return null;
449 409
450 final List<String> list = new ArrayList<String>(); 410 final List<String> list = new ArrayList<String>();
451 411
452 while(field!=null) 412 while(field!=null)
453 { 413 {
454 list.add(field.getValue()); 414 list.add(field.getValue());
455 field=field._next; 415 field=field._next;
456 } 416 }
457 return list; 417 return list;
458 } 418 }
459 419
460 /* -------------------------------------------------------------- */ 420 /* -------------------------------------------------------------- */
461 /** 421 /**
462 * Get multi headers 422 * Get multi headers
582 if (value==null) 542 if (value==null)
583 remove(name); 543 remove(name);
584 else 544 else
585 { 545 {
586 Buffer n = HttpHeaders.CACHE.lookup(name); 546 Buffer n = HttpHeaders.CACHE.lookup(name);
587 Buffer v = convertValue(value); 547 put(n, value);
588 put(n, v);
589 } 548 }
590 } 549 }
591 550
592 /* -------------------------------------------------------------- */ 551 /* -------------------------------------------------------------- */
593 /** 552 /**
596 * @param name the name of the field 555 * @param name the name of the field
597 * @param value the value of the field. If null the field is cleared. 556 * @param value the value of the field. If null the field is cleared.
598 */ 557 */
599 public void put(Buffer name, String value) 558 public void put(Buffer name, String value)
600 { 559 {
560 /*
601 Buffer n = HttpHeaders.CACHE.lookup(name); 561 Buffer n = HttpHeaders.CACHE.lookup(name);
602 Buffer v = convertValue(value); 562 Buffer v = convertValue(value);
603 put(n, v); 563 put(n, v);
604 } 564 */
605
606 /* -------------------------------------------------------------- */
607 /**
608 * Set a field.
609 *
610 * @param name the name of the field
611 * @param value the value of the field. If null the field is cleared.
612 */
613 public void put(Buffer name, Buffer value)
614 {
615 remove(name); 565 remove(name);
616 if (value == null) 566 if (value == null)
617 return; 567 return;
618 568
619 if (!(name instanceof BufferCache.CachedBuffer)) 569 if (!(name instanceof BufferCache.CachedBuffer))
620 name = HttpHeaders.CACHE.lookup(name); 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);
621 if (!(value instanceof CachedBuffer)) 595 if (!(value instanceof CachedBuffer))
622 value= HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer(); 596 value = HttpHeaderValues.CACHE.lookup(value).asImmutableBuffer();
623 597
624 // new value; 598 // new value;
625 Field field = new Field(name, value); 599 Field field = new Field(name, value);
626 _fields.add(field); 600 _fields.add(field);
627 _names.put(name, field); 601 _names.put(name, field);
628 } 602 */
629 603 String s = value==null ? null : value.toString();
630 /* -------------------------------------------------------------- */ 604 put(name,s);
631 /**
632 * Set a field.
633 *
634 * @param name the name of the field
635 * @param list the List value of the field. If null the field is cleared.
636 */
637 public void put(String name, List<?> list)
638 {
639 if (list == null || list.size() == 0)
640 {
641 remove(name);
642 return;
643 }
644 Buffer n = HttpHeaders.CACHE.lookup(name);
645
646 Object v = list.get(0);
647 if (v != null)
648 put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
649 else
650 remove(n);
651
652 if (list.size() > 1)
653 {
654 java.util.Iterator<?> iter = list.iterator();
655 iter.next();
656 while (iter.hasNext())
657 {
658 v = iter.next();
659 if (v != null) put(n, HttpHeaderValues.CACHE.lookup(v.toString()));
660 }
661 }
662 } 605 }
663 606
664 /* -------------------------------------------------------------- */ 607 /* -------------------------------------------------------------- */
665 /** 608 /**
666 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple 609 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple
674 public void add(String name, String value) throws IllegalArgumentException 617 public void add(String name, String value) throws IllegalArgumentException
675 { 618 {
676 if (value==null) 619 if (value==null)
677 return; 620 return;
678 Buffer n = HttpHeaders.CACHE.lookup(name); 621 Buffer n = HttpHeaders.CACHE.lookup(name);
679 Buffer v = convertValue(value); 622 add(n, value);
680 add(n, v);
681 } 623 }
682 624
683 /* -------------------------------------------------------------- */ 625 /* -------------------------------------------------------------- */
684 /** 626 /**
685 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple 627 * Add to or set a field. If the field is allowed to have multiple values, add will add multiple
688 * @param name the name of the field 630 * @param name the name of the field
689 * @param value the value of the field. 631 * @param value the value of the field.
690 * @exception IllegalArgumentException If the name is a single valued field and already has a 632 * @exception IllegalArgumentException If the name is a single valued field and already has a
691 * value. 633 * value.
692 */ 634 */
693 public void add(Buffer name, Buffer value) throws IllegalArgumentException 635 public void add(Buffer name, String value) throws IllegalArgumentException
694 { 636 {
695 if (value == null) throw new IllegalArgumentException("null value"); 637 if (value == null) throw new IllegalArgumentException("null value");
696 638
697 if (!(name instanceof CachedBuffer)) 639 if (!(name instanceof CachedBuffer))
698 name = HttpHeaders.CACHE.lookup(name); 640 name = HttpHeaders.CACHE.lookup(name);
699 name=name.asImmutableBuffer(); 641 name=name.asImmutableBuffer();
700 642 /*
701 if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name))) 643 if (!(value instanceof CachedBuffer) && HttpHeaderValues.hasKnownValues(HttpHeaders.CACHE.getOrdinal(name)))
702 value= HttpHeaderValues.CACHE.lookup(value); 644 value= HttpHeaderValues.CACHE.lookup(value);
703 value=value.asImmutableBuffer(); 645 value=value.asImmutableBuffer();
704 646 */
705 Field field = _names.get(name); 647 Field field = _names.get(name);
706 Field last = null; 648 Field last = null;
707 while (field != null) 649 while (field != null)
708 { 650 {
709 last = field; 651 last = field;
710 field = field._next; 652 field = field._next;
711 } 653 }
712 654
713 // create the field 655 // create the field
714 field = new Field(name, value); 656 int valueOrdinal = HttpHeaderValues.CACHE.getOrdinal(value);
657 field = new Field(name, value, valueOrdinal);
715 _fields.add(field); 658 _fields.add(field);
716 659
717 // look for chain to add too 660 // look for chain to add too
718 if (last != null) 661 if (last != null)
719 last._next = field; 662 last._next = field;
789 { 732 {
790 Field field = getField(name); 733 Field field = getField(name);
791 if (field == null) 734 if (field == null)
792 return -1; 735 return -1;
793 736
794 String val = valueParameters(BufferUtil.to8859_1_String(field._value), null); 737 String val = valueParameters(field._value, null);
795 if (val == null) 738 if (val == null)
796 return -1; 739 return -1;
797 740
798 final long date = __dateParser.get().parse(val); 741 final long date = __dateParser.get().parse(val);
799 if (date==-1) 742 if (date==-1)
808 * @param name the field name 751 * @param name the field name
809 * @param value the field long value 752 * @param value the field long value
810 */ 753 */
811 public void putLongField(Buffer name, long value) 754 public void putLongField(Buffer name, long value)
812 { 755 {
813 Buffer v = BufferUtil.toBuffer(value); 756 // Buffer v = BufferUtil.toBuffer(value);
757 String v = Long.toString(value);
814 put(name, v); 758 put(name, v);
815 } 759 }
816 760
817 /* -------------------------------------------------------------- */ 761 /* -------------------------------------------------------------- */
818 /** 762 /**
822 * @param value the field long value 766 * @param value the field long value
823 */ 767 */
824 public void putLongField(String name, long value) 768 public void putLongField(String name, long value)
825 { 769 {
826 Buffer n = HttpHeaders.CACHE.lookup(name); 770 Buffer n = HttpHeaders.CACHE.lookup(name);
827 Buffer v = BufferUtil.toBuffer(value); 771 // Buffer v = BufferUtil.toBuffer(value);
772 String v = Long.toString(value);
828 put(n, v); 773 put(n, v);
829 } 774 }
830 775
831 /* -------------------------------------------------------------- */ 776 /* -------------------------------------------------------------- */
832 /** 777 /**
836 * @param value the field long value 781 * @param value the field long value
837 */ 782 */
838 public void addLongField(String name, long value) 783 public void addLongField(String name, long value)
839 { 784 {
840 Buffer n = HttpHeaders.CACHE.lookup(name); 785 Buffer n = HttpHeaders.CACHE.lookup(name);
841 Buffer v = BufferUtil.toBuffer(value); 786 // Buffer v = BufferUtil.toBuffer(value);
787 String v = Long.toString(value);
842 add(n, v); 788 add(n, v);
843 } 789 }
844 790
845 /* -------------------------------------------------------------- */ 791 /* -------------------------------------------------------------- */
846 /** 792 /**
849 * @param name the field name 795 * @param name the field name
850 * @param value the field long value 796 * @param value the field long value
851 */ 797 */
852 public void addLongField(Buffer name, long value) 798 public void addLongField(Buffer name, long value)
853 { 799 {
854 Buffer v = BufferUtil.toBuffer(value); 800 // Buffer v = BufferUtil.toBuffer(value);
801 String v = Long.toString(value);
855 add(name, v); 802 add(name, v);
856 } 803 }
857 804
858 /* -------------------------------------------------------------- */ 805 /* -------------------------------------------------------------- */
859 /** 806 /**
891 */ 838 */
892 public void addDateField(String name, long date) 839 public void addDateField(String name, long date)
893 { 840 {
894 String d=formatDate(date); 841 String d=formatDate(date);
895 Buffer n = HttpHeaders.CACHE.lookup(name); 842 Buffer n = HttpHeaders.CACHE.lookup(name);
896 Buffer v = new ByteArrayBuffer(d); 843 // Buffer v = new ByteArrayBuffer(d);
897 add(n, v); 844 add(n, d);
898 } 845 }
899 846
900 /* ------------------------------------------------------------ */ 847 /* ------------------------------------------------------------ */
901 /** 848 /**
902 * Format a set cookie value 849 * Format a set cookie value
1026 } 973 }
1027 last=field; 974 last=field;
1028 field=field._next; 975 field=field._next;
1029 } 976 }
1030 977
1031 add(HttpHeaders.SET_COOKIE_BUFFER, new ByteArrayBuffer(name_value_params)); 978 add(HttpHeaders.SET_COOKIE_BUFFER, name_value_params);
1032 979
1033 // Expire responses with set-cookie headers so they do not get cached. 980 // Expire responses with set-cookie headers so they do not get cached.
1034 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER); 981 put(HttpHeaders.EXPIRES_BUFFER, __01Jan1970_BUFFER);
1035 } 982 }
1036 983
1037 /* -------------------------------------------------------------- */ 984 @Override
1038 public void putTo(Buffer buffer) throws IOException
1039 {
1040 for (int i = 0; i < _fields.size(); i++)
1041 {
1042 Field field = _fields.get(i);
1043 if (field != null)
1044 field.putTo(buffer);
1045 }
1046 BufferUtil.putCRLF(buffer);
1047 }
1048
1049 /* -------------------------------------------------------------- */
1050 public String toString() 985 public String toString()
1051 { 986 {
1052 try 987 try
1053 { 988 {
1054 StringBuffer buffer = new StringBuffer(); 989 StringBuffer buffer = new StringBuffer();
1219 } 1154 }
1220 ql.clear(); 1155 ql.clear();
1221 return vl; 1156 return vl;
1222 } 1157 }
1223 1158
1224 /* ------------------------------------------------------------ */ 1159
1225 /* ------------------------------------------------------------ */
1226 /* ------------------------------------------------------------ */
1227 public static final class Field 1160 public static final class Field
1228 { 1161 {
1229 private Buffer _name; 1162 private final Buffer _name;
1230 private Buffer _value; 1163 private final String _value;
1164 private final int _valueOrdinal;
1231 private Field _next; 1165 private Field _next;
1232 1166
1233 /* ------------------------------------------------------------ */ 1167 private Field(Buffer name, String value, int valueOrdinal)
1234 private Field(Buffer name, Buffer value)
1235 { 1168 {
1236 _name = name; 1169 _name = name;
1237 _value = value; 1170 _value = value;
1171 _valueOrdinal = valueOrdinal;
1238 _next = null; 1172 _next = null;
1239 } 1173 }
1240 1174 /*
1241 /* ------------------------------------------------------------ */ 1175 private Field(Buffer name, Buffer value)
1176 {
1177 this(name,value.toString(),HttpHeaderValues.CACHE.getOrdinal(value));
1178 }
1179 */
1242 public void putTo(Buffer buffer) throws IOException 1180 public void putTo(Buffer buffer) throws IOException
1243 { 1181 {
1244 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1; 1182 int o=(_name instanceof CachedBuffer)?((CachedBuffer)_name).getOrdinal():-1;
1245 if (o>=0) 1183 if (o>=0)
1246 buffer.put(_name); 1184 buffer.put(_name);
1264 } 1202 }
1265 1203
1266 buffer.put((byte) ':'); 1204 buffer.put((byte) ':');
1267 buffer.put((byte) ' '); 1205 buffer.put((byte) ' ');
1268 1206
1269 o=(_value instanceof CachedBuffer)?((CachedBuffer)_value).getOrdinal():-1; 1207 o = _valueOrdinal;
1208 byte[] valueBytes = StringUtil.getBytes(_value);
1270 if (o>=0) 1209 if (o>=0)
1271 buffer.put(_value); 1210 buffer.put(valueBytes);
1272 else 1211 else
1273 { 1212 {
1274 int s=_value.getIndex(); 1213 for( byte b : valueBytes ) {
1275 int e=_value.putIndex();
1276 while (s<e)
1277 {
1278 byte b=_value.peek(s++);
1279 switch(b) 1214 switch(b)
1280 { 1215 {
1281 case '\r': 1216 case '\r':
1282 case '\n': 1217 case '\n':
1283 continue; 1218 continue;
1288 } 1223 }
1289 1224
1290 BufferUtil.putCRLF(buffer); 1225 BufferUtil.putCRLF(buffer);
1291 } 1226 }
1292 1227
1293 /* ------------------------------------------------------------ */ 1228 private String getName()
1294 public String getName()
1295 { 1229 {
1296 return BufferUtil.to8859_1_String(_name); 1230 return BufferUtil.to8859_1_String(_name);
1297 } 1231 }
1298 1232
1299 /* ------------------------------------------------------------ */
1300 Buffer getNameBuffer()
1301 {
1302 return _name;
1303 }
1304
1305 /* ------------------------------------------------------------ */
1306 public int getNameOrdinal() 1233 public int getNameOrdinal()
1307 { 1234 {
1308 return HttpHeaders.CACHE.getOrdinal(_name); 1235 return HttpHeaders.CACHE.getOrdinal(_name);
1309 } 1236 }
1310 1237
1311 /* ------------------------------------------------------------ */
1312 public String getValue() 1238 public String getValue()
1313 { 1239 {
1314 return BufferUtil.to8859_1_String(_value);
1315 }
1316
1317 /* ------------------------------------------------------------ */
1318 public Buffer getValueBuffer()
1319 {
1320 return _value; 1240 return _value;
1321 } 1241 }
1322 1242
1323 /* ------------------------------------------------------------ */
1324 public int getValueOrdinal() 1243 public int getValueOrdinal()
1325 { 1244 {
1326 return HttpHeaderValues.CACHE.getOrdinal(_value); 1245 return _valueOrdinal;
1327 } 1246 }
1328 1247
1329 /* ------------------------------------------------------------ */
1330 public int getIntValue() 1248 public int getIntValue()
1331 { 1249 {
1332 return (int) getLongValue(); 1250 return (int) getLongValue();
1333 } 1251 }
1334 1252
1335 /* ------------------------------------------------------------ */
1336 public long getLongValue() 1253 public long getLongValue()
1337 { 1254 {
1338 return BufferUtil.toLong(_value); 1255 return BufferUtil.toLong(_value);
1339 } 1256 }
1340 1257
1341 /* ------------------------------------------------------------ */ 1258 @Override
1342 public String toString() 1259 public String toString()
1343 { 1260 {
1344 return ("[" + getName() + "=" + _value + (_next == null ? "" : "->") + "]"); 1261 return ("[" + getName() + "=" + _value + (_next == null ? "" : "->") + "]");
1345 } 1262 }
1346 } 1263 }