1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package io.netty.handler.codec;
16
17 import io.netty.util.HashingStrategy;
18 import io.netty.util.concurrent.FastThreadLocal;
19 import io.netty.util.internal.SystemPropertyUtil;
20
21 import java.text.DateFormat;
22 import java.text.ParseException;
23 import java.text.SimpleDateFormat;
24 import java.util.Arrays;
25 import java.util.Collections;
26 import java.util.Date;
27 import java.util.Iterator;
28 import java.util.LinkedHashSet;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Locale;
32 import java.util.Map;
33 import java.util.Map.Entry;
34 import java.util.NoSuchElementException;
35 import java.util.Set;
36 import java.util.TimeZone;
37
38 import static io.netty.util.HashingStrategy.JAVA_HASHER;
39 import static io.netty.util.internal.MathUtil.findNextPositivePowerOfTwo;
40 import static io.netty.util.internal.ObjectUtil.checkNotNull;
41 import static java.lang.Math.min;
42 import static java.lang.Math.max;
43
44
45
46
47
48
49
50
51 public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers<K, V, T> {
52
53
54
55
56 private static final int ARRAY_SIZE_HINT_MAX = min(128,
57 max(1, SystemPropertyUtil.getInt("io.netty.DefaultHeaders.arraySizeHintMax", 16)));
58
59
60
61 static final int HASH_CODE_SEED = 0xc2b2ae35;
62
63 private final HeaderEntry<K, V>[] entries;
64 protected final HeaderEntry<K, V> head;
65
66 private final byte hashMask;
67 private final ValueConverter<V> valueConverter;
68 private final NameValidator<K> nameValidator;
69 private final HashingStrategy<K> hashingStrategy;
70 int size;
71
72 public interface NameValidator<K> {
73
74
75
76
77
78 void validateName(K name);
79
80 @SuppressWarnings("rawtypes")
81 NameValidator NOT_NULL = new NameValidator() {
82 @Override
83 public void validateName(Object name) {
84 checkNotNull(name, "name");
85 }
86 };
87 }
88
89 @SuppressWarnings("unchecked")
90 public DefaultHeaders(ValueConverter<V> valueConverter) {
91 this(JAVA_HASHER, valueConverter);
92 }
93
94 @SuppressWarnings("unchecked")
95 public DefaultHeaders(ValueConverter<V> valueConverter, NameValidator<K> nameValidator) {
96 this(JAVA_HASHER, valueConverter, nameValidator);
97 }
98
99 @SuppressWarnings("unchecked")
100 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy, ValueConverter<V> valueConverter) {
101 this(nameHashingStrategy, valueConverter, NameValidator.NOT_NULL);
102 }
103
104 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy,
105 ValueConverter<V> valueConverter, NameValidator<K> nameValidator) {
106 this(nameHashingStrategy, valueConverter, nameValidator, 16);
107 }
108
109
110
111
112
113
114
115
116
117 @SuppressWarnings("unchecked")
118 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy,
119 ValueConverter<V> valueConverter, NameValidator<K> nameValidator, int arraySizeHint) {
120 this.valueConverter = checkNotNull(valueConverter, "valueConverter");
121 this.nameValidator = checkNotNull(nameValidator, "nameValidator");
122 this.hashingStrategy = checkNotNull(nameHashingStrategy, "nameHashingStrategy");
123 entries = new DefaultHeaders.HeaderEntry[findNextPositivePowerOfTwo(min(arraySizeHint, ARRAY_SIZE_HINT_MAX))];
124 hashMask = (byte) (entries.length - 1);
125 head = new HeaderEntry<K, V>();
126 }
127
128 @Override
129 public V get(K name) {
130 checkNotNull(name, "name");
131
132 int h = hashingStrategy.hashCode(name);
133 int i = index(h);
134 HeaderEntry<K, V> e = entries[i];
135 V value = null;
136
137 while (e != null) {
138 if (e.hash == h && hashingStrategy.equals(name, e.key)) {
139 value = e.value;
140 }
141
142 e = e.next;
143 }
144 return value;
145 }
146
147 @Override
148 public V get(K name, V defaultValue) {
149 V value = get(name);
150 if (value == null) {
151 return defaultValue;
152 }
153 return value;
154 }
155
156 @Override
157 public V getAndRemove(K name) {
158 int h = hashingStrategy.hashCode(name);
159 return remove0(h, index(h), checkNotNull(name, "name"));
160 }
161
162 @Override
163 public V getAndRemove(K name, V defaultValue) {
164 V value = getAndRemove(name);
165 if (value == null) {
166 return defaultValue;
167 }
168 return value;
169 }
170
171 @Override
172 public List<V> getAll(K name) {
173 checkNotNull(name, "name");
174
175 LinkedList<V> values = new LinkedList<V>();
176
177 int h = hashingStrategy.hashCode(name);
178 int i = index(h);
179 HeaderEntry<K, V> e = entries[i];
180 while (e != null) {
181 if (e.hash == h && hashingStrategy.equals(name, e.key)) {
182 values.addFirst(e.getValue());
183 }
184 e = e.next;
185 }
186 return values;
187 }
188
189 @Override
190 public List<V> getAllAndRemove(K name) {
191 List<V> all = getAll(name);
192 remove(name);
193 return all;
194 }
195
196 @Override
197 public boolean contains(K name) {
198 return get(name) != null;
199 }
200
201 @Override
202 public boolean containsObject(K name, Object value) {
203 return contains(name, valueConverter.convertObject(checkNotNull(value, "value")));
204 }
205
206 @Override
207 public boolean containsBoolean(K name, boolean value) {
208 return contains(name, valueConverter.convertBoolean(value));
209 }
210
211 @Override
212 public boolean containsByte(K name, byte value) {
213 return contains(name, valueConverter.convertByte(value));
214 }
215
216 @Override
217 public boolean containsChar(K name, char value) {
218 return contains(name, valueConverter.convertChar(value));
219 }
220
221 @Override
222 public boolean containsShort(K name, short value) {
223 return contains(name, valueConverter.convertShort(value));
224 }
225
226 @Override
227 public boolean containsInt(K name, int value) {
228 return contains(name, valueConverter.convertInt(value));
229 }
230
231 @Override
232 public boolean containsLong(K name, long value) {
233 return contains(name, valueConverter.convertLong(value));
234 }
235
236 @Override
237 public boolean containsFloat(K name, float value) {
238 return contains(name, valueConverter.convertFloat(value));
239 }
240
241 @Override
242 public boolean containsDouble(K name, double value) {
243 return contains(name, valueConverter.convertDouble(value));
244 }
245
246 @Override
247 public boolean containsTimeMillis(K name, long value) {
248 return contains(name, valueConverter.convertTimeMillis(value));
249 }
250
251 @SuppressWarnings("unchecked")
252 @Override
253 public boolean contains(K name, V value) {
254 return contains(name, value, JAVA_HASHER);
255 }
256
257 public final boolean contains(K name, V value, HashingStrategy<? super V> valueHashingStrategy) {
258 checkNotNull(name, "name");
259
260 int h = hashingStrategy.hashCode(name);
261 int i = index(h);
262 HeaderEntry<K, V> e = entries[i];
263 while (e != null) {
264 if (e.hash == h && hashingStrategy.equals(name, e.key) && valueHashingStrategy.equals(value, e.value)) {
265 return true;
266 }
267 e = e.next;
268 }
269 return false;
270 }
271
272 @Override
273 public int size() {
274 return size;
275 }
276
277 @Override
278 public boolean isEmpty() {
279 return head == head.after;
280 }
281
282 @Override
283 public Set<K> names() {
284 if (isEmpty()) {
285 return Collections.emptySet();
286 }
287 Set<K> names = new LinkedHashSet<K>(size());
288 HeaderEntry<K, V> e = head.after;
289 while (e != head) {
290 names.add(e.getKey());
291 e = e.after;
292 }
293 return names;
294 }
295
296 @Override
297 public T add(K name, V value) {
298 nameValidator.validateName(name);
299 checkNotNull(value, "value");
300 int h = hashingStrategy.hashCode(name);
301 int i = index(h);
302 add0(h, i, name, value);
303 return thisT();
304 }
305
306 @Override
307 public T add(K name, Iterable<? extends V> values) {
308 nameValidator.validateName(name);
309 int h = hashingStrategy.hashCode(name);
310 int i = index(h);
311 for (V v: values) {
312 add0(h, i, name, v);
313 }
314 return thisT();
315 }
316
317 @Override
318 public T add(K name, V... values) {
319 nameValidator.validateName(name);
320 int h = hashingStrategy.hashCode(name);
321 int i = index(h);
322 for (V v: values) {
323 add0(h, i, name, v);
324 }
325 return thisT();
326 }
327
328 @Override
329 public T addObject(K name, Object value) {
330 return add(name, valueConverter.convertObject(checkNotNull(value, "value")));
331 }
332
333 @Override
334 public T addObject(K name, Iterable<?> values) {
335 for (Object value : values) {
336 addObject(name, value);
337 }
338 return thisT();
339 }
340
341 @Override
342 public T addObject(K name, Object... values) {
343 for (int i = 0; i < values.length; i++) {
344 addObject(name, values[i]);
345 }
346 return thisT();
347 }
348
349 @Override
350 public T addInt(K name, int value) {
351 return add(name, valueConverter.convertInt(value));
352 }
353
354 @Override
355 public T addLong(K name, long value) {
356 return add(name, valueConverter.convertLong(value));
357 }
358
359 @Override
360 public T addDouble(K name, double value) {
361 return add(name, valueConverter.convertDouble(value));
362 }
363
364 @Override
365 public T addTimeMillis(K name, long value) {
366 return add(name, valueConverter.convertTimeMillis(value));
367 }
368
369 @Override
370 public T addChar(K name, char value) {
371 return add(name, valueConverter.convertChar(value));
372 }
373
374 @Override
375 public T addBoolean(K name, boolean value) {
376 return add(name, valueConverter.convertBoolean(value));
377 }
378
379 @Override
380 public T addFloat(K name, float value) {
381 return add(name, valueConverter.convertFloat(value));
382 }
383
384 @Override
385 public T addByte(K name, byte value) {
386 return add(name, valueConverter.convertByte(value));
387 }
388
389 @Override
390 public T addShort(K name, short value) {
391 return add(name, valueConverter.convertShort(value));
392 }
393
394 @Override
395 public T add(Headers<? extends K, ? extends V, ?> headers) {
396 if (headers == this) {
397 throw new IllegalArgumentException("can't add to itself.");
398 }
399 addImpl(headers);
400 return thisT();
401 }
402
403 protected void addImpl(Headers<? extends K, ? extends V, ?> headers) {
404 if (headers instanceof DefaultHeaders) {
405 @SuppressWarnings("unchecked")
406 final DefaultHeaders<? extends K, ? extends V, T> defaultHeaders =
407 (DefaultHeaders<? extends K, ? extends V, T>) headers;
408 HeaderEntry<? extends K, ? extends V> e = defaultHeaders.head.after;
409 if (defaultHeaders.hashingStrategy == hashingStrategy &&
410 defaultHeaders.nameValidator == nameValidator) {
411
412 while (e != defaultHeaders.head) {
413 add0(e.hash, index(e.hash), e.key, e.value);
414 e = e.after;
415 }
416 } else {
417
418 while (e != defaultHeaders.head) {
419 add(e.key, e.value);
420 e = e.after;
421 }
422 }
423 } else {
424
425 for (Entry<? extends K, ? extends V> header : headers) {
426 add(header.getKey(), header.getValue());
427 }
428 }
429 }
430
431 @Override
432 public T set(K name, V value) {
433 nameValidator.validateName(name);
434 checkNotNull(value, "value");
435 int h = hashingStrategy.hashCode(name);
436 int i = index(h);
437 remove0(h, i, name);
438 add0(h, i, name, value);
439 return thisT();
440 }
441
442 @Override
443 public T set(K name, Iterable<? extends V> values) {
444 nameValidator.validateName(name);
445 checkNotNull(values, "values");
446
447 int h = hashingStrategy.hashCode(name);
448 int i = index(h);
449
450 remove0(h, i, name);
451 for (V v: values) {
452 if (v == null) {
453 break;
454 }
455 add0(h, i, name, v);
456 }
457
458 return thisT();
459 }
460
461 @Override
462 public T set(K name, V... values) {
463 nameValidator.validateName(name);
464 checkNotNull(values, "values");
465
466 int h = hashingStrategy.hashCode(name);
467 int i = index(h);
468
469 remove0(h, i, name);
470 for (V v: values) {
471 if (v == null) {
472 break;
473 }
474 add0(h, i, name, v);
475 }
476
477 return thisT();
478 }
479
480 @Override
481 public T setObject(K name, Object value) {
482 checkNotNull(value, "value");
483 V convertedValue = checkNotNull(valueConverter.convertObject(value), "convertedValue");
484 return set(name, convertedValue);
485 }
486
487 @Override
488 public T setObject(K name, Iterable<?> values) {
489 nameValidator.validateName(name);
490
491 int h = hashingStrategy.hashCode(name);
492 int i = index(h);
493
494 remove0(h, i, name);
495 for (Object v: values) {
496 if (v == null) {
497 break;
498 }
499 add0(h, i, name, valueConverter.convertObject(v));
500 }
501
502 return thisT();
503 }
504
505 @Override
506 public T setObject(K name, Object... values) {
507 nameValidator.validateName(name);
508
509 int h = hashingStrategy.hashCode(name);
510 int i = index(h);
511
512 remove0(h, i, name);
513 for (Object v: values) {
514 if (v == null) {
515 break;
516 }
517 add0(h, i, name, valueConverter.convertObject(v));
518 }
519
520 return thisT();
521 }
522
523 @Override
524 public T setInt(K name, int value) {
525 return set(name, valueConverter.convertInt(value));
526 }
527
528 @Override
529 public T setLong(K name, long value) {
530 return set(name, valueConverter.convertLong(value));
531 }
532
533 @Override
534 public T setDouble(K name, double value) {
535 return set(name, valueConverter.convertDouble(value));
536 }
537
538 @Override
539 public T setTimeMillis(K name, long value) {
540 return set(name, valueConverter.convertTimeMillis(value));
541 }
542
543 @Override
544 public T setFloat(K name, float value) {
545 return set(name, valueConverter.convertFloat(value));
546 }
547
548 @Override
549 public T setChar(K name, char value) {
550 return set(name, valueConverter.convertChar(value));
551 }
552
553 @Override
554 public T setBoolean(K name, boolean value) {
555 return set(name, valueConverter.convertBoolean(value));
556 }
557
558 @Override
559 public T setByte(K name, byte value) {
560 return set(name, valueConverter.convertByte(value));
561 }
562
563 @Override
564 public T setShort(K name, short value) {
565 return set(name, valueConverter.convertShort(value));
566 }
567
568 @Override
569 public T set(Headers<? extends K, ? extends V, ?> headers) {
570 if (headers != this) {
571 clear();
572 addImpl(headers);
573 }
574 return thisT();
575 }
576
577 @Override
578 public T setAll(Headers<? extends K, ? extends V, ?> headers) {
579 if (headers != this) {
580 for (K key : headers.names()) {
581 remove(key);
582 }
583 addImpl(headers);
584 }
585 return thisT();
586 }
587
588 @Override
589 public boolean remove(K name) {
590 return getAndRemove(name) != null;
591 }
592
593 @Override
594 public T clear() {
595 Arrays.fill(entries, null);
596 head.before = head.after = head;
597 size = 0;
598 return thisT();
599 }
600
601 @Override
602 public Iterator<Entry<K, V>> iterator() {
603 return new HeaderIterator();
604 }
605
606 @Override
607 public Boolean getBoolean(K name) {
608 V v = get(name);
609 return v != null ? valueConverter.convertToBoolean(v) : null;
610 }
611
612 @Override
613 public boolean getBoolean(K name, boolean defaultValue) {
614 Boolean v = getBoolean(name);
615 return v != null ? v : defaultValue;
616 }
617
618 @Override
619 public Byte getByte(K name) {
620 V v = get(name);
621 return v != null ? valueConverter.convertToByte(v) : null;
622 }
623
624 @Override
625 public byte getByte(K name, byte defaultValue) {
626 Byte v = getByte(name);
627 return v != null ? v : defaultValue;
628 }
629
630 @Override
631 public Character getChar(K name) {
632 V v = get(name);
633 return v != null ? valueConverter.convertToChar(v) : null;
634 }
635
636 @Override
637 public char getChar(K name, char defaultValue) {
638 Character v = getChar(name);
639 return v != null ? v : defaultValue;
640 }
641
642 @Override
643 public Short getShort(K name) {
644 V v = get(name);
645 return v != null ? valueConverter.convertToShort(v) : null;
646 }
647
648 @Override
649 public short getShort(K name, short defaultValue) {
650 Short v = getShort(name);
651 return v != null ? v : defaultValue;
652 }
653
654 @Override
655 public Integer getInt(K name) {
656 V v = get(name);
657 return v != null ? valueConverter.convertToInt(v) : null;
658 }
659
660 @Override
661 public int getInt(K name, int defaultValue) {
662 Integer v = getInt(name);
663 return v != null ? v : defaultValue;
664 }
665
666 @Override
667 public Long getLong(K name) {
668 V v = get(name);
669 return v != null ? valueConverter.convertToLong(v) : null;
670 }
671
672 @Override
673 public long getLong(K name, long defaultValue) {
674 Long v = getLong(name);
675 return v != null ? v : defaultValue;
676 }
677
678 @Override
679 public Float getFloat(K name) {
680 V v = get(name);
681 return v != null ? valueConverter.convertToFloat(v) : null;
682 }
683
684 @Override
685 public float getFloat(K name, float defaultValue) {
686 Float v = getFloat(name);
687 return v != null ? v : defaultValue;
688 }
689
690 @Override
691 public Double getDouble(K name) {
692 V v = get(name);
693 return v != null ? valueConverter.convertToDouble(v) : null;
694 }
695
696 @Override
697 public double getDouble(K name, double defaultValue) {
698 Double v = getDouble(name);
699 return v != null ? v : defaultValue;
700 }
701
702 @Override
703 public Long getTimeMillis(K name) {
704 V v = get(name);
705 return v != null ? valueConverter.convertToTimeMillis(v) : null;
706 }
707
708 @Override
709 public long getTimeMillis(K name, long defaultValue) {
710 Long v = getTimeMillis(name);
711 return v != null ? v : defaultValue;
712 }
713
714 @Override
715 public Boolean getBooleanAndRemove(K name) {
716 V v = getAndRemove(name);
717 return v != null ? valueConverter.convertToBoolean(v) : null;
718 }
719
720 @Override
721 public boolean getBooleanAndRemove(K name, boolean defaultValue) {
722 Boolean v = getBooleanAndRemove(name);
723 return v != null ? v : defaultValue;
724 }
725
726 @Override
727 public Byte getByteAndRemove(K name) {
728 V v = getAndRemove(name);
729 return v != null ? valueConverter.convertToByte(v) : null;
730 }
731
732 @Override
733 public byte getByteAndRemove(K name, byte defaultValue) {
734 Byte v = getByteAndRemove(name);
735 return v != null ? v : defaultValue;
736 }
737
738 @Override
739 public Character getCharAndRemove(K name) {
740 V v = getAndRemove(name);
741 if (v == null) {
742 return null;
743 }
744 try {
745 return valueConverter.convertToChar(v);
746 } catch (Throwable ignored) {
747 return null;
748 }
749 }
750
751 @Override
752 public char getCharAndRemove(K name, char defaultValue) {
753 Character v = getCharAndRemove(name);
754 return v != null ? v : defaultValue;
755 }
756
757 @Override
758 public Short getShortAndRemove(K name) {
759 V v = getAndRemove(name);
760 return v != null ? valueConverter.convertToShort(v) : null;
761 }
762
763 @Override
764 public short getShortAndRemove(K name, short defaultValue) {
765 Short v = getShortAndRemove(name);
766 return v != null ? v : defaultValue;
767 }
768
769 @Override
770 public Integer getIntAndRemove(K name) {
771 V v = getAndRemove(name);
772 return v != null ? valueConverter.convertToInt(v) : null;
773 }
774
775 @Override
776 public int getIntAndRemove(K name, int defaultValue) {
777 Integer v = getIntAndRemove(name);
778 return v != null ? v : defaultValue;
779 }
780
781 @Override
782 public Long getLongAndRemove(K name) {
783 V v = getAndRemove(name);
784 return v != null ? valueConverter.convertToLong(v) : null;
785 }
786
787 @Override
788 public long getLongAndRemove(K name, long defaultValue) {
789 Long v = getLongAndRemove(name);
790 return v != null ? v : defaultValue;
791 }
792
793 @Override
794 public Float getFloatAndRemove(K name) {
795 V v = getAndRemove(name);
796 return v != null ? valueConverter.convertToFloat(v) : null;
797 }
798
799 @Override
800 public float getFloatAndRemove(K name, float defaultValue) {
801 Float v = getFloatAndRemove(name);
802 return v != null ? v : defaultValue;
803 }
804
805 @Override
806 public Double getDoubleAndRemove(K name) {
807 V v = getAndRemove(name);
808 return v != null ? valueConverter.convertToDouble(v) : null;
809 }
810
811 @Override
812 public double getDoubleAndRemove(K name, double defaultValue) {
813 Double v = getDoubleAndRemove(name);
814 return v != null ? v : defaultValue;
815 }
816
817 @Override
818 public Long getTimeMillisAndRemove(K name) {
819 V v = getAndRemove(name);
820 return v != null ? valueConverter.convertToTimeMillis(v) : null;
821 }
822
823 @Override
824 public long getTimeMillisAndRemove(K name, long defaultValue) {
825 Long v = getTimeMillisAndRemove(name);
826 return v != null ? v : defaultValue;
827 }
828
829 @SuppressWarnings("unchecked")
830 @Override
831 public boolean equals(Object o) {
832 if (!(o instanceof Headers)) {
833 return false;
834 }
835
836 return equals((Headers<K, V, ?>) o, JAVA_HASHER);
837 }
838
839 @SuppressWarnings("unchecked")
840 @Override
841 public int hashCode() {
842 return hashCode(JAVA_HASHER);
843 }
844
845
846
847
848
849
850
851
852 public final boolean equals(Headers<K, V, ?> h2, HashingStrategy<V> valueHashingStrategy) {
853 if (h2.size() != size()) {
854 return false;
855 }
856
857 if (this == h2) {
858 return true;
859 }
860
861 for (K name : names()) {
862 List<V> otherValues = h2.getAll(name);
863 List<V> values = getAll(name);
864 if (otherValues.size() != values.size()) {
865 return false;
866 }
867 for (int i = 0; i < otherValues.size(); i++) {
868 if (!valueHashingStrategy.equals(otherValues.get(i), values.get(i))) {
869 return false;
870 }
871 }
872 }
873 return true;
874 }
875
876
877
878
879
880
881 public final int hashCode(HashingStrategy<V> valueHashingStrategy) {
882 int result = HASH_CODE_SEED;
883 for (K name : names()) {
884 result = 31 * result + hashingStrategy.hashCode(name);
885 List<V> values = getAll(name);
886 for (int i = 0; i < values.size(); ++i) {
887 result = 31 * result + valueHashingStrategy.hashCode(values.get(i));
888 }
889 }
890 return result;
891 }
892
893 @Override
894 public String toString() {
895 StringBuilder builder = new StringBuilder(getClass().getSimpleName()).append('[');
896 String separator = "";
897 for (K name : names()) {
898 List<V> values = getAll(name);
899 for (int i = 0; i < values.size(); ++i) {
900 builder.append(separator);
901 builder.append(name).append(": ").append(values.get(i));
902 }
903 separator = ", ";
904 }
905 return builder.append(']').toString();
906 }
907
908 protected HeaderEntry<K, V> newHeaderEntry(int h, K name, V value, HeaderEntry<K, V> next) {
909 return new HeaderEntry<K, V>(h, name, value, next, head);
910 }
911
912 protected ValueConverter<V> valueConverter() {
913 return valueConverter;
914 }
915
916 private int index(int hash) {
917 return hash & hashMask;
918 }
919
920 private void add0(int h, int i, K name, V value) {
921
922 entries[i] = newHeaderEntry(h, name, value, entries[i]);
923 ++size;
924 }
925
926
927
928
929 private V remove0(int h, int i, K name) {
930 HeaderEntry<K, V> e = entries[i];
931 if (e == null) {
932 return null;
933 }
934
935 V value = null;
936 HeaderEntry<K, V> next = e.next;
937 while (next != null) {
938 if (next.hash == h && hashingStrategy.equals(name, next.key)) {
939 value = next.value;
940 e.next = next.next;
941 next.remove();
942 --size;
943 } else {
944 e = next;
945 }
946
947 next = e.next;
948 }
949
950 e = entries[i];
951 if (e.hash == h && hashingStrategy.equals(name, e.key)) {
952 if (value == null) {
953 value = e.value;
954 }
955 entries[i] = e.next;
956 e.remove();
957 --size;
958 }
959
960 return value;
961 }
962
963 @SuppressWarnings("unchecked")
964 private T thisT() {
965 return (T) this;
966 }
967
968
969
970
971
972
973
974
975
976
977 public static final class HeaderDateFormat {
978 private static final FastThreadLocal<HeaderDateFormat> dateFormatThreadLocal =
979 new FastThreadLocal<HeaderDateFormat>() {
980 @Override
981 protected HeaderDateFormat initialValue() {
982 return new HeaderDateFormat();
983 }
984 };
985
986 static HeaderDateFormat get() {
987 return dateFormatThreadLocal.get();
988 }
989
990
991
992
993
994
995
996
997 private final DateFormat dateFormat1 = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
998
999
1000
1001
1002
1003
1004
1005
1006 private final DateFormat dateFormat2 = new SimpleDateFormat("E, dd-MMM-yy HH:mm:ss z", Locale.ENGLISH);
1007
1008
1009
1010
1011
1012
1013
1014
1015 private final DateFormat dateFormat3 = new SimpleDateFormat("E MMM d HH:mm:ss yyyy", Locale.ENGLISH);
1016
1017 private HeaderDateFormat() {
1018 TimeZone tz = TimeZone.getTimeZone("GMT");
1019 dateFormat1.setTimeZone(tz);
1020 dateFormat2.setTimeZone(tz);
1021 dateFormat3.setTimeZone(tz);
1022 }
1023
1024 long parse(String text) throws ParseException {
1025 Date date = dateFormat1.parse(text);
1026 if (date == null) {
1027 date = dateFormat2.parse(text);
1028 }
1029 if (date == null) {
1030 date = dateFormat3.parse(text);
1031 }
1032 if (date == null) {
1033 throw new ParseException(text, 0);
1034 }
1035 return date.getTime();
1036 }
1037 }
1038
1039 private final class HeaderIterator implements Iterator<Map.Entry<K, V>> {
1040 private HeaderEntry<K, V> current = head;
1041
1042 @Override
1043 public boolean hasNext() {
1044 return current.after != head;
1045 }
1046
1047 @Override
1048 public Entry<K, V> next() {
1049 current = current.after;
1050
1051 if (current == head) {
1052 throw new NoSuchElementException();
1053 }
1054
1055 return current;
1056 }
1057
1058 @Override
1059 public void remove() {
1060 throw new UnsupportedOperationException("read-only iterator");
1061 }
1062 }
1063
1064 protected static class HeaderEntry<K, V> implements Map.Entry<K, V> {
1065 protected final int hash;
1066 protected final K key;
1067 protected V value;
1068
1069
1070
1071 protected HeaderEntry<K, V> next;
1072
1073
1074
1075 protected HeaderEntry<K, V> before, after;
1076
1077 protected HeaderEntry(int hash, K key) {
1078 this.hash = hash;
1079 this.key = key;
1080 }
1081
1082 HeaderEntry(int hash, K key, V value, HeaderEntry<K, V> next, HeaderEntry<K, V> head) {
1083 this.hash = hash;
1084 this.key = key;
1085 this.value = value;
1086 this.next = next;
1087
1088 after = head;
1089 before = head.before;
1090 pointNeighborsToThis();
1091 }
1092
1093 HeaderEntry() {
1094 hash = -1;
1095 key = null;
1096 before = after = this;
1097 }
1098
1099 protected final void pointNeighborsToThis() {
1100 before.after = this;
1101 after.before = this;
1102 }
1103
1104 public final HeaderEntry<K, V> before() {
1105 return before;
1106 }
1107
1108 public final HeaderEntry<K, V> after() {
1109 return after;
1110 }
1111
1112 protected void remove() {
1113 before.after = after;
1114 after.before = before;
1115 }
1116
1117 @Override
1118 public final K getKey() {
1119 return key;
1120 }
1121
1122 @Override
1123 public final V getValue() {
1124 return value;
1125 }
1126
1127 @Override
1128 public final V setValue(V value) {
1129 checkNotNull(value, "value");
1130 V oldValue = this.value;
1131 this.value = value;
1132 return oldValue;
1133 }
1134
1135 @Override
1136 public final String toString() {
1137 return key.toString() + '=' + value.toString();
1138 }
1139 }
1140 }