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