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