• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 The gRPC Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a 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
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.grpc;
18 
19 import static com.google.common.base.Charsets.US_ASCII;
20 import static com.google.common.base.Preconditions.checkArgument;
21 import static com.google.common.base.Preconditions.checkNotNull;
22 
23 import com.google.common.annotations.VisibleForTesting;
24 import com.google.common.base.Preconditions;
25 import com.google.common.io.BaseEncoding;
26 import com.google.common.io.ByteStreams;
27 import java.io.ByteArrayInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.nio.ByteBuffer;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.BitSet;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Iterator;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.Map;
41 import java.util.NoSuchElementException;
42 import java.util.Set;
43 import java.util.logging.Level;
44 import java.util.logging.Logger;
45 import javax.annotation.Nullable;
46 import javax.annotation.concurrent.Immutable;
47 import javax.annotation.concurrent.NotThreadSafe;
48 
49 /**
50  * Provides access to read and write metadata values to be exchanged during a call.
51  *
52  * <p>Keys are allowed to be associated with more than one value.
53  *
54  * <p>This class is not thread safe, implementations should ensure that header reads and writes do
55  * not occur in multiple threads concurrently.
56  */
57 @NotThreadSafe
58 public final class Metadata {
59   private static final Logger logger = Logger.getLogger(Metadata.class.getName());
60 
61   /**
62    * All binary headers should have this suffix in their names. Vice versa.
63    *
64    * <p>Its value is {@code "-bin"}. An ASCII header's name must not end with this.
65    */
66   public static final String BINARY_HEADER_SUFFIX = "-bin";
67 
68   /**
69    * Simple metadata marshaller that encodes bytes as is.
70    *
71    * <p>This should be used when raw bytes are favored over un-serialized version of object. Can be
72    * helpful in situations where more processing to bytes is needed on application side, avoids
73    * double encoding/decoding.
74    *
75    * <p>Both {@link BinaryMarshaller#toBytes} and {@link BinaryMarshaller#parseBytes} methods do not
76    * return a copy of the byte array. Do _not_ modify the byte arrays of either the arguments or
77    * return values.
78    */
79   public static final BinaryMarshaller<byte[]> BINARY_BYTE_MARSHALLER =
80       new BinaryMarshaller<byte[]>() {
81 
82         @Override
83         public byte[] toBytes(byte[] value) {
84           return value;
85         }
86 
87         @Override
88         public byte[] parseBytes(byte[] serialized) {
89           return serialized;
90         }
91       };
92 
93   /**
94    * Simple metadata marshaller that encodes strings as is.
95    *
96    * <p>This should be used with ASCII strings that only contain the characters listed in the class
97    * comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and
98    * discarded by the transport, or the call may fail.
99    */
100   public static final AsciiMarshaller<String> ASCII_STRING_MARSHALLER =
101       new AsciiMarshaller<String>() {
102 
103         @Override
104         public String toAsciiString(String value) {
105           return value;
106         }
107 
108         @Override
109         public String parseAsciiString(String serialized) {
110           return serialized;
111         }
112       };
113 
114   static final BaseEncoding BASE64_ENCODING_OMIT_PADDING = BaseEncoding.base64().omitPadding();
115 
116   /**
117    * Constructor called by the transport layer when it receives binary metadata. Metadata will
118    * mutate the passed in array.
119    */
Metadata(byte[]... binaryValues)120   Metadata(byte[]... binaryValues) {
121     this(binaryValues.length / 2, binaryValues);
122   }
123 
124   /**
125    * Constructor called by the transport layer when it receives binary metadata. Metadata will
126    * mutate the passed in array.
127    *
128    * @param usedNames the number of names
129    */
Metadata(int usedNames, byte[]... binaryValues)130   Metadata(int usedNames, byte[]... binaryValues) {
131     this(usedNames, (Object[]) binaryValues);
132   }
133 
134   /**
135    * Constructor called by the transport layer when it receives partially-parsed metadata.
136    * Metadata will mutate the passed in array.
137    *
138    * @param usedNames the number of names
139    * @param namesAndValues an array of interleaved names and values, with each name
140    *     (at even indices) represented by a byte array, and values (at odd indices) as
141    *     described by {@link InternalMetadata#newMetadataWithParsedValues}.
142    */
Metadata(int usedNames, Object[] namesAndValues)143   Metadata(int usedNames, Object[] namesAndValues) {
144     assert (namesAndValues.length & 1) == 0
145         : "Odd number of key-value pairs " + namesAndValues.length;
146     size = usedNames;
147     this.namesAndValues = namesAndValues;
148   }
149 
150   private Object[] namesAndValues;
151   // The unscaled number of headers present.
152   private int size;
153 
name(int i)154   private byte[] name(int i) {
155     return (byte[]) namesAndValues[i * 2];
156   }
157 
name(int i, byte[] name)158   private void name(int i, byte[] name) {
159     namesAndValues[i * 2] = name;
160   }
161 
value(int i)162   private Object value(int i) {
163     return namesAndValues[i * 2 + 1];
164   }
165 
value(int i, byte[] value)166   private void value(int i, byte[] value) {
167     namesAndValues[i * 2 + 1] = value;
168   }
169 
value(int i, Object value)170   private void value(int i, Object value) {
171     if (namesAndValues instanceof byte[][]) {
172       // Reallocate an array of Object.
173       expand(cap());
174     }
175     namesAndValues[i * 2 + 1] = value;
176   }
177 
valueAsBytes(int i)178   private byte[] valueAsBytes(int i) {
179     Object value = value(i);
180     if (value instanceof byte[]) {
181       return (byte[]) value;
182     } else {
183       return ((LazyValue<?>) value).toBytes();
184     }
185   }
186 
valueAsBytesOrStream(int i)187   private Object valueAsBytesOrStream(int i) {
188     Object value = value(i);
189     if (value instanceof byte[]) {
190       return value;
191     } else {
192       return ((LazyValue<?>) value).toStream();
193     }
194   }
195 
valueAsT(int i, Key<T> key)196   private <T> T valueAsT(int i, Key<T> key) {
197     Object value = value(i);
198     if (value instanceof byte[]) {
199       return key.parseBytes((byte[]) value);
200     } else {
201       return ((LazyValue<?>) value).toObject(key);
202     }
203   }
204 
cap()205   private int cap() {
206     return namesAndValues != null ? namesAndValues.length : 0;
207   }
208 
209   // The scaled version of size.
len()210   private int len() {
211     return size * 2;
212   }
213 
214   /** checks when {@link #namesAndValues} is null or has no elements. */
isEmpty()215   private boolean isEmpty() {
216     return size == 0;
217   }
218 
219   /** Constructor called by the application layer when it wants to send metadata. */
Metadata()220   public Metadata() {}
221 
222   /** Returns the total number of key-value headers in this metadata, including duplicates. */
headerCount()223   int headerCount() {
224     return size;
225   }
226 
227   /**
228    * Returns true if a value is defined for the given key.
229    *
230    * <p>This is done by linear search, so if it is followed by {@link #get} or {@link #getAll},
231    * prefer calling them directly and checking the return value against {@code null}.
232    */
containsKey(Key<?> key)233   public boolean containsKey(Key<?> key) {
234     for (int i = 0; i < size; i++) {
235       if (bytesEqual(key.asciiName(), name(i))) {
236         return true;
237       }
238     }
239     return false;
240   }
241 
242   /**
243    * Returns the last metadata entry added with the name 'name' parsed as T.
244    *
245    * @return the parsed metadata entry or null if there are none.
246    */
247   @Nullable
get(Key<T> key)248   public <T> T get(Key<T> key) {
249     for (int i = size - 1; i >= 0; i--) {
250       if (bytesEqual(key.asciiName(), name(i))) {
251         return valueAsT(i, key);
252       }
253     }
254     return null;
255   }
256 
257   private final class IterableAt<T> implements Iterable<T> {
258     private final Key<T> key;
259     private int startIdx;
260 
IterableAt(Key<T> key, int startIdx)261     private IterableAt(Key<T> key, int startIdx) {
262       this.key = key;
263       this.startIdx = startIdx;
264     }
265 
266     @Override
iterator()267     public Iterator<T> iterator() {
268       return new Iterator<T>() {
269         private boolean hasNext = true;
270         private int idx = startIdx;
271 
272         @Override
273         public boolean hasNext() {
274           if (hasNext) {
275             return true;
276           }
277           for (; idx < size; idx++) {
278             if (bytesEqual(key.asciiName(), name(idx))) {
279               hasNext = true;
280               return hasNext;
281             }
282           }
283           return false;
284         }
285 
286         @Override
287         public T next() {
288           if (hasNext()) {
289             hasNext = false;
290             return valueAsT(idx++, key);
291           }
292           throw new NoSuchElementException();
293         }
294 
295         @Override
296         public void remove() {
297           throw new UnsupportedOperationException();
298         }
299       };
300     }
301   }
302 
303   /**
304    * Returns all the metadata entries named 'name', in the order they were received, parsed as T, or
305    * null if there are none. The iterator is not guaranteed to be "live." It may or may not be
306    * accurate if Metadata is mutated.
307    */
308   @Nullable
getAll(final Key<T> key)309   public <T> Iterable<T> getAll(final Key<T> key) {
310     for (int i = 0; i < size; i++) {
311       if (bytesEqual(key.asciiName(), name(i))) {
312         return new IterableAt<>(key, i);
313       }
314     }
315     return null;
316   }
317 
318   /**
319    * Returns set of all keys in store.
320    *
321    * @return unmodifiable Set of keys
322    */
323   @SuppressWarnings("deprecation") // The String ctor is deprecated, but fast.
keys()324   public Set<String> keys() {
325     if (isEmpty()) {
326       return Collections.emptySet();
327     }
328     Set<String> ks = new HashSet<>(size);
329     for (int i = 0; i < size; i++) {
330       ks.add(new String(name(i), 0 /* hibyte */));
331     }
332     // immutable in case we decide to change the implementation later.
333     return Collections.unmodifiableSet(ks);
334   }
335 
336   /**
337    * Adds the {@code key, value} pair. If {@code key} already has values, {@code value} is added to
338    * the end. Duplicate values for the same key are permitted.
339    *
340    * @throws NullPointerException if key or value is null
341    */
put(Key<T> key, T value)342   public <T> void put(Key<T> key, T value) {
343     Preconditions.checkNotNull(key, "key");
344     Preconditions.checkNotNull(value, "value");
345     maybeExpand();
346     name(size, key.asciiName());
347     if (key.serializesToStreams()) {
348       value(size, LazyValue.create(key, value));
349     } else {
350       value(size, key.toBytes(value));
351     }
352     size++;
353   }
354 
maybeExpand()355   private void maybeExpand() {
356     if (len() == 0 || len() == cap()) {
357       expand(Math.max(len() * 2, 8));
358     }
359   }
360 
361   // Expands to exactly the desired capacity.
expand(int newCapacity)362   private void expand(int newCapacity) {
363     Object[] newNamesAndValues = new Object[newCapacity];
364     if (!isEmpty()) {
365       System.arraycopy(namesAndValues, 0, newNamesAndValues, 0, len());
366     }
367     namesAndValues = newNamesAndValues;
368   }
369 
370   /**
371    * Removes the first occurrence of {@code value} for {@code key}.
372    *
373    * @param key key for value
374    * @param value value
375    * @return {@code true} if {@code value} removed; {@code false} if {@code value} was not present
376    * @throws NullPointerException if {@code key} or {@code value} is null
377    */
remove(Key<T> key, T value)378   public <T> boolean remove(Key<T> key, T value) {
379     Preconditions.checkNotNull(key, "key");
380     Preconditions.checkNotNull(value, "value");
381     for (int i = 0; i < size; i++) {
382       if (!bytesEqual(key.asciiName(), name(i))) {
383         continue;
384       }
385       T stored = valueAsT(i, key);
386       if (!value.equals(stored)) {
387         continue;
388       }
389       int writeIdx = i * 2;
390       int readIdx = (i + 1) * 2;
391       int readLen = len() - readIdx;
392       System.arraycopy(namesAndValues, readIdx, namesAndValues, writeIdx, readLen);
393       size -= 1;
394       name(size, null);
395       value(size, (byte[]) null);
396       return true;
397     }
398     return false;
399   }
400 
401   /** Remove all values for the given key. If there were no values, {@code null} is returned. */
removeAll(Key<T> key)402   public <T> Iterable<T> removeAll(Key<T> key) {
403     if (isEmpty()) {
404       return null;
405     }
406     int writeIdx = 0;
407     int readIdx = 0;
408     List<T> ret = null;
409     for (; readIdx < size; readIdx++) {
410       if (bytesEqual(key.asciiName(), name(readIdx))) {
411         ret = ret != null ? ret : new ArrayList<T>();
412         ret.add(valueAsT(readIdx, key));
413         continue;
414       }
415       name(writeIdx, name(readIdx));
416       value(writeIdx, value(readIdx));
417       writeIdx++;
418     }
419     int newSize = writeIdx;
420     // Multiply by two since namesAndValues is interleaved.
421     Arrays.fill(namesAndValues, writeIdx * 2, len(), null);
422     size = newSize;
423     return ret;
424   }
425 
426   /**
427    * Remove all values for the given key without returning them. This is a minor performance
428    * optimization if you do not need the previous values.
429    */
430   @ExperimentalApi("https://github.com/grpc/grpc-java/issues/4691")
discardAll(Key<T> key)431   public <T> void discardAll(Key<T> key) {
432     if (isEmpty()) {
433       return;
434     }
435     int writeIdx = 0;
436     int readIdx = 0;
437     for (; readIdx < size; readIdx++) {
438       if (bytesEqual(key.asciiName(), name(readIdx))) {
439         continue;
440       }
441       name(writeIdx, name(readIdx));
442       value(writeIdx, value(readIdx));
443       writeIdx++;
444     }
445     int newSize = writeIdx;
446     // Multiply by two since namesAndValues is interleaved.
447     Arrays.fill(namesAndValues, writeIdx * 2, len(), null);
448     size = newSize;
449   }
450 
451   /**
452    * Serialize all the metadata entries.
453    *
454    * <p>It produces serialized names and values interleaved. result[i*2] are names, while
455    * result[i*2+1] are values.
456    *
457    * <p>Names are ASCII string bytes that contains only the characters listed in the class comment
458    * of {@link Key}. If the name ends with {@code "-bin"}, the value can be raw binary. Otherwise,
459    * the value must contain only characters listed in the class comments of {@link AsciiMarshaller}
460    *
461    * <p>The returned individual byte arrays <em>must not</em> be modified. However, the top level
462    * array may be modified.
463    *
464    * <p>This method is intended for transport use only.
465    */
466   @Nullable
serialize()467   byte[][] serialize() {
468     byte[][] serialized = new byte[len()][];
469     if (namesAndValues instanceof byte[][]) {
470       System.arraycopy(namesAndValues, 0, serialized, 0, len());
471     } else {
472       for (int i = 0; i < size; i++) {
473         serialized[i * 2] = name(i);
474         serialized[i * 2 + 1] = valueAsBytes(i);
475       }
476     }
477     return serialized;
478   }
479 
480   /**
481    * Serializes all metadata entries, leaving some values as {@link InputStream}s.
482    *
483    * <p>Produces serialized names and values interleaved. result[i*2] are names, while
484    * result[i*2+1] are values.
485    *
486    * <p>Names are byte arrays as described according to the {@link #serialize}
487    * method. Values are either byte arrays or {@link InputStream}s.
488    *
489    * <p>This method is intended for transport use only.
490    */
491   @Nullable
serializePartial()492   Object[] serializePartial() {
493     Object[] serialized = new Object[len()];
494     for (int i = 0; i < size; i++) {
495       serialized[i * 2] = name(i);
496       serialized[i * 2 + 1] = valueAsBytesOrStream(i);
497     }
498     return serialized;
499   }
500 
501   /**
502    * Perform a simple merge of two sets of metadata.
503    *
504    * <p>This is a purely additive operation, because a single key can be associated with multiple
505    * values.
506    */
merge(Metadata other)507   public void merge(Metadata other) {
508     if (other.isEmpty()) {
509       return;
510     }
511     int remaining = cap() - len();
512     if (isEmpty() || remaining < other.len()) {
513       expand(len() + other.len());
514     }
515     System.arraycopy(other.namesAndValues, 0, namesAndValues, len(), other.len());
516     size += other.size;
517   }
518 
519   /**
520    * Merge values from the given set of keys into this set of metadata. If a key is present in keys,
521    * then all of the associated values will be copied over.
522    *
523    * @param other The source of the new key values.
524    * @param keys The subset of matching key we want to copy, if they exist in the source.
525    */
merge(Metadata other, Set<Key<?>> keys)526   public void merge(Metadata other, Set<Key<?>> keys) {
527     Preconditions.checkNotNull(other, "other");
528     // Use ByteBuffer for equals and hashCode.
529     Map<ByteBuffer, Key<?>> asciiKeys = new HashMap<>(keys.size());
530     for (Key<?> key : keys) {
531       asciiKeys.put(ByteBuffer.wrap(key.asciiName()), key);
532     }
533     for (int i = 0; i < other.size; i++) {
534       ByteBuffer wrappedNamed = ByteBuffer.wrap(other.name(i));
535       if (asciiKeys.containsKey(wrappedNamed)) {
536         maybeExpand();
537         name(size, other.name(i));
538         value(size, other.value(i));
539         size++;
540       }
541     }
542   }
543 
544   @Override
toString()545   public String toString() {
546     StringBuilder sb = new StringBuilder("Metadata(");
547     for (int i = 0; i < size; i++) {
548       if (i != 0) {
549         sb.append(',');
550       }
551       String headerName = new String(name(i), US_ASCII);
552       sb.append(headerName).append('=');
553       if (headerName.endsWith(BINARY_HEADER_SUFFIX)) {
554         sb.append(BASE64_ENCODING_OMIT_PADDING.encode(valueAsBytes(i)));
555       } else {
556         String headerValue = new String(valueAsBytes(i), US_ASCII);
557         sb.append(headerValue);
558       }
559     }
560     return sb.append(')').toString();
561   }
562 
bytesEqual(byte[] left, byte[] right)563   private boolean bytesEqual(byte[] left, byte[] right) {
564     return Arrays.equals(left, right);
565   }
566 
567   /** Marshaller for metadata values that are serialized into raw binary. */
568   public interface BinaryMarshaller<T> {
569     /**
570      * Serialize a metadata value to bytes.
571      *
572      * @param value to serialize
573      * @return serialized version of value
574      */
toBytes(T value)575     byte[] toBytes(T value);
576 
577     /**
578      * Parse a serialized metadata value from bytes.
579      *
580      * @param serialized value of metadata to parse
581      * @return a parsed instance of type T
582      */
parseBytes(byte[] serialized)583     T parseBytes(byte[] serialized);
584   }
585 
586   /**
587    * Marshaller for metadata values that are serialized into ASCII strings. The strings contain only
588    * following characters:
589    *
590    * <ul>
591    * <li>Space: {@code 0x20}, but must not be at the beginning or at the end of the value. Leading
592    *     or trailing whitespace may not be preserved.
593    * <li>ASCII visible characters ({@code 0x21-0x7E}).
594    * </ul>
595    *
596    * <p>Note this has to be the subset of valid characters in {@code field-content} from RFC 7230
597    * Section 3.2.
598    */
599   public interface AsciiMarshaller<T> {
600     /**
601      * Serialize a metadata value to a ASCII string that contains only the characters listed in the
602      * class comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and
603      * discarded by the transport, or the call may fail.
604      *
605      * @param value to serialize
606      * @return serialized version of value, or null if value cannot be transmitted.
607      */
toAsciiString(T value)608     String toAsciiString(T value);
609 
610     /**
611      * Parse a serialized metadata value from an ASCII string.
612      *
613      * @param serialized value of metadata to parse
614      * @return a parsed instance of type T
615      */
parseAsciiString(String serialized)616     T parseAsciiString(String serialized);
617   }
618 
619   /** Marshaller for metadata values that are serialized to an InputStream. */
620   @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6575")
621   public interface BinaryStreamMarshaller<T> {
622     /**
623      * Serializes a metadata value to an {@link InputStream}.
624      *
625      * @param value to serialize
626      * @return serialized version of value
627      */
toStream(T value)628     InputStream toStream(T value);
629 
630     /**
631      * Parses a serialized metadata value from an {@link InputStream}.
632      *
633      * @param stream of metadata to parse
634      * @return a parsed instance of type T
635      */
parseStream(InputStream stream)636     T parseStream(InputStream stream);
637   }
638 
639   /**
640    * Key for metadata entries. Allows for parsing and serialization of metadata.
641    *
642    * <h3>Valid characters in key names</h3>
643    *
644    * <p>Only the following ASCII characters are allowed in the names of keys:
645    *
646    * <ul>
647    * <li>digits: {@code 0-9}
648    * <li>uppercase letters: {@code A-Z} (normalized to lower)
649    * <li>lowercase letters: {@code a-z}
650    * <li>special characters: {@code -_.}
651    * </ul>
652    *
653    * <p>This is a strict subset of the HTTP field-name rules. Applications may not send or receive
654    * metadata with invalid key names. However, the gRPC library may preserve any metadata received
655    * even if it does not conform to the above limitations. Additionally, if metadata contains non
656    * conforming field names, they will still be sent. In this way, unknown metadata fields are
657    * parsed, serialized and preserved, but never interpreted. They are similar to protobuf unknown
658    * fields.
659    *
660    * <p>Note this has to be the subset of valid HTTP/2 token characters as defined in RFC7230
661    * Section 3.2.6 and RFC5234 Section B.1
662    *
663    * <p>Note that a key is immutable but it may not be deeply immutable, because the key depends on
664    * its marshaller, and the marshaller can be mutable though not recommended.
665    *
666    * @see <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md">Wire Spec</a>
667    * @see <a href="https://tools.ietf.org/html/rfc7230#section-3.2.6">RFC7230</a>
668    * @see <a href="https://tools.ietf.org/html/rfc5234#appendix-B.1">RFC5234</a>
669    */
670   @Immutable
671   public abstract static class Key<T> {
672 
673     /** Valid characters for field names as defined in RFC7230 and RFC5234. */
674     private static final BitSet VALID_T_CHARS = generateValidTChars();
675 
676     /**
677      * Creates a key for a binary header.
678      *
679      * @param name Must contain only the valid key characters as defined in the class comment. Must
680      *     end with {@link #BINARY_HEADER_SUFFIX}.
681      */
of(String name, BinaryMarshaller<T> marshaller)682     public static <T> Key<T> of(String name, BinaryMarshaller<T> marshaller) {
683       return new BinaryKey<>(name, marshaller);
684     }
685 
686     /**
687      * Creates a key for a binary header, serializing to input streams.
688      *
689      * @param name Must contain only the valid key characters as defined in the class comment. Must
690      *     end with {@link #BINARY_HEADER_SUFFIX}.
691      */
692     @ExperimentalApi("https://github.com/grpc/grpc-java/issues/6575")
of(String name, BinaryStreamMarshaller<T> marshaller)693     public static <T> Key<T> of(String name, BinaryStreamMarshaller<T> marshaller) {
694       return new LazyStreamBinaryKey<>(name, marshaller);
695     }
696 
697     /**
698      * Creates a key for an ASCII header.
699      *
700      * @param name Must contain only the valid key characters as defined in the class comment. Must
701      *     <b>not</b> end with {@link #BINARY_HEADER_SUFFIX}
702      */
of(String name, AsciiMarshaller<T> marshaller)703     public static <T> Key<T> of(String name, AsciiMarshaller<T> marshaller) {
704       return of(name, false, marshaller);
705     }
706 
of(String name, boolean pseudo, AsciiMarshaller<T> marshaller)707     static <T> Key<T> of(String name, boolean pseudo, AsciiMarshaller<T> marshaller) {
708       return new AsciiKey<>(name, pseudo, marshaller);
709     }
710 
of(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller)711     static <T> Key<T> of(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller) {
712       return new TrustedAsciiKey<>(name, pseudo, marshaller);
713     }
714 
715     private final String originalName;
716 
717     private final String name;
718     private final byte[] nameBytes;
719     private final Object marshaller;
720 
generateValidTChars()721     private static BitSet generateValidTChars() {
722       BitSet valid = new BitSet(0x7f);
723       valid.set('-');
724       valid.set('_');
725       valid.set('.');
726       for (char c = '0'; c <= '9'; c++) {
727         valid.set(c);
728       }
729       // Only validates after normalization, so we exclude uppercase.
730       for (char c = 'a'; c <= 'z'; c++) {
731         valid.set(c);
732       }
733       return valid;
734     }
735 
validateName(String n, boolean pseudo)736     private static String validateName(String n, boolean pseudo) {
737       checkNotNull(n, "name");
738       checkArgument(!n.isEmpty(), "token must have at least 1 tchar");
739       if (n.equals("connection")) {
740         logger.log(
741             Level.WARNING,
742             "Metadata key is 'Connection', which should not be used. That is used by HTTP/1 for "
743             + "connection-specific headers which are not to be forwarded. There is probably an "
744             + "HTTP/1 conversion bug. Simply removing the Connection header is not enough; you "
745             + "should remove all headers it references as well. See RFC 7230 section 6.1",
746             new RuntimeException("exception to show backtrace"));
747       }
748       for (int i = 0; i < n.length(); i++) {
749         char tChar = n.charAt(i);
750         if (pseudo && tChar == ':' && i == 0) {
751           continue;
752         }
753 
754         checkArgument(
755             VALID_T_CHARS.get(tChar), "Invalid character '%s' in key name '%s'", tChar, n);
756       }
757       return n;
758     }
759 
Key(String name, boolean pseudo, Object marshaller)760     private Key(String name, boolean pseudo, Object marshaller) {
761       this.originalName = checkNotNull(name, "name");
762       this.name = validateName(this.originalName.toLowerCase(Locale.ROOT), pseudo);
763       this.nameBytes = this.name.getBytes(US_ASCII);
764       this.marshaller = marshaller;
765     }
766 
767     /**
768      * Returns the original name used to create this key.
769      */
originalName()770     public final String originalName() {
771       return originalName;
772     }
773 
774     /**
775      * Returns the normalized name for this key.
776      */
name()777     public final String name() {
778       return name;
779     }
780 
781     /**
782      * Get the name as bytes using ASCII-encoding.
783      *
784      * <p>The returned byte arrays <em>must not</em> be modified.
785      *
786      * <p>This method is intended for transport use only.
787      */
788     // TODO (louiscryan): Migrate to ByteString
789     @VisibleForTesting
asciiName()790     byte[] asciiName() {
791       return nameBytes;
792     }
793 
794     /**
795      * Returns true if the two objects are both Keys, and their names match (case insensitive).
796      */
797     @SuppressWarnings("EqualsGetClass")
798     @Override
equals(Object o)799     public final boolean equals(Object o) {
800       if (this == o) {
801         return true;
802       }
803       if (o == null || getClass() != o.getClass()) {
804         return false;
805       }
806       Key<?> key = (Key<?>) o;
807       return name.equals(key.name);
808     }
809 
810     @Override
hashCode()811     public final int hashCode() {
812       return name.hashCode();
813     }
814 
815     @Override
toString()816     public String toString() {
817       return "Key{name='" + name + "'}";
818     }
819 
820     /**
821      * Serialize a metadata value to bytes.
822      *
823      * @param value to serialize
824      * @return serialized version of value
825      */
toBytes(T value)826     abstract byte[] toBytes(T value);
827 
828     /**
829      * Parse a serialized metadata value from bytes.
830      *
831      * @param serialized value of metadata to parse
832      * @return a parsed instance of type T
833      */
parseBytes(byte[] serialized)834     abstract T parseBytes(byte[] serialized);
835 
836     /**
837      * Returns whether this key will be serialized to bytes lazily.
838      */
serializesToStreams()839     boolean serializesToStreams() {
840       return false;
841     }
842 
843     /**
844      * Gets this keys (implementation-specific) marshaller, or null if the
845      * marshaller is not of the given type.
846      *
847      * @param marshallerClass The type we expect the marshaller to be.
848      * @return the marshaller object for this key, or null.
849      */
850     @Nullable
getMarshaller(Class<M> marshallerClass)851     final <M> M getMarshaller(Class<M> marshallerClass) {
852       if (marshallerClass.isInstance(marshaller)) {
853         return marshallerClass.cast(marshaller);
854       }
855       return null;
856     }
857   }
858 
859   private static class BinaryKey<T> extends Key<T> {
860     private final BinaryMarshaller<T> marshaller;
861 
862     /** Keys have a name and a binary marshaller used for serialization. */
BinaryKey(String name, BinaryMarshaller<T> marshaller)863     private BinaryKey(String name, BinaryMarshaller<T> marshaller) {
864       super(name, false /* not pseudo */, marshaller);
865       checkArgument(
866           name.endsWith(BINARY_HEADER_SUFFIX),
867           "Binary header is named %s. It must end with %s",
868           name,
869           BINARY_HEADER_SUFFIX);
870       checkArgument(name.length() > BINARY_HEADER_SUFFIX.length(), "empty key name");
871       this.marshaller = checkNotNull(marshaller, "marshaller is null");
872     }
873 
874     @Override
toBytes(T value)875     byte[] toBytes(T value) {
876       return Preconditions.checkNotNull(marshaller.toBytes(value), "null marshaller.toBytes()");
877     }
878 
879     @Override
parseBytes(byte[] serialized)880     T parseBytes(byte[] serialized) {
881       return marshaller.parseBytes(serialized);
882     }
883   }
884 
885   /** A binary key for values which should be serialized lazily to {@link InputStream}s. */
886   private static class LazyStreamBinaryKey<T> extends Key<T> {
887 
888     private final BinaryStreamMarshaller<T> marshaller;
889 
890     /** Keys have a name and a stream marshaller used for serialization. */
LazyStreamBinaryKey(String name, BinaryStreamMarshaller<T> marshaller)891     private LazyStreamBinaryKey(String name, BinaryStreamMarshaller<T> marshaller) {
892       super(name, false /* not pseudo */, marshaller);
893       checkArgument(
894           name.endsWith(BINARY_HEADER_SUFFIX),
895           "Binary header is named %s. It must end with %s",
896           name,
897           BINARY_HEADER_SUFFIX);
898       checkArgument(name.length() > BINARY_HEADER_SUFFIX.length(), "empty key name");
899       this.marshaller = checkNotNull(marshaller, "marshaller is null");
900     }
901 
902     @Override
toBytes(T value)903     byte[] toBytes(T value) {
904       return streamToBytes(checkNotNull(marshaller.toStream(value), "null marshaller.toStream()"));
905     }
906 
907     @Override
parseBytes(byte[] serialized)908     T parseBytes(byte[] serialized) {
909       return marshaller.parseStream(new ByteArrayInputStream(serialized));
910     }
911 
912     @Override
serializesToStreams()913     boolean serializesToStreams() {
914       return true;
915     }
916   }
917 
918   /** Internal holder for values which are serialized/de-serialized lazily. */
919   static final class LazyValue<T> {
920     private final BinaryStreamMarshaller<T> marshaller;
921     private final T value;
922     private volatile byte[] serialized;
923 
create(Key<T> key, T value)924     static <T> LazyValue<T> create(Key<T> key, T value) {
925       return new LazyValue<>(checkNotNull(getBinaryStreamMarshaller(key)), value);
926     }
927 
928     /** A value set by the application. */
LazyValue(BinaryStreamMarshaller<T> marshaller, T value)929     LazyValue(BinaryStreamMarshaller<T> marshaller, T value) {
930       this.marshaller = marshaller;
931       this.value = value;
932     }
933 
toStream()934     InputStream toStream() {
935       return checkNotNull(marshaller.toStream(value), "null marshaller.toStream()");
936     }
937 
toBytes()938     byte[] toBytes() {
939       if (serialized == null) {
940         synchronized (this) {
941           if (serialized == null) {
942             serialized = streamToBytes(toStream());
943           }
944         }
945       }
946       return serialized;
947     }
948 
toObject(Key<T2> key)949     <T2> T2 toObject(Key<T2> key) {
950       if (key.serializesToStreams()) {
951         BinaryStreamMarshaller<T2> marshaller = getBinaryStreamMarshaller(key);
952         if (marshaller != null) {
953           return marshaller.parseStream(toStream());
954         }
955       }
956       return key.parseBytes(toBytes());
957     }
958 
959     @Nullable
960     @SuppressWarnings("unchecked")
getBinaryStreamMarshaller(Key<T> key)961     private static <T> BinaryStreamMarshaller<T> getBinaryStreamMarshaller(Key<T> key) {
962       return (BinaryStreamMarshaller<T>) key.getMarshaller(BinaryStreamMarshaller.class);
963     }
964   }
965 
966   private static class AsciiKey<T> extends Key<T> {
967     private final AsciiMarshaller<T> marshaller;
968 
969     /** Keys have a name and an ASCII marshaller used for serialization. */
AsciiKey(String name, boolean pseudo, AsciiMarshaller<T> marshaller)970     private AsciiKey(String name, boolean pseudo, AsciiMarshaller<T> marshaller) {
971       super(name, pseudo, marshaller);
972       Preconditions.checkArgument(
973           !name.endsWith(BINARY_HEADER_SUFFIX),
974           "ASCII header is named %s.  Only binary headers may end with %s",
975           name,
976           BINARY_HEADER_SUFFIX);
977       this.marshaller = Preconditions.checkNotNull(marshaller, "marshaller");
978     }
979 
980     @Override
toBytes(T value)981     byte[] toBytes(T value) {
982       String encoded = Preconditions.checkNotNull(
983           marshaller.toAsciiString(value), "null marshaller.toAsciiString()");
984       return encoded.getBytes(US_ASCII);
985     }
986 
987     @Override
parseBytes(byte[] serialized)988     T parseBytes(byte[] serialized) {
989       return marshaller.parseAsciiString(new String(serialized, US_ASCII));
990     }
991   }
992 
993   private static final class TrustedAsciiKey<T> extends Key<T> {
994     private final TrustedAsciiMarshaller<T> marshaller;
995 
996     /** Keys have a name and an ASCII marshaller used for serialization. */
TrustedAsciiKey(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller)997     private TrustedAsciiKey(String name, boolean pseudo, TrustedAsciiMarshaller<T> marshaller) {
998       super(name, pseudo, marshaller);
999       Preconditions.checkArgument(
1000           !name.endsWith(BINARY_HEADER_SUFFIX),
1001           "ASCII header is named %s.  Only binary headers may end with %s",
1002           name,
1003           BINARY_HEADER_SUFFIX);
1004       this.marshaller = Preconditions.checkNotNull(marshaller, "marshaller");
1005     }
1006 
1007     @Override
toBytes(T value)1008     byte[] toBytes(T value) {
1009       return Preconditions.checkNotNull(
1010           marshaller.toAsciiString(value), "null marshaller.toAsciiString()");
1011     }
1012 
1013     @Override
parseBytes(byte[] serialized)1014     T parseBytes(byte[] serialized) {
1015       return marshaller.parseAsciiString(serialized);
1016     }
1017   }
1018 
1019   /**
1020    * A specialized plain ASCII marshaller. Both input and output are assumed to be valid header
1021    * ASCII.
1022    */
1023   @Immutable
1024   interface TrustedAsciiMarshaller<T> {
1025     /**
1026      * Serialize a metadata value to a ASCII string that contains only the characters listed in the
1027      * class comment of {@link io.grpc.Metadata.AsciiMarshaller}. Otherwise the output may be
1028      * considered invalid and discarded by the transport, or the call may fail.
1029      *
1030      * @param value to serialize
1031      * @return serialized version of value, or null if value cannot be transmitted.
1032      */
toAsciiString(T value)1033     byte[] toAsciiString(T value);
1034 
1035     /**
1036      * Parse a serialized metadata value from an ASCII string.
1037      *
1038      * @param serialized value of metadata to parse
1039      * @return a parsed instance of type T
1040      */
parseAsciiString(byte[] serialized)1041     T parseAsciiString(byte[] serialized);
1042   }
1043 
streamToBytes(InputStream stream)1044   private static byte[] streamToBytes(InputStream stream) {
1045     try {
1046       return ByteStreams.toByteArray(stream);
1047     } catch (IOException ioe) {
1048       throw new RuntimeException("failure reading serialized stream", ioe);
1049     }
1050   }
1051 }
1052