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
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.Iterator;
22 import java.util.LinkedHashSet;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.NoSuchElementException;
28 import java.util.Set;
29
30 import static io.netty.util.HashingStrategy.JAVA_HASHER;
31 import static io.netty.util.internal.MathUtil.findNextPositivePowerOfTwo;
32 import static io.netty.util.internal.ObjectUtil.checkNotNull;
33 import static java.lang.Math.max;
34 import static java.lang.Math.min;
35
36
37
38
39
40
41
42
43 public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers<K, V, T> {
44
45
46
47 static final int HASH_CODE_SEED = 0xc2b2ae35;
48
49 private final HeaderEntry<K, V>[] entries;
50 protected final HeaderEntry<K, V> head;
51
52 private final byte hashMask;
53 private final ValueConverter<V> valueConverter;
54 private final NameValidator<K> nameValidator;
55 private final ValueValidator<V> valueValidator;
56 private final HashingStrategy<K> hashingStrategy;
57 int size;
58
59 public interface NameValidator<K> {
60
61
62
63
64
65 void validateName(K name);
66
67 @SuppressWarnings("rawtypes")
68 NameValidator NOT_NULL = new NameValidator() {
69 @Override
70 public void validateName(Object name) {
71 checkNotNull(name, "name");
72 }
73 };
74 }
75
76 public interface ValueValidator<V> {
77
78
79
80
81
82
83 void validate(V value);
84
85 ValueValidator<?> NO_VALIDATION = new ValueValidator<Object>() {
86 @Override
87 public void validate(Object value) {
88 }
89 };
90 }
91
92 @SuppressWarnings("unchecked")
93 public DefaultHeaders(ValueConverter<V> valueConverter) {
94 this(JAVA_HASHER, valueConverter);
95 }
96
97 @SuppressWarnings("unchecked")
98 public DefaultHeaders(ValueConverter<V> valueConverter, NameValidator<K> nameValidator) {
99 this(JAVA_HASHER, valueConverter, nameValidator);
100 }
101
102 @SuppressWarnings("unchecked")
103 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy, ValueConverter<V> valueConverter) {
104 this(nameHashingStrategy, valueConverter, NameValidator.NOT_NULL);
105 }
106
107 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy,
108 ValueConverter<V> valueConverter, NameValidator<K> nameValidator) {
109 this(nameHashingStrategy, valueConverter, nameValidator, 16);
110 }
111
112
113
114
115
116
117
118
119
120 @SuppressWarnings("unchecked")
121 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy,
122 ValueConverter<V> valueConverter, NameValidator<K> nameValidator, int arraySizeHint) {
123 this(nameHashingStrategy, valueConverter, nameValidator, arraySizeHint,
124 (ValueValidator<V>) ValueValidator.NO_VALIDATION);
125 }
126
127
128
129
130
131
132
133
134
135
136 @SuppressWarnings("unchecked")
137 public DefaultHeaders(HashingStrategy<K> nameHashingStrategy, ValueConverter<V> valueConverter,
138 NameValidator<K> nameValidator, int arraySizeHint, ValueValidator<V> valueValidator) {
139 this.valueConverter = checkNotNull(valueConverter, "valueConverter");
140 this.nameValidator = checkNotNull(nameValidator, "nameValidator");
141 hashingStrategy = checkNotNull(nameHashingStrategy, "nameHashingStrategy");
142 this.valueValidator = checkNotNull(valueValidator, "valueValidator");
143
144
145 entries = new HeaderEntry[findNextPositivePowerOfTwo(max(2, min(arraySizeHint, 128)))];
146 hashMask = (byte) (entries.length - 1);
147 head = new HeaderEntry<K, V>();
148 }
149
150 @Override
151 public V get(K name) {
152 checkNotNull(name, "name");
153
154 int h = hashingStrategy.hashCode(name);
155 int i = index(h);
156 HeaderEntry<K, V> e = entries[i];
157 V value = null;
158
159 while (e != null) {
160 if (e.hash == h && hashingStrategy.equals(name, e.key)) {
161 value = e.value;
162 }
163
164 e = e.next;
165 }
166 return value;
167 }
168
169 @Override
170 public V get(K name, V defaultValue) {
171 V value = get(name);
172 if (value == null) {
173 return defaultValue;
174 }
175 return value;
176 }
177
178 @Override
179 public V getAndRemove(K name) {
180 int h = hashingStrategy.hashCode(name);
181 return remove0(h, index(h), checkNotNull(name, "name"));
182 }
183
184 @Override
185 public V getAndRemove(K name, V defaultValue) {
186 V value = getAndRemove(name);
187 if (value == null) {
188 return defaultValue;
189 }
190 return value;
191 }
192
193 @Override
194 public List<V> getAll(K name) {
195 checkNotNull(name, "name");
196
197 LinkedList<V> values = new LinkedList<V>();
198
199 int h = hashingStrategy.hashCode(name);
200 int i = index(h);
201 HeaderEntry<K, V> e = entries[i];
202 while (e != null) {
203 if (e.hash == h && hashingStrategy.equals(name, e.key)) {
204 values.addFirst(e.getValue());
205 }
206 e = e.next;
207 }
208 return values;
209 }
210
211
212
213
214
215
216 public Iterator<V> valueIterator(K name) {
217 return new ValueIterator(name);
218 }
219
220 @Override
221 public List<V> getAllAndRemove(K name) {
222 List<V> all = getAll(name);
223 remove(name);
224 return all;
225 }
226
227 @Override
228 public boolean contains(K name) {
229 return get(name) != null;
230 }
231
232 @Override
233 public boolean containsObject(K name, Object value) {
234 return contains(name, fromObject(name, value));
235 }
236
237 @Override
238 public boolean containsBoolean(K name, boolean value) {
239 return contains(name, fromBoolean(name, value));
240 }
241
242 @Override
243 public boolean containsByte(K name, byte value) {
244 return contains(name, fromByte(name, value));
245 }
246
247 @Override
248 public boolean containsChar(K name, char value) {
249 return contains(name, fromChar(name, value));
250 }
251
252 @Override
253 public boolean containsShort(K name, short value) {
254 return contains(name, fromShort(name, value));
255 }
256
257 @Override
258 public boolean containsInt(K name, int value) {
259 return contains(name, fromInt(name, value));
260 }
261
262 @Override
263 public boolean containsLong(K name, long value) {
264 return contains(name, fromLong(name, value));
265 }
266
267 @Override
268 public boolean containsFloat(K name, float value) {
269 return contains(name, fromFloat(name, value));
270 }
271
272 @Override
273 public boolean containsDouble(K name, double value) {
274 return contains(name, fromDouble(name, value));
275 }
276
277 @Override
278 public boolean containsTimeMillis(K name, long value) {
279 return contains(name, fromTimeMillis(name, value));
280 }
281
282 @SuppressWarnings("unchecked")
283 @Override
284 public boolean contains(K name, V value) {
285 return contains(name, value, JAVA_HASHER);
286 }
287
288 public final boolean contains(K name, V value, HashingStrategy<? super V> valueHashingStrategy) {
289 checkNotNull(name, "name");
290
291 int h = hashingStrategy.hashCode(name);
292 int i = index(h);
293 HeaderEntry<K, V> e = entries[i];
294 while (e != null) {
295 if (e.hash == h && hashingStrategy.equals(name, e.key) && valueHashingStrategy.equals(value, e.value)) {
296 return true;
297 }
298 e = e.next;
299 }
300 return false;
301 }
302
303 @Override
304 public int size() {
305 return size;
306 }
307
308 @Override
309 public boolean isEmpty() {
310 return head == head.after;
311 }
312
313 @Override
314 public Set<K> names() {
315 if (isEmpty()) {
316 return Collections.emptySet();
317 }
318 Set<K> names = new LinkedHashSet<K>(size());
319 HeaderEntry<K, V> e = head.after;
320 while (e != head) {
321 names.add(e.getKey());
322 e = e.after;
323 }
324 return names;
325 }
326
327 @Override
328 public T add(K name, V value) {
329 validateName(nameValidator, true, name);
330 validateValue(valueValidator, name, value);
331 checkNotNull(value, "value");
332 int h = hashingStrategy.hashCode(name);
333 int i = index(h);
334 add0(h, i, name, value);
335 return thisT();
336 }
337
338 @Override
339 public T add(K name, Iterable<? extends V> values) {
340 validateName(nameValidator, true, name);
341 int h = hashingStrategy.hashCode(name);
342 int i = index(h);
343 for (V v: values) {
344 validateValue(valueValidator, name, v);
345 add0(h, i, name, v);
346 }
347 return thisT();
348 }
349
350 @Override
351 public T add(K name, V... values) {
352 validateName(nameValidator, true, name);
353 int h = hashingStrategy.hashCode(name);
354 int i = index(h);
355 for (V v: values) {
356 validateValue(valueValidator, name, v);
357 add0(h, i, name, v);
358 }
359 return thisT();
360 }
361
362 @Override
363 public T addObject(K name, Object value) {
364 return add(name, fromObject(name, value));
365 }
366
367 @Override
368 public T addObject(K name, Iterable<?> values) {
369 for (Object value : values) {
370 addObject(name, value);
371 }
372 return thisT();
373 }
374
375 @Override
376 public T addObject(K name, Object... values) {
377 for (Object value: values) {
378 addObject(name, value);
379 }
380 return thisT();
381 }
382
383 @Override
384 public T addInt(K name, int value) {
385 return add(name, fromInt(name, value));
386 }
387
388 @Override
389 public T addLong(K name, long value) {
390 return add(name, fromLong(name, value));
391 }
392
393 @Override
394 public T addDouble(K name, double value) {
395 return add(name, fromDouble(name, value));
396 }
397
398 @Override
399 public T addTimeMillis(K name, long value) {
400 return add(name, fromTimeMillis(name, value));
401 }
402
403 @Override
404 public T addChar(K name, char value) {
405 return add(name, fromChar(name, value));
406 }
407
408 @Override
409 public T addBoolean(K name, boolean value) {
410 return add(name, fromBoolean(name, value));
411 }
412
413 @Override
414 public T addFloat(K name, float value) {
415 return add(name, fromFloat(name, value));
416 }
417
418 @Override
419 public T addByte(K name, byte value) {
420 return add(name, fromByte(name, value));
421 }
422
423 @Override
424 public T addShort(K name, short value) {
425 return add(name, fromShort(name, value));
426 }
427
428 @Override
429 public T add(Headers<? extends K, ? extends V, ?> headers) {
430 if (headers == this) {
431 throw new IllegalArgumentException("can't add to itself.");
432 }
433 addImpl(headers);
434 return thisT();
435 }
436
437 protected void addImpl(Headers<? extends K, ? extends V, ?> headers) {
438 if (headers instanceof DefaultHeaders) {
439 @SuppressWarnings("unchecked")
440 final DefaultHeaders<? extends K, ? extends V, T> defaultHeaders =
441 (DefaultHeaders<? extends K, ? extends V, T>) headers;
442 HeaderEntry<? extends K, ? extends V> e = defaultHeaders.head.after;
443 if (defaultHeaders.hashingStrategy == hashingStrategy &&
444 defaultHeaders.nameValidator == nameValidator) {
445
446 while (e != defaultHeaders.head) {
447 add0(e.hash, index(e.hash), e.key, e.value);
448 e = e.after;
449 }
450 } else {
451
452 while (e != defaultHeaders.head) {
453 add(e.key, e.value);
454 e = e.after;
455 }
456 }
457 } else {
458
459 for (Entry<? extends K, ? extends V> header : headers) {
460 add(header.getKey(), header.getValue());
461 }
462 }
463 }
464
465 @Override
466 public T set(K name, V value) {
467 validateName(nameValidator, false, name);
468 validateValue(valueValidator, name, value);
469 checkNotNull(value, "value");
470 int h = hashingStrategy.hashCode(name);
471 int i = index(h);
472 remove0(h, i, name);
473 add0(h, i, name, value);
474 return thisT();
475 }
476
477 @Override
478 public T set(K name, Iterable<? extends V> values) {
479 validateName(nameValidator, false, name);
480 checkNotNull(values, "values");
481
482 int h = hashingStrategy.hashCode(name);
483 int i = index(h);
484
485 remove0(h, i, name);
486 for (V v: values) {
487 if (v == null) {
488 break;
489 }
490 validateValue(valueValidator, name, v);
491 add0(h, i, name, v);
492 }
493
494 return thisT();
495 }
496
497 @Override
498 public T set(K name, V... values) {
499 validateName(nameValidator, false, name);
500 checkNotNull(values, "values");
501
502 int h = hashingStrategy.hashCode(name);
503 int i = index(h);
504
505 remove0(h, i, name);
506 for (V v: values) {
507 if (v == null) {
508 break;
509 }
510 validateValue(valueValidator, name, v);
511 add0(h, i, name, v);
512 }
513
514 return thisT();
515 }
516
517 @Override
518 public T setObject(K name, Object value) {
519 V convertedValue = checkNotNull(fromObject(name, value), "convertedValue");
520 return set(name, convertedValue);
521 }
522
523 @Override
524 public T setObject(K name, Iterable<?> values) {
525 validateName(nameValidator, false, name);
526
527 int h = hashingStrategy.hashCode(name);
528 int i = index(h);
529
530 remove0(h, i, name);
531 for (Object v: values) {
532 if (v == null) {
533 break;
534 }
535 V converted = fromObject(name, v);
536 validateValue(valueValidator, name, converted);
537 add0(h, i, name, converted);
538 }
539
540 return thisT();
541 }
542
543 @Override
544 public T setObject(K name, Object... values) {
545 validateName(nameValidator, false, name);
546
547 int h = hashingStrategy.hashCode(name);
548 int i = index(h);
549
550 remove0(h, i, name);
551 for (Object v: values) {
552 if (v == null) {
553 break;
554 }
555 V converted = fromObject(name, v);
556 validateValue(valueValidator, name, converted);
557 add0(h, i, name, converted);
558 }
559
560 return thisT();
561 }
562
563 @Override
564 public T setInt(K name, int value) {
565 return set(name, fromInt(name, value));
566 }
567
568 @Override
569 public T setLong(K name, long value) {
570 return set(name, fromLong(name, value));
571 }
572
573 @Override
574 public T setDouble(K name, double value) {
575 return set(name, fromDouble(name, value));
576 }
577
578 @Override
579 public T setTimeMillis(K name, long value) {
580 return set(name, fromTimeMillis(name, value));
581 }
582
583 @Override
584 public T setFloat(K name, float value) {
585 return set(name, fromFloat(name, value));
586 }
587
588 @Override
589 public T setChar(K name, char value) {
590 return set(name, fromChar(name, value));
591 }
592
593 @Override
594 public T setBoolean(K name, boolean value) {
595 return set(name, fromBoolean(name, value));
596 }
597
598 @Override
599 public T setByte(K name, byte value) {
600 return set(name, fromByte(name, value));
601 }
602
603 @Override
604 public T setShort(K name, short value) {
605 return set(name, fromShort(name, value));
606 }
607
608 @Override
609 public T set(Headers<? extends K, ? extends V, ?> headers) {
610 if (headers != this) {
611 clear();
612 addImpl(headers);
613 }
614 return thisT();
615 }
616
617 @Override
618 public T setAll(Headers<? extends K, ? extends V, ?> headers) {
619 if (headers != this) {
620 for (K key : headers.names()) {
621 remove(key);
622 }
623 addImpl(headers);
624 }
625 return thisT();
626 }
627
628 @Override
629 public boolean remove(K name) {
630 return getAndRemove(name) != null;
631 }
632
633 @Override
634 public T clear() {
635 Arrays.fill(entries, null);
636 head.before = head.after = head;
637 size = 0;
638 return thisT();
639 }
640
641 @Override
642 public Iterator<Entry<K, V>> iterator() {
643 return new HeaderIterator();
644 }
645
646 @Override
647 public Boolean getBoolean(K name) {
648 V v = get(name);
649 try {
650 return v != null ? toBoolean(name, v) : null;
651 } catch (RuntimeException ignore) {
652 return null;
653 }
654 }
655
656 @Override
657 public boolean getBoolean(K name, boolean defaultValue) {
658 Boolean v = getBoolean(name);
659 return v != null ? v : defaultValue;
660 }
661
662 @Override
663 public Byte getByte(K name) {
664 V v = get(name);
665 try {
666 return v != null ? toByte(name, v) : null;
667 } catch (RuntimeException ignore) {
668 return null;
669 }
670 }
671
672 @Override
673 public byte getByte(K name, byte defaultValue) {
674 Byte v = getByte(name);
675 return v != null ? v : defaultValue;
676 }
677
678 @Override
679 public Character getChar(K name) {
680 V v = get(name);
681 try {
682 return v != null ? toChar(name, v) : null;
683 } catch (RuntimeException ignore) {
684 return null;
685 }
686 }
687
688 @Override
689 public char getChar(K name, char defaultValue) {
690 Character v = getChar(name);
691 return v != null ? v : defaultValue;
692 }
693
694 @Override
695 public Short getShort(K name) {
696 V v = get(name);
697 try {
698 return v != null ? toShort(name, v) : null;
699 } catch (RuntimeException ignore) {
700 return null;
701 }
702 }
703
704 @Override
705 public short getShort(K name, short defaultValue) {
706 Short v = getShort(name);
707 return v != null ? v : defaultValue;
708 }
709
710 @Override
711 public Integer getInt(K name) {
712 V v = get(name);
713 try {
714 return v != null ? toInt(name, v) : null;
715 } catch (RuntimeException ignore) {
716 return null;
717 }
718 }
719
720 @Override
721 public int getInt(K name, int defaultValue) {
722 Integer v = getInt(name);
723 return v != null ? v : defaultValue;
724 }
725
726 @Override
727 public Long getLong(K name) {
728 V v = get(name);
729 try {
730 return v != null ? toLong(name, v) : null;
731 } catch (RuntimeException ignore) {
732 return null;
733 }
734 }
735
736 @Override
737 public long getLong(K name, long defaultValue) {
738 Long v = getLong(name);
739 return v != null ? v : defaultValue;
740 }
741
742 @Override
743 public Float getFloat(K name) {
744 V v = get(name);
745 try {
746 return v != null ? toFloat(name, v) : null;
747 } catch (RuntimeException ignore) {
748 return null;
749 }
750 }
751
752 @Override
753 public float getFloat(K name, float defaultValue) {
754 Float v = getFloat(name);
755 return v != null ? v : defaultValue;
756 }
757
758 @Override
759 public Double getDouble(K name) {
760 V v = get(name);
761 try {
762 return v != null ? toDouble(name, v) : null;
763 } catch (RuntimeException ignore) {
764 return null;
765 }
766 }
767
768 @Override
769 public double getDouble(K name, double defaultValue) {
770 Double v = getDouble(name);
771 return v != null ? v : defaultValue;
772 }
773
774 @Override
775 public Long getTimeMillis(K name) {
776 V v = get(name);
777 try {
778 return v != null ? toTimeMillis(name, v) : null;
779 } catch (RuntimeException ignore) {
780 return null;
781 }
782 }
783
784 @Override
785 public long getTimeMillis(K name, long defaultValue) {
786 Long v = getTimeMillis(name);
787 return v != null ? v : defaultValue;
788 }
789
790 @Override
791 public Boolean getBooleanAndRemove(K name) {
792 V v = getAndRemove(name);
793 try {
794 return v != null ? toBoolean(name, v) : null;
795 } catch (RuntimeException ignore) {
796 return null;
797 }
798 }
799
800 @Override
801 public boolean getBooleanAndRemove(K name, boolean defaultValue) {
802 Boolean v = getBooleanAndRemove(name);
803 return v != null ? v : defaultValue;
804 }
805
806 @Override
807 public Byte getByteAndRemove(K name) {
808 V v = getAndRemove(name);
809 try {
810 return v != null ? toByte(name, v) : null;
811 } catch (RuntimeException ignore) {
812 return null;
813 }
814 }
815
816 @Override
817 public byte getByteAndRemove(K name, byte defaultValue) {
818 Byte v = getByteAndRemove(name);
819 return v != null ? v : defaultValue;
820 }
821
822 @Override
823 public Character getCharAndRemove(K name) {
824 V v = getAndRemove(name);
825 try {
826 return v != null ? toChar(name, v) : null;
827 } catch (RuntimeException ignore) {
828 return null;
829 }
830 }
831
832 @Override
833 public char getCharAndRemove(K name, char defaultValue) {
834 Character v = getCharAndRemove(name);
835 return v != null ? v : defaultValue;
836 }
837
838 @Override
839 public Short getShortAndRemove(K name) {
840 V v = getAndRemove(name);
841 try {
842 return v != null ? toShort(name, v) : null;
843 } catch (RuntimeException ignore) {
844 return null;
845 }
846 }
847
848 @Override
849 public short getShortAndRemove(K name, short defaultValue) {
850 Short v = getShortAndRemove(name);
851 return v != null ? v : defaultValue;
852 }
853
854 @Override
855 public Integer getIntAndRemove(K name) {
856 V v = getAndRemove(name);
857 try {
858 return v != null ? toInt(name, v) : null;
859 } catch (RuntimeException ignore) {
860 return null;
861 }
862 }
863
864 @Override
865 public int getIntAndRemove(K name, int defaultValue) {
866 Integer v = getIntAndRemove(name);
867 return v != null ? v : defaultValue;
868 }
869
870 @Override
871 public Long getLongAndRemove(K name) {
872 V v = getAndRemove(name);
873 try {
874 return v != null ? toLong(name, v) : null;
875 } catch (RuntimeException ignore) {
876 return null;
877 }
878 }
879
880 @Override
881 public long getLongAndRemove(K name, long defaultValue) {
882 Long v = getLongAndRemove(name);
883 return v != null ? v : defaultValue;
884 }
885
886 @Override
887 public Float getFloatAndRemove(K name) {
888 V v = getAndRemove(name);
889 try {
890 return v != null ? toFloat(name, v) : null;
891 } catch (RuntimeException ignore) {
892 return null;
893 }
894 }
895
896 @Override
897 public float getFloatAndRemove(K name, float defaultValue) {
898 Float v = getFloatAndRemove(name);
899 return v != null ? v : defaultValue;
900 }
901
902 @Override
903 public Double getDoubleAndRemove(K name) {
904 V v = getAndRemove(name);
905 try {
906 return v != null ? toDouble(name, v) : null;
907 } catch (RuntimeException ignore) {
908 return null;
909 }
910 }
911
912 @Override
913 public double getDoubleAndRemove(K name, double defaultValue) {
914 Double v = getDoubleAndRemove(name);
915 return v != null ? v : defaultValue;
916 }
917
918 @Override
919 public Long getTimeMillisAndRemove(K name) {
920 V v = getAndRemove(name);
921 try {
922 return v != null ? toTimeMillis(name, v) : null;
923 } catch (RuntimeException ignore) {
924 return null;
925 }
926 }
927
928 @Override
929 public long getTimeMillisAndRemove(K name, long defaultValue) {
930 Long v = getTimeMillisAndRemove(name);
931 return v != null ? v : defaultValue;
932 }
933
934 @SuppressWarnings("unchecked")
935 @Override
936 public boolean equals(Object o) {
937 if (!(o instanceof Headers)) {
938 return false;
939 }
940
941 return equals((Headers<K, V, ?>) o, JAVA_HASHER);
942 }
943
944 @SuppressWarnings("unchecked")
945 @Override
946 public int hashCode() {
947 return hashCode(JAVA_HASHER);
948 }
949
950
951
952
953
954
955
956
957 public final boolean equals(Headers<K, V, ?> h2, HashingStrategy<V> valueHashingStrategy) {
958 if (h2.size() != size()) {
959 return false;
960 }
961
962 if (this == h2) {
963 return true;
964 }
965
966 for (K name : names()) {
967 List<V> otherValues = h2.getAll(name);
968 List<V> values = getAll(name);
969 if (otherValues.size() != values.size()) {
970 return false;
971 }
972 for (int i = 0; i < otherValues.size(); i++) {
973 if (!valueHashingStrategy.equals(otherValues.get(i), values.get(i))) {
974 return false;
975 }
976 }
977 }
978 return true;
979 }
980
981
982
983
984
985
986 public final int hashCode(HashingStrategy<V> valueHashingStrategy) {
987 int result = HASH_CODE_SEED;
988 for (K name : names()) {
989 result = 31 * result + hashingStrategy.hashCode(name);
990 List<V> values = getAll(name);
991 for (int i = 0; i < values.size(); ++i) {
992 result = 31 * result + valueHashingStrategy.hashCode(values.get(i));
993 }
994 }
995 return result;
996 }
997
998 @Override
999 public String toString() {
1000 return HeadersUtils.toString(getClass(), iterator(), size());
1001 }
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 protected void validateName(NameValidator<K> validator, boolean forAdd, K name) {
1012 validator.validateName(name);
1013 }
1014
1015 protected void validateValue(ValueValidator<V> validator, K name, V value) {
1016 try {
1017 validator.validate(value);
1018 } catch (IllegalArgumentException e) {
1019 throw new IllegalArgumentException("Validation failed for header '" + name + "'", e);
1020 }
1021 }
1022
1023 protected HeaderEntry<K, V> newHeaderEntry(int h, K name, V value, HeaderEntry<K, V> next) {
1024 return new HeaderEntry<K, V>(h, name, value, next, head);
1025 }
1026
1027 protected ValueConverter<V> valueConverter() {
1028 return valueConverter;
1029 }
1030
1031 protected NameValidator<K> nameValidator() {
1032 return nameValidator;
1033 }
1034
1035 protected ValueValidator<V> valueValidator() {
1036 return valueValidator;
1037 }
1038
1039 private int index(int hash) {
1040 return hash & hashMask;
1041 }
1042
1043 private void add0(int h, int i, K name, V value) {
1044
1045 entries[i] = newHeaderEntry(h, name, value, entries[i]);
1046 ++size;
1047 }
1048
1049
1050
1051
1052 private V remove0(int h, int i, K name) {
1053 HeaderEntry<K, V> e = entries[i];
1054 if (e == null) {
1055 return null;
1056 }
1057
1058 V value = null;
1059 HeaderEntry<K, V> next = e.next;
1060 while (next != null) {
1061 if (next.hash == h && hashingStrategy.equals(name, next.key)) {
1062 value = next.value;
1063 e.next = next.next;
1064 next.remove();
1065 --size;
1066 } else {
1067 e = next;
1068 }
1069
1070 next = e.next;
1071 }
1072
1073 e = entries[i];
1074 if (e.hash == h && hashingStrategy.equals(name, e.key)) {
1075 if (value == null) {
1076 value = e.value;
1077 }
1078 entries[i] = e.next;
1079 e.remove();
1080 --size;
1081 }
1082
1083 return value;
1084 }
1085
1086 HeaderEntry<K, V> remove0(HeaderEntry<K, V> entry, HeaderEntry<K, V> previous) {
1087 int i = index(entry.hash);
1088 HeaderEntry<K, V> firstEntry = entries[i];
1089 if (firstEntry == entry) {
1090 entries[i] = entry.next;
1091 previous = entries[i];
1092 } else if (previous == null) {
1093
1094 previous = firstEntry;
1095 HeaderEntry<K, V> next = firstEntry.next;
1096 while (next != null && next != entry) {
1097 previous = next;
1098 next = next.next;
1099 }
1100 assert next != null: "Entry not found in its hash bucket: " + entry;
1101 previous.next = entry.next;
1102 } else {
1103 previous.next = entry.next;
1104 }
1105 entry.remove();
1106 --size;
1107 return previous;
1108 }
1109
1110 @SuppressWarnings("unchecked")
1111 private T thisT() {
1112 return (T) this;
1113 }
1114
1115 private V fromObject(K name, Object value) {
1116 try {
1117 return valueConverter.convertObject(checkNotNull(value, "value"));
1118 } catch (IllegalArgumentException e) {
1119 throw new IllegalArgumentException("Failed to convert object value for header '" + name + '\'', e);
1120 }
1121 }
1122
1123 private V fromBoolean(K name, boolean value) {
1124 try {
1125 return valueConverter.convertBoolean(value);
1126 } catch (IllegalArgumentException e) {
1127 throw new IllegalArgumentException("Failed to convert boolean value for header '" + name + '\'', e);
1128 }
1129 }
1130
1131 private V fromByte(K name, byte value) {
1132 try {
1133 return valueConverter.convertByte(value);
1134 } catch (IllegalArgumentException e) {
1135 throw new IllegalArgumentException("Failed to convert byte value for header '" + name + '\'', e);
1136 }
1137 }
1138
1139 private V fromChar(K name, char value) {
1140 try {
1141 return valueConverter.convertChar(value);
1142 } catch (IllegalArgumentException e) {
1143 throw new IllegalArgumentException("Failed to convert char value for header '" + name + '\'', e);
1144 }
1145 }
1146
1147 private V fromShort(K name, short value) {
1148 try {
1149 return valueConverter.convertShort(value);
1150 } catch (IllegalArgumentException e) {
1151 throw new IllegalArgumentException("Failed to convert short value for header '" + name + '\'', e);
1152 }
1153 }
1154
1155 private V fromInt(K name, int value) {
1156 try {
1157 return valueConverter.convertInt(value);
1158 } catch (IllegalArgumentException e) {
1159 throw new IllegalArgumentException("Failed to convert int value for header '" + name + '\'', e);
1160 }
1161 }
1162
1163 private V fromLong(K name, long value) {
1164 try {
1165 return valueConverter.convertLong(value);
1166 } catch (IllegalArgumentException e) {
1167 throw new IllegalArgumentException("Failed to convert long value for header '" + name + '\'', e);
1168 }
1169 }
1170
1171 private V fromFloat(K name, float value) {
1172 try {
1173 return valueConverter.convertFloat(value);
1174 } catch (IllegalArgumentException e) {
1175 throw new IllegalArgumentException("Failed to convert float value for header '" + name + '\'', e);
1176 }
1177 }
1178
1179 private V fromDouble(K name, double value) {
1180 try {
1181 return valueConverter.convertDouble(value);
1182 } catch (IllegalArgumentException e) {
1183 throw new IllegalArgumentException("Failed to convert double value for header '" + name + '\'', e);
1184 }
1185 }
1186
1187 private V fromTimeMillis(K name, long value) {
1188 try {
1189 return valueConverter.convertTimeMillis(value);
1190 } catch (IllegalArgumentException e) {
1191 throw new IllegalArgumentException("Failed to convert millsecond value for header '" + name + '\'', e);
1192 }
1193 }
1194
1195 private boolean toBoolean(K name, V value) {
1196 try {
1197 return valueConverter.convertToBoolean(value);
1198 } catch (IllegalArgumentException e) {
1199 throw new IllegalArgumentException("Failed to convert header value to boolean for header '" + name + '\'');
1200 }
1201 }
1202
1203 private byte toByte(K name, V value) {
1204 try {
1205 return valueConverter.convertToByte(value);
1206 } catch (IllegalArgumentException e) {
1207 throw new IllegalArgumentException("Failed to convert header value to byte for header '" + name + '\'');
1208 }
1209 }
1210
1211 private char toChar(K name, V value) {
1212 try {
1213 return valueConverter.convertToChar(value);
1214 } catch (IllegalArgumentException e) {
1215 throw new IllegalArgumentException("Failed to convert header value to char for header '" + name + '\'');
1216 }
1217 }
1218
1219 private short toShort(K name, V value) {
1220 try {
1221 return valueConverter.convertToShort(value);
1222 } catch (IllegalArgumentException e) {
1223 throw new IllegalArgumentException("Failed to convert header value to short for header '" + name + '\'');
1224 }
1225 }
1226
1227 private int toInt(K name, V value) {
1228 try {
1229 return valueConverter.convertToInt(value);
1230 } catch (IllegalArgumentException e) {
1231 throw new IllegalArgumentException("Failed to convert header value to int for header '" + name + '\'');
1232 }
1233 }
1234
1235 private long toLong(K name, V value) {
1236 try {
1237 return valueConverter.convertToLong(value);
1238 } catch (IllegalArgumentException e) {
1239 throw new IllegalArgumentException("Failed to convert header value to long for header '" + name + '\'');
1240 }
1241 }
1242
1243 private float toFloat(K name, V value) {
1244 try {
1245 return valueConverter.convertToFloat(value);
1246 } catch (IllegalArgumentException e) {
1247 throw new IllegalArgumentException("Failed to convert header value to float for header '" + name + '\'');
1248 }
1249 }
1250
1251 private double toDouble(K name, V value) {
1252 try {
1253 return valueConverter.convertToDouble(value);
1254 } catch (IllegalArgumentException e) {
1255 throw new IllegalArgumentException("Failed to convert header value to double for header '" + name + '\'');
1256 }
1257 }
1258
1259 private long toTimeMillis(K name, V value) {
1260 try {
1261 return valueConverter.convertToTimeMillis(value);
1262 } catch (IllegalArgumentException e) {
1263 throw new IllegalArgumentException(
1264 "Failed to convert header value to millsecond for header '" + name + '\'');
1265 }
1266 }
1267
1268
1269
1270
1271 public DefaultHeaders<K, V, T> copy() {
1272 DefaultHeaders<K, V, T> copy = new DefaultHeaders<K, V, T>(
1273 hashingStrategy, valueConverter, nameValidator, entries.length);
1274 copy.addImpl(this);
1275 return copy;
1276 }
1277
1278 private final class HeaderIterator implements Iterator<Entry<K, V>> {
1279 private HeaderEntry<K, V> current = head;
1280
1281 @Override
1282 public boolean hasNext() {
1283 return current.after != head;
1284 }
1285
1286 @Override
1287 public Entry<K, V> next() {
1288 current = current.after;
1289
1290 if (current == head) {
1291 throw new NoSuchElementException();
1292 }
1293
1294 return current;
1295 }
1296
1297 @Override
1298 public void remove() {
1299 throw new UnsupportedOperationException("read only");
1300 }
1301 }
1302
1303 private final class ValueIterator implements Iterator<V> {
1304 private final K name;
1305 private final int hash;
1306 private HeaderEntry<K, V> removalPrevious;
1307 private HeaderEntry<K, V> previous;
1308 private HeaderEntry<K, V> next;
1309
1310 ValueIterator(K name) {
1311 this.name = checkNotNull(name, "name");
1312 hash = hashingStrategy.hashCode(name);
1313 calculateNext(entries[index(hash)]);
1314 }
1315
1316 @Override
1317 public boolean hasNext() {
1318 return next != null;
1319 }
1320
1321 @Override
1322 public V next() {
1323 if (!hasNext()) {
1324 throw new NoSuchElementException();
1325 }
1326 if (previous != null) {
1327 removalPrevious = previous;
1328 }
1329 previous = next;
1330 calculateNext(next.next);
1331 return previous.value;
1332 }
1333
1334 @Override
1335 public void remove() {
1336 if (previous == null) {
1337 throw new IllegalStateException();
1338 }
1339 removalPrevious = remove0(previous, removalPrevious);
1340 previous = null;
1341 }
1342
1343 private void calculateNext(HeaderEntry<K, V> entry) {
1344 while (entry != null) {
1345 if (entry.hash == hash && hashingStrategy.equals(name, entry.key)) {
1346 next = entry;
1347 return;
1348 }
1349 entry = entry.next;
1350 }
1351 next = null;
1352 }
1353 }
1354
1355 protected static class HeaderEntry<K, V> implements Entry<K, V> {
1356 protected final int hash;
1357 protected final K key;
1358 protected V value;
1359
1360
1361
1362 protected HeaderEntry<K, V> next;
1363
1364
1365
1366 protected HeaderEntry<K, V> before, after;
1367
1368 protected HeaderEntry(int hash, K key) {
1369 this.hash = hash;
1370 this.key = key;
1371 }
1372
1373 HeaderEntry(int hash, K key, V value, HeaderEntry<K, V> next, HeaderEntry<K, V> head) {
1374 this.hash = hash;
1375 this.key = key;
1376 this.value = value;
1377 this.next = next;
1378
1379 after = head;
1380 before = head.before;
1381 pointNeighborsToThis();
1382 }
1383
1384 HeaderEntry() {
1385 hash = -1;
1386 key = null;
1387 before = after = this;
1388 }
1389
1390 protected final void pointNeighborsToThis() {
1391 before.after = this;
1392 after.before = this;
1393 }
1394
1395 public final HeaderEntry<K, V> before() {
1396 return before;
1397 }
1398
1399 public final HeaderEntry<K, V> after() {
1400 return after;
1401 }
1402
1403 protected void remove() {
1404 before.after = after;
1405 after.before = before;
1406 }
1407
1408 @Override
1409 public final K getKey() {
1410 return key;
1411 }
1412
1413 @Override
1414 public final V getValue() {
1415 return value;
1416 }
1417
1418 @Override
1419 public final V setValue(V value) {
1420 checkNotNull(value, "value");
1421 V oldValue = this.value;
1422 this.value = value;
1423 return oldValue;
1424 }
1425
1426 @Override
1427 public final String toString() {
1428 return key.toString() + '=' + value.toString();
1429 }
1430
1431 @Override
1432 public boolean equals(Object o) {
1433 if (!(o instanceof Map.Entry)) {
1434 return false;
1435 }
1436 Entry<?, ?> other = (Entry<?, ?>) o;
1437 return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) &&
1438 (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
1439 }
1440
1441 @Override
1442 public int hashCode() {
1443 return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
1444 }
1445 }
1446 }