View Javadoc
1   /*
2    * Copyright 2014 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License, version 2.0 (the
5    * "License"); you may not use this file except in compliance with the License. You may obtain a
6    * copy of the License at:
7    *
8    * https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software distributed under the License
11   * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing permissions and limitations under
13   * the License.
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  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   * Default implementation of {@link Headers};
39   *
40   * @param <K> the type of the header name.
41   * @param <V> the type of the header value.
42   * @param <T> the type to use for return values when the intention is to return {@code this} object.
43   */
44  public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers<K, V, T> {
45      /**
46       * Constant used to seed the hash code generation. Could be anything but this was borrowed from murmur3.
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           * Verify that {@code name} is valid.
63           * @param name The name to validate.
64           * @throws RuntimeException if {@code name} is not valid.
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           * Validate the given value. If the validation fails, then an implementation specific runtime exception may be
80           * thrown.
81           *
82           * @param value The value to validate.
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      * Create a new instance.
115      * @param nameHashingStrategy Used to hash and equality compare names.
116      * @param valueConverter Used to convert values to/from native types.
117      * @param nameValidator Used to validate name elements.
118      * @param arraySizeHint A hint as to how large the hash data structure should be.
119      * The next positive power of two will be used. An upper bound may be enforced.
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      * Create a new instance.
130      * @param nameHashingStrategy Used to hash and equality compare names.
131      * @param valueConverter Used to convert values to/from native types.
132      * @param nameValidator Used to validate name elements.
133      * @param arraySizeHint A hint as to how large the hash data structure should be.
134      * The next positive power of two will be used. An upper bound may be enforced.
135      * @param valueValidator The validation strategy for entry values.
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         // Enforce a bound of [2, 128] because hashMask is a byte. The max possible value of hashMask is one less
145         // than the length of this array, and we want the mask to be > 0.
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      * Returns {@code true} if there exists a header with the given {@code name} for which the
153      * supplied {@code valuePredicate} returns {@code true} when invoked with the stored header
154      * value as the first argument and {@code predicateArg} as the second argument.
155      * <p>
156      * Matching is performed by invoking {@code valuePredicate.test(storedValue, predicateArg)}
157      * on each stored header value for {@code name}.
158      *
159      * @param name           the header name to search for (must not be {@code null})
160      * @param predicateArg   argument passed as the second parameter to {@code valuePredicate} (may be {@code null})
161      * @param valuePredicate predicate used to test stored header values (must not be {@code null})
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         // loop until the first header was found
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         LinkedList<V> values = new LinkedList<V>();
226 
227         int h = hashingStrategy.hashCode(name);
228         int i = index(h);
229         HeaderEntry<K, V> e = entries[i];
230         while (e != null) {
231             if (e.hash == h && hashingStrategy.equals(name, e.key)) {
232                 values.addFirst(e.getValue());
233             }
234             e = e.next;
235         }
236         return values;
237     }
238 
239     /**
240      * Equivalent to {@link #getAll(Object)} but no intermediate list is generated.
241      * @param name the name of the header to retrieve
242      * @return an {@link Iterator} of header values corresponding to {@code name}.
243      */
244     public Iterator<V> valueIterator(K name) {
245         return new ValueIterator(name);
246     }
247 
248     @Override
249     public List<V> getAllAndRemove(K name) {
250         List<V> all = getAll(name);
251         remove(name);
252         return all;
253     }
254 
255     @Override
256     public boolean contains(K name) {
257         return get(name) != null;
258     }
259 
260     @Override
261     public boolean containsObject(K name, Object value) {
262         return contains(name, fromObject(name, value));
263     }
264 
265     @Override
266     public boolean containsBoolean(K name, boolean value) {
267         return contains(name, fromBoolean(name, value));
268     }
269 
270     @Override
271     public boolean containsByte(K name, byte value) {
272         return contains(name, fromByte(name, value));
273     }
274 
275     @Override
276     public boolean containsChar(K name, char value) {
277         return contains(name, fromChar(name, value));
278     }
279 
280     @Override
281     public boolean containsShort(K name, short value) {
282         return contains(name, fromShort(name, value));
283     }
284 
285     @Override
286     public boolean containsInt(K name, int value) {
287         return contains(name, fromInt(name, value));
288     }
289 
290     @Override
291     public boolean containsLong(K name, long value) {
292         return contains(name, fromLong(name, value));
293     }
294 
295     @Override
296     public boolean containsFloat(K name, float value) {
297         return contains(name, fromFloat(name, value));
298     }
299 
300     @Override
301     public boolean containsDouble(K name, double value) {
302         return contains(name, fromDouble(name, value));
303     }
304 
305     @Override
306     public boolean containsTimeMillis(K name, long value) {
307         return contains(name, fromTimeMillis(name, value));
308     }
309 
310     @SuppressWarnings("unchecked")
311     @Override
312     public boolean contains(K name, V value) {
313         return contains(name, value, JAVA_HASHER);
314     }
315 
316     public final boolean contains(K name, V value, HashingStrategy<? super V> valueHashingStrategy) {
317         checkNotNull(name, "name");
318 
319         int h = hashingStrategy.hashCode(name);
320         int i = index(h);
321         HeaderEntry<K, V> e = entries[i];
322         while (e != null) {
323             if (e.hash == h && hashingStrategy.equals(name, e.key) && valueHashingStrategy.equals(value, e.value)) {
324                 return true;
325             }
326             e = e.next;
327         }
328         return false;
329     }
330 
331     @Override
332     public int size() {
333         return size;
334     }
335 
336     @Override
337     public boolean isEmpty() {
338         return head == head.after;
339     }
340 
341     @Override
342     public Set<K> names() {
343         if (isEmpty()) {
344             return Collections.emptySet();
345         }
346         Set<K> names = new LinkedHashSet<K>(size());
347         HeaderEntry<K, V> e = head.after;
348         while (e != head) {
349             names.add(e.getKey());
350             e = e.after;
351         }
352         return names;
353     }
354 
355     @Override
356     public T add(K name, V value) {
357         validateName(nameValidator, true, name);
358         validateValue(valueValidator, name, value);
359         checkNotNull(value, "value");
360         int h = hashingStrategy.hashCode(name);
361         int i = index(h);
362         add0(h, i, name, value);
363         return thisT();
364     }
365 
366     @Override
367     public T add(K name, Iterable<? extends V> values) {
368         validateName(nameValidator, true, name);
369         int h = hashingStrategy.hashCode(name);
370         int i = index(h);
371         for (V v: values) {
372             validateValue(valueValidator, name, v);
373             add0(h, i, name, v);
374         }
375         return thisT();
376     }
377 
378     @Override
379     public T add(K name, V... values) {
380         validateName(nameValidator, true, name);
381         int h = hashingStrategy.hashCode(name);
382         int i = index(h);
383         for (V v: values) {
384             validateValue(valueValidator, name, v);
385             add0(h, i, name, v);
386         }
387         return thisT();
388     }
389 
390     @Override
391     public T addObject(K name, Object value) {
392         return add(name, fromObject(name, value));
393     }
394 
395     @Override
396     public T addObject(K name, Iterable<?> values) {
397         for (Object value : values) {
398             addObject(name, value);
399         }
400         return thisT();
401     }
402 
403     @Override
404     public T addObject(K name, Object... values) {
405         for (Object value: values) {
406             addObject(name, value);
407         }
408         return thisT();
409     }
410 
411     @Override
412     public T addInt(K name, int value) {
413         return add(name, fromInt(name, value));
414     }
415 
416     @Override
417     public T addLong(K name, long value) {
418         return add(name, fromLong(name, value));
419     }
420 
421     @Override
422     public T addDouble(K name, double value) {
423         return add(name, fromDouble(name, value));
424     }
425 
426     @Override
427     public T addTimeMillis(K name, long value) {
428         return add(name, fromTimeMillis(name, value));
429     }
430 
431     @Override
432     public T addChar(K name, char value) {
433         return add(name, fromChar(name, value));
434     }
435 
436     @Override
437     public T addBoolean(K name, boolean value) {
438         return add(name, fromBoolean(name, value));
439     }
440 
441     @Override
442     public T addFloat(K name, float value) {
443         return add(name, fromFloat(name, value));
444     }
445 
446     @Override
447     public T addByte(K name, byte value) {
448         return add(name, fromByte(name, value));
449     }
450 
451     @Override
452     public T addShort(K name, short value) {
453         return add(name, fromShort(name, value));
454     }
455 
456     @Override
457     public T add(Headers<? extends K, ? extends V, ?> headers) {
458         if (headers == this) {
459             throw new IllegalArgumentException("can't add to itself.");
460         }
461         addImpl(headers);
462         return thisT();
463     }
464 
465     protected void addImpl(Headers<? extends K, ? extends V, ?> headers) {
466         if (headers instanceof DefaultHeaders) {
467             @SuppressWarnings("unchecked")
468             final DefaultHeaders<? extends K, ? extends V, T> defaultHeaders =
469                     (DefaultHeaders<? extends K, ? extends V, T>) headers;
470             HeaderEntry<? extends K, ? extends V> e = defaultHeaders.head.after;
471             if (defaultHeaders.hashingStrategy == hashingStrategy &&
472                     defaultHeaders.nameValidator == nameValidator) {
473                 // Fastest copy
474                 while (e != defaultHeaders.head) {
475                     add0(e.hash, index(e.hash), e.key, e.value);
476                     e = e.after;
477                 }
478             } else {
479                 // Fast copy
480                 while (e != defaultHeaders.head) {
481                     add(e.key, e.value);
482                     e = e.after;
483                 }
484             }
485         } else {
486             // Slow copy
487             for (Entry<? extends K, ? extends V> header : headers) {
488                 add(header.getKey(), header.getValue());
489             }
490         }
491     }
492 
493     @Override
494     public T set(K name, V value) {
495         validateName(nameValidator, false, name);
496         validateValue(valueValidator, name, value);
497         checkNotNull(value, "value");
498         int h = hashingStrategy.hashCode(name);
499         int i = index(h);
500         remove0(h, i, name);
501         add0(h, i, name, value);
502         return thisT();
503     }
504 
505     @Override
506     public T set(K name, Iterable<? extends V> values) {
507         validateName(nameValidator, false, name);
508         checkNotNull(values, "values");
509 
510         int h = hashingStrategy.hashCode(name);
511         int i = index(h);
512 
513         remove0(h, i, name);
514         for (V v: values) {
515             if (v == null) {
516                 break;
517             }
518             validateValue(valueValidator, name, v);
519             add0(h, i, name, v);
520         }
521 
522         return thisT();
523     }
524 
525     @Override
526     public T set(K name, 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 setObject(K name, Object value) {
547         V convertedValue = checkNotNull(fromObject(name, value), "convertedValue");
548         return set(name, convertedValue);
549     }
550 
551     @Override
552     public T setObject(K name, Iterable<?> values) {
553         validateName(nameValidator, false, name);
554 
555         int h = hashingStrategy.hashCode(name);
556         int i = index(h);
557 
558         remove0(h, i, name);
559         for (Object v: values) {
560             if (v == null) {
561                 break;
562             }
563             V converted = fromObject(name, v);
564             validateValue(valueValidator, name, converted);
565             add0(h, i, name, converted);
566         }
567 
568         return thisT();
569     }
570 
571     @Override
572     public T setObject(K name, Object... 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 setInt(K name, int value) {
593         return set(name, fromInt(name, value));
594     }
595 
596     @Override
597     public T setLong(K name, long value) {
598         return set(name, fromLong(name, value));
599     }
600 
601     @Override
602     public T setDouble(K name, double value) {
603         return set(name, fromDouble(name, value));
604     }
605 
606     @Override
607     public T setTimeMillis(K name, long value) {
608         return set(name, fromTimeMillis(name, value));
609     }
610 
611     @Override
612     public T setFloat(K name, float value) {
613         return set(name, fromFloat(name, value));
614     }
615 
616     @Override
617     public T setChar(K name, char value) {
618         return set(name, fromChar(name, value));
619     }
620 
621     @Override
622     public T setBoolean(K name, boolean value) {
623         return set(name, fromBoolean(name, value));
624     }
625 
626     @Override
627     public T setByte(K name, byte value) {
628         return set(name, fromByte(name, value));
629     }
630 
631     @Override
632     public T setShort(K name, short value) {
633         return set(name, fromShort(name, value));
634     }
635 
636     @Override
637     public T set(Headers<? extends K, ? extends V, ?> headers) {
638         if (headers != this) {
639             clear();
640             addImpl(headers);
641         }
642         return thisT();
643     }
644 
645     @Override
646     public T setAll(Headers<? extends K, ? extends V, ?> headers) {
647         if (headers != this) {
648             for (K key : headers.names()) {
649                 remove(key);
650             }
651             addImpl(headers);
652         }
653         return thisT();
654     }
655 
656     @Override
657     public boolean remove(K name) {
658         return getAndRemove(name) != null;
659     }
660 
661     @Override
662     public T clear() {
663         Arrays.fill(entries, null);
664         head.before = head.after = head;
665         size = 0;
666         return thisT();
667     }
668 
669     @Override
670     public Iterator<Entry<K, V>> iterator() {
671         return new HeaderIterator();
672     }
673 
674     @Override
675     public Boolean getBoolean(K name) {
676         V v = get(name);
677         try {
678             return v != null ? toBoolean(name, v) : null;
679         } catch (RuntimeException ignore) {
680             return null;
681         }
682     }
683 
684     @Override
685     public boolean getBoolean(K name, boolean defaultValue) {
686         Boolean v = getBoolean(name);
687         return v != null ? v : defaultValue;
688     }
689 
690     @Override
691     public Byte getByte(K name) {
692         V v = get(name);
693         try {
694             return v != null ? toByte(name, v) : null;
695         } catch (RuntimeException ignore) {
696             return null;
697         }
698     }
699 
700     @Override
701     public byte getByte(K name, byte defaultValue) {
702         Byte v = getByte(name);
703         return v != null ? v : defaultValue;
704     }
705 
706     @Override
707     public Character getChar(K name) {
708         V v = get(name);
709         try {
710             return v != null ? toChar(name, v) : null;
711         } catch (RuntimeException ignore) {
712             return null;
713         }
714     }
715 
716     @Override
717     public char getChar(K name, char defaultValue) {
718         Character v = getChar(name);
719         return v != null ? v : defaultValue;
720     }
721 
722     @Override
723     public Short getShort(K name) {
724         V v = get(name);
725         try {
726             return v != null ? toShort(name, v) : null;
727         } catch (RuntimeException ignore) {
728             return null;
729         }
730     }
731 
732     @Override
733     public short getShort(K name, short defaultValue) {
734         Short v = getShort(name);
735         return v != null ? v : defaultValue;
736     }
737 
738     @Override
739     public Integer getInt(K name) {
740         V v = get(name);
741         try {
742             return v != null ? toInt(name, v) : null;
743         } catch (RuntimeException ignore) {
744             return null;
745         }
746     }
747 
748     @Override
749     public int getInt(K name, int defaultValue) {
750         Integer v = getInt(name);
751         return v != null ? v : defaultValue;
752     }
753 
754     @Override
755     public Long getLong(K name) {
756         V v = get(name);
757         try {
758             return v != null ? toLong(name, v) : null;
759         } catch (RuntimeException ignore) {
760             return null;
761         }
762     }
763 
764     @Override
765     public long getLong(K name, long defaultValue) {
766         Long v = getLong(name);
767         return v != null ? v : defaultValue;
768     }
769 
770     @Override
771     public Float getFloat(K name) {
772         V v = get(name);
773         try {
774             return v != null ? toFloat(name, v) : null;
775         } catch (RuntimeException ignore) {
776             return null;
777         }
778     }
779 
780     @Override
781     public float getFloat(K name, float defaultValue) {
782         Float v = getFloat(name);
783         return v != null ? v : defaultValue;
784     }
785 
786     @Override
787     public Double getDouble(K name) {
788         V v = get(name);
789         try {
790             return v != null ? toDouble(name, v) : null;
791         } catch (RuntimeException ignore) {
792             return null;
793         }
794     }
795 
796     @Override
797     public double getDouble(K name, double defaultValue) {
798         Double v = getDouble(name);
799         return v != null ? v : defaultValue;
800     }
801 
802     @Override
803     public Long getTimeMillis(K name) {
804         V v = get(name);
805         try {
806             return v != null ? toTimeMillis(name, v) : null;
807         } catch (RuntimeException ignore) {
808             return null;
809         }
810     }
811 
812     @Override
813     public long getTimeMillis(K name, long defaultValue) {
814         Long v = getTimeMillis(name);
815         return v != null ? v : defaultValue;
816     }
817 
818     @Override
819     public Boolean getBooleanAndRemove(K name) {
820         V v = getAndRemove(name);
821         try {
822             return v != null ? toBoolean(name, v) : null;
823         } catch (RuntimeException ignore) {
824             return null;
825         }
826     }
827 
828     @Override
829     public boolean getBooleanAndRemove(K name, boolean defaultValue) {
830         Boolean v = getBooleanAndRemove(name);
831         return v != null ? v : defaultValue;
832     }
833 
834     @Override
835     public Byte getByteAndRemove(K name) {
836         V v = getAndRemove(name);
837         try {
838             return v != null ? toByte(name, v) : null;
839         } catch (RuntimeException ignore) {
840             return null;
841         }
842     }
843 
844     @Override
845     public byte getByteAndRemove(K name, byte defaultValue) {
846         Byte v = getByteAndRemove(name);
847         return v != null ? v : defaultValue;
848     }
849 
850     @Override
851     public Character getCharAndRemove(K name) {
852         V v = getAndRemove(name);
853         try {
854             return v != null ? toChar(name, v) : null;
855         } catch (RuntimeException ignore) {
856             return null;
857         }
858     }
859 
860     @Override
861     public char getCharAndRemove(K name, char defaultValue) {
862         Character v = getCharAndRemove(name);
863         return v != null ? v : defaultValue;
864     }
865 
866     @Override
867     public Short getShortAndRemove(K name) {
868         V v = getAndRemove(name);
869         try {
870             return v != null ? toShort(name, v) : null;
871         } catch (RuntimeException ignore) {
872             return null;
873         }
874     }
875 
876     @Override
877     public short getShortAndRemove(K name, short defaultValue) {
878         Short v = getShortAndRemove(name);
879         return v != null ? v : defaultValue;
880     }
881 
882     @Override
883     public Integer getIntAndRemove(K name) {
884         V v = getAndRemove(name);
885         try {
886             return v != null ? toInt(name, v) : null;
887         } catch (RuntimeException ignore) {
888             return null;
889         }
890     }
891 
892     @Override
893     public int getIntAndRemove(K name, int defaultValue) {
894         Integer v = getIntAndRemove(name);
895         return v != null ? v : defaultValue;
896     }
897 
898     @Override
899     public Long getLongAndRemove(K name) {
900         V v = getAndRemove(name);
901         try {
902             return v != null ? toLong(name, v) : null;
903         } catch (RuntimeException ignore) {
904             return null;
905         }
906     }
907 
908     @Override
909     public long getLongAndRemove(K name, long defaultValue) {
910         Long v = getLongAndRemove(name);
911         return v != null ? v : defaultValue;
912     }
913 
914     @Override
915     public Float getFloatAndRemove(K name) {
916         V v = getAndRemove(name);
917         try {
918             return v != null ? toFloat(name, v) : null;
919         } catch (RuntimeException ignore) {
920             return null;
921         }
922     }
923 
924     @Override
925     public float getFloatAndRemove(K name, float defaultValue) {
926         Float v = getFloatAndRemove(name);
927         return v != null ? v : defaultValue;
928     }
929 
930     @Override
931     public Double getDoubleAndRemove(K name) {
932         V v = getAndRemove(name);
933         try {
934             return v != null ? toDouble(name, v) : null;
935         } catch (RuntimeException ignore) {
936             return null;
937         }
938     }
939 
940     @Override
941     public double getDoubleAndRemove(K name, double defaultValue) {
942         Double v = getDoubleAndRemove(name);
943         return v != null ? v : defaultValue;
944     }
945 
946     @Override
947     public Long getTimeMillisAndRemove(K name) {
948         V v = getAndRemove(name);
949         try {
950             return v != null ? toTimeMillis(name, v) : null;
951         } catch (RuntimeException ignore) {
952             return null;
953         }
954     }
955 
956     @Override
957     public long getTimeMillisAndRemove(K name, long defaultValue) {
958         Long v = getTimeMillisAndRemove(name);
959         return v != null ? v : defaultValue;
960     }
961 
962     @SuppressWarnings("unchecked")
963     @Override
964     public boolean equals(Object o) {
965         if (!(o instanceof Headers)) {
966             return false;
967         }
968 
969         return equals((Headers<K, V, ?>) o, JAVA_HASHER);
970     }
971 
972     @SuppressWarnings("unchecked")
973     @Override
974     public int hashCode() {
975         return hashCode(JAVA_HASHER);
976     }
977 
978     /**
979      * Test this object for equality against {@code h2}.
980      * @param h2 The object to check equality for.
981      * @param valueHashingStrategy Defines how values will be compared for equality.
982      * @return {@code true} if this object equals {@code h2} given {@code valueHashingStrategy}.
983      * {@code false} otherwise.
984      */
985     public final boolean equals(Headers<K, V, ?> h2, HashingStrategy<V> valueHashingStrategy) {
986         if (h2.size() != size()) {
987             return false;
988         }
989 
990         if (this == h2) {
991             return true;
992         }
993 
994         for (K name : names()) {
995             List<V> otherValues = h2.getAll(name);
996             List<V> values = getAll(name);
997             if (otherValues.size() != values.size()) {
998                 return false;
999             }
1000             for (int i = 0; i < otherValues.size(); i++) {
1001                 if (!valueHashingStrategy.equals(otherValues.get(i), values.get(i))) {
1002                     return false;
1003                 }
1004             }
1005         }
1006         return true;
1007     }
1008 
1009     /**
1010      * Generate a hash code for this object given a {@link HashingStrategy} to generate hash codes for
1011      * individual values.
1012      * @param valueHashingStrategy Defines how values will be hashed.
1013      */
1014     public final int hashCode(HashingStrategy<V> valueHashingStrategy) {
1015         int result = HASH_CODE_SEED;
1016         for (K name : names()) {
1017             result = 31 * result + hashingStrategy.hashCode(name);
1018             List<V> values = getAll(name);
1019             for (int i = 0; i < values.size(); ++i) {
1020                 result = 31 * result + valueHashingStrategy.hashCode(values.get(i));
1021             }
1022         }
1023         return result;
1024     }
1025 
1026     @Override
1027     public String toString() {
1028         return HeadersUtils.toString(getClass(), iterator(), size());
1029     }
1030 
1031     /**
1032      * Call out to the given {@link NameValidator} to validate the given name.
1033      *
1034      * @param validator the validator to use
1035      * @param forAdd {@code true } if this validation is for adding to the headers, or {@code false} if this is for
1036      * setting (overwriting) the given header.
1037      * @param name the name to validate.
1038      */
1039     protected void validateName(NameValidator<K> validator, boolean forAdd, K name) {
1040         validator.validateName(name);
1041     }
1042 
1043     protected void validateValue(ValueValidator<V> validator, K name, V value) {
1044         try {
1045             validator.validate(value);
1046         } catch (IllegalArgumentException e) {
1047             throw new IllegalArgumentException("Validation failed for header '" + name + "'", e);
1048         }
1049     }
1050 
1051     protected HeaderEntry<K, V> newHeaderEntry(int h, K name, V value, HeaderEntry<K, V> next) {
1052         return new HeaderEntry<K, V>(h, name, value, next, head);
1053     }
1054 
1055     protected ValueConverter<V> valueConverter() {
1056         return valueConverter;
1057     }
1058 
1059     protected NameValidator<K> nameValidator() {
1060         return nameValidator;
1061     }
1062 
1063     protected ValueValidator<V> valueValidator() {
1064         return valueValidator;
1065     }
1066 
1067     private int index(int hash) {
1068         return hash & hashMask;
1069     }
1070 
1071     private void add0(int h, int i, K name, V value) {
1072         // Update the hash table.
1073         entries[i] = newHeaderEntry(h, name, value, entries[i]);
1074         ++size;
1075     }
1076 
1077     /**
1078      * @return the first value inserted whose hash code equals {@code h} and whose name is equal to {@code name}.
1079      */
1080     private V remove0(int h, int i, K name) {
1081         HeaderEntry<K, V> e = entries[i];
1082         if (e == null) {
1083             return null;
1084         }
1085 
1086         V value = null;
1087         HeaderEntry<K, V> next = e.next;
1088         while (next != null) {
1089             if (next.hash == h && hashingStrategy.equals(name, next.key)) {
1090                 value = next.value;
1091                 e.next = next.next;
1092                 next.remove();
1093                 --size;
1094             } else {
1095                 e = next;
1096             }
1097 
1098             next = e.next;
1099         }
1100 
1101         e = entries[i];
1102         if (e.hash == h && hashingStrategy.equals(name, e.key)) {
1103             if (value == null) {
1104                 value = e.value;
1105             }
1106             entries[i] = e.next;
1107             e.remove();
1108             --size;
1109         }
1110 
1111         return value;
1112     }
1113 
1114     HeaderEntry<K, V> remove0(HeaderEntry<K, V> entry, HeaderEntry<K, V> previous) {
1115         int i = index(entry.hash);
1116         HeaderEntry<K, V> firstEntry = entries[i];
1117         if (firstEntry == entry) {
1118             entries[i] = entry.next;
1119             previous = entries[i];
1120         } else if (previous == null) {
1121             // If we don't have any existing starting point, then start from the beginning.
1122             previous = firstEntry;
1123             HeaderEntry<K, V> next = firstEntry.next;
1124             while (next != null && next != entry) {
1125                 previous = next;
1126                 next = next.next;
1127             }
1128             assert next != null: "Entry not found in its hash bucket: " + entry;
1129             previous.next = entry.next;
1130         } else {
1131             previous.next = entry.next;
1132         }
1133         entry.remove();
1134         --size;
1135         return previous;
1136     }
1137 
1138     @SuppressWarnings("unchecked")
1139     private T thisT() {
1140         return (T) this;
1141     }
1142 
1143     private V fromObject(K name, Object value) {
1144         try {
1145             return valueConverter.convertObject(checkNotNull(value, "value"));
1146         } catch (IllegalArgumentException e) {
1147             throw new IllegalArgumentException("Failed to convert object value for header '" + name + '\'', e);
1148         }
1149     }
1150 
1151     private V fromBoolean(K name, boolean value) {
1152         try {
1153             return valueConverter.convertBoolean(value);
1154         } catch (IllegalArgumentException e) {
1155             throw new IllegalArgumentException("Failed to convert boolean value for header '" + name + '\'', e);
1156         }
1157     }
1158 
1159     private V fromByte(K name, byte value) {
1160         try {
1161             return valueConverter.convertByte(value);
1162         } catch (IllegalArgumentException e) {
1163             throw new IllegalArgumentException("Failed to convert byte value for header '" + name + '\'', e);
1164         }
1165     }
1166 
1167     private V fromChar(K name, char value) {
1168         try {
1169             return valueConverter.convertChar(value);
1170         } catch (IllegalArgumentException e) {
1171             throw new IllegalArgumentException("Failed to convert char value for header '" + name + '\'', e);
1172         }
1173     }
1174 
1175     private V fromShort(K name, short value) {
1176         try {
1177             return valueConverter.convertShort(value);
1178         } catch (IllegalArgumentException e) {
1179             throw new IllegalArgumentException("Failed to convert short value for header '" + name + '\'', e);
1180         }
1181     }
1182 
1183     private V fromInt(K name, int value) {
1184         try {
1185             return valueConverter.convertInt(value);
1186         } catch (IllegalArgumentException e) {
1187             throw new IllegalArgumentException("Failed to convert int value for header '" + name + '\'', e);
1188         }
1189     }
1190 
1191     private V fromLong(K name, long value) {
1192         try {
1193             return valueConverter.convertLong(value);
1194         } catch (IllegalArgumentException e) {
1195             throw new IllegalArgumentException("Failed to convert long value for header '" + name + '\'', e);
1196         }
1197     }
1198 
1199     private V fromFloat(K name, float value) {
1200         try {
1201             return valueConverter.convertFloat(value);
1202         } catch (IllegalArgumentException e) {
1203             throw new IllegalArgumentException("Failed to convert float value for header '" + name + '\'', e);
1204         }
1205     }
1206 
1207     private V fromDouble(K name, double value) {
1208         try {
1209             return valueConverter.convertDouble(value);
1210         } catch (IllegalArgumentException e) {
1211             throw new IllegalArgumentException("Failed to convert double value for header '" + name + '\'', e);
1212         }
1213     }
1214 
1215     private V fromTimeMillis(K name, long value) {
1216         try {
1217             return valueConverter.convertTimeMillis(value);
1218         } catch (IllegalArgumentException e) {
1219             throw new IllegalArgumentException("Failed to convert millsecond value for header '" + name + '\'', e);
1220         }
1221     }
1222 
1223     private boolean toBoolean(K name, V value) {
1224         try {
1225             return valueConverter.convertToBoolean(value);
1226         } catch (IllegalArgumentException e) {
1227             throw new IllegalArgumentException("Failed to convert header value to boolean for header '" + name + '\'');
1228         }
1229     }
1230 
1231     private byte toByte(K name, V value) {
1232         try {
1233             return valueConverter.convertToByte(value);
1234         } catch (IllegalArgumentException e) {
1235             throw new IllegalArgumentException("Failed to convert header value to byte for header '" + name + '\'');
1236         }
1237     }
1238 
1239     private char toChar(K name, V value) {
1240         try {
1241             return valueConverter.convertToChar(value);
1242         } catch (IllegalArgumentException e) {
1243             throw new IllegalArgumentException("Failed to convert header value to char for header '" + name + '\'');
1244         }
1245     }
1246 
1247     private short toShort(K name, V value) {
1248         try {
1249             return valueConverter.convertToShort(value);
1250         } catch (IllegalArgumentException e) {
1251             throw new IllegalArgumentException("Failed to convert header value to short for header '" + name + '\'');
1252         }
1253     }
1254 
1255     private int toInt(K name, V value) {
1256         try {
1257             return valueConverter.convertToInt(value);
1258         } catch (IllegalArgumentException e) {
1259             throw new IllegalArgumentException("Failed to convert header value to int for header '" + name + '\'');
1260         }
1261     }
1262 
1263     private long toLong(K name, V value) {
1264         try {
1265             return valueConverter.convertToLong(value);
1266         } catch (IllegalArgumentException e) {
1267             throw new IllegalArgumentException("Failed to convert header value to long for header '" + name + '\'');
1268         }
1269     }
1270 
1271     private float toFloat(K name, V value) {
1272         try {
1273             return valueConverter.convertToFloat(value);
1274         } catch (IllegalArgumentException e) {
1275             throw new IllegalArgumentException("Failed to convert header value to float for header '" + name + '\'');
1276         }
1277     }
1278 
1279     private double toDouble(K name, V value) {
1280         try {
1281             return valueConverter.convertToDouble(value);
1282         } catch (IllegalArgumentException e) {
1283             throw new IllegalArgumentException("Failed to convert header value to double for header '" + name + '\'');
1284         }
1285     }
1286 
1287     private long toTimeMillis(K name, V value) {
1288         try {
1289             return valueConverter.convertToTimeMillis(value);
1290         } catch (IllegalArgumentException e) {
1291             throw new IllegalArgumentException(
1292                     "Failed to convert header value to millsecond for header '" + name + '\'');
1293         }
1294     }
1295 
1296     /**
1297      * Returns a deep copy of this instance.
1298      */
1299     public DefaultHeaders<K, V, T> copy() {
1300         DefaultHeaders<K, V, T> copy = new DefaultHeaders<K, V, T>(
1301                 hashingStrategy, valueConverter, nameValidator, entries.length);
1302         copy.addImpl(this);
1303         return copy;
1304     }
1305 
1306     private final class HeaderIterator implements Iterator<Entry<K, V>> {
1307         private HeaderEntry<K, V> current = head;
1308 
1309         @Override
1310         public boolean hasNext() {
1311             return current.after != head;
1312         }
1313 
1314         @Override
1315         public Entry<K, V> next() {
1316             current = current.after;
1317 
1318             if (current == head) {
1319                 throw new NoSuchElementException();
1320             }
1321 
1322             return current;
1323         }
1324 
1325         @Override
1326         public void remove() {
1327             throw new UnsupportedOperationException("read only");
1328         }
1329     }
1330 
1331     private final class ValueIterator implements Iterator<V> {
1332         private final K name;
1333         private final int hash;
1334         private HeaderEntry<K, V> removalPrevious;
1335         private HeaderEntry<K, V> previous;
1336         private HeaderEntry<K, V> next;
1337 
1338         ValueIterator(K name) {
1339             this.name = checkNotNull(name, "name");
1340             hash = hashingStrategy.hashCode(name);
1341             calculateNext(entries[index(hash)]);
1342         }
1343 
1344         @Override
1345         public boolean hasNext() {
1346             return next != null;
1347         }
1348 
1349         @Override
1350         public V next() {
1351             if (!hasNext()) {
1352                 throw new NoSuchElementException();
1353             }
1354             if (previous != null) {
1355                 removalPrevious = previous;
1356             }
1357             previous = next;
1358             calculateNext(next.next);
1359             return previous.value;
1360         }
1361 
1362         @Override
1363         public void remove() {
1364             if (previous == null) {
1365                 throw new IllegalStateException();
1366             }
1367             removalPrevious = remove0(previous, removalPrevious);
1368             previous = null;
1369         }
1370 
1371         private void calculateNext(HeaderEntry<K, V> entry) {
1372             while (entry != null) {
1373                 if (entry.hash == hash && hashingStrategy.equals(name, entry.key)) {
1374                     next = entry;
1375                     return;
1376                 }
1377                 entry = entry.next;
1378             }
1379             next = null;
1380         }
1381     }
1382 
1383     protected static class HeaderEntry<K, V> implements Entry<K, V> {
1384         protected final int hash;
1385         protected final K key;
1386         protected V value;
1387         /**
1388          * In bucket linked list
1389          */
1390         protected HeaderEntry<K, V> next;
1391         /**
1392          * Overall insertion order linked list
1393          */
1394         protected HeaderEntry<K, V> before, after;
1395 
1396         protected HeaderEntry(int hash, K key) {
1397             this.hash = hash;
1398             this.key = key;
1399         }
1400 
1401         HeaderEntry(int hash, K key, V value, HeaderEntry<K, V> next, HeaderEntry<K, V> head) {
1402             this.hash = hash;
1403             this.key = key;
1404             this.value = value;
1405             this.next = next;
1406 
1407             after = head;
1408             before = head.before;
1409             pointNeighborsToThis();
1410         }
1411 
1412         HeaderEntry() {
1413             hash = -1;
1414             key = null;
1415             before = after = this;
1416         }
1417 
1418         protected final void pointNeighborsToThis() {
1419             before.after = this;
1420             after.before = this;
1421         }
1422 
1423         public final HeaderEntry<K, V> before() {
1424             return before;
1425         }
1426 
1427         public final HeaderEntry<K, V> after() {
1428             return after;
1429         }
1430 
1431         protected void remove() {
1432             before.after = after;
1433             after.before = before;
1434         }
1435 
1436         @Override
1437         public final K getKey() {
1438             return key;
1439         }
1440 
1441         @Override
1442         public final V getValue() {
1443             return value;
1444         }
1445 
1446         @Override
1447         public final V setValue(V value) {
1448             checkNotNull(value, "value");
1449             V oldValue = this.value;
1450             this.value = value;
1451             return oldValue;
1452         }
1453 
1454         @Override
1455         public final String toString() {
1456             return key.toString() + '=' + value.toString();
1457         }
1458 
1459         @Override
1460         public boolean equals(Object o) {
1461             if (!(o instanceof Map.Entry)) {
1462                 return false;
1463             }
1464             Entry<?, ?> other = (Entry<?, ?>) o;
1465             return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey()))  &&
1466                    (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()));
1467         }
1468 
1469         @Override
1470         public int hashCode() {
1471             return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode());
1472         }
1473     }
1474 }