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  
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   * Default implementation of {@link Headers};
38   *
39   * @param <K> the type of the header name.
40   * @param <V> the type of the header value.
41   * @param <T> the type to use for return values when the intention is to return {@code this} object.
42   */
43  public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers<K, V, T> {
44      /**
45       * Constant used to seed the hash code generation. Could be anything but this was borrowed from murmur3.
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           * Verify that {@code name} is valid.
62           * @param name The name to validate.
63           * @throws RuntimeException if {@code name} is not valid.
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           * Validate the given value. If the validation fails, then an implementation specific runtime exception may be
79           * thrown.
80           *
81           * @param value The value to validate.
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      * Create a new instance.
114      * @param nameHashingStrategy Used to hash and equality compare names.
115      * @param valueConverter Used to convert values to/from native types.
116      * @param nameValidator Used to validate name elements.
117      * @param arraySizeHint A hint as to how large the hash data structure should be.
118      * The next positive power of two will be used. An upper bound may be enforced.
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      * Create a new instance.
129      * @param nameHashingStrategy Used to hash and equality compare names.
130      * @param valueConverter Used to convert values to/from native types.
131      * @param nameValidator Used to validate name elements.
132      * @param arraySizeHint A hint as to how large the hash data structure should be.
133      * The next positive power of two will be used. An upper bound may be enforced.
134      * @param valueValidator The validation strategy for entry values.
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         // Enforce a bound of [2, 128] because hashMask is a byte. The max possible value of hashMask is one less
144         // than the length of this array, and we want the mask to be > 0.
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         // loop until the first header was found
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      * Equivalent to {@link #getAll(Object)} but no intermediate list is generated.
213      * @param name the name of the header to retrieve
214      * @return an {@link Iterator} of header values corresponding to {@code name}.
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                 // Fastest copy
446                 while (e != defaultHeaders.head) {
447                     add0(e.hash, index(e.hash), e.key, e.value);
448                     e = e.after;
449                 }
450             } else {
451                 // Fast copy
452                 while (e != defaultHeaders.head) {
453                     add(e.key, e.value);
454                     e = e.after;
455                 }
456             }
457         } else {
458             // Slow copy
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      * Test this object for equality against {@code h2}.
952      * @param h2 The object to check equality for.
953      * @param valueHashingStrategy Defines how values will be compared for equality.
954      * @return {@code true} if this object equals {@code h2} given {@code valueHashingStrategy}.
955      * {@code false} otherwise.
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      * Generate a hash code for this object given a {@link HashingStrategy} to generate hash codes for
983      * individual values.
984      * @param valueHashingStrategy Defines how values will be hashed.
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      * Call out to the given {@link NameValidator} to validate the given name.
1005      *
1006      * @param validator the validator to use
1007      * @param forAdd {@code true } if this validation is for adding to the headers, or {@code false} if this is for
1008      * setting (overwriting) the given header.
1009      * @param name the name to validate.
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         // Update the hash table.
1045         entries[i] = newHeaderEntry(h, name, value, entries[i]);
1046         ++size;
1047     }
1048 
1049     /**
1050      * @return the first value inserted whose hash code equals {@code h} and whose name is equal to {@code name}.
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             // If we don't have any existing starting point, then start from the beginning.
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      * Returns a deep copy of this instance.
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          * In bucket linked list
1361          */
1362         protected HeaderEntry<K, V> next;
1363         /**
1364          * Overall insertion order linked list
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 }