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