1 /* 2 * Copyright 2017 Google LLC 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google LLC nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.google.api.gax.rpc; 31 32 import com.google.api.gax.core.GaxProperties; 33 import com.google.common.collect.ImmutableMap; 34 import java.io.Serializable; 35 import java.util.Map; 36 37 /** 38 * Implementation of HeaderProvider that provides headers describing the API client library making 39 * API calls. 40 */ 41 public class ApiClientHeaderProvider implements HeaderProvider, Serializable { 42 private static final long serialVersionUID = -8876627296793342119L; 43 static final String QUOTA_PROJECT_ID_HEADER_KEY = "x-goog-user-project"; 44 45 private final Map<String, String> headers; 46 ApiClientHeaderProvider(Builder builder)47 protected ApiClientHeaderProvider(Builder builder) { 48 ImmutableMap.Builder<String, String> headersBuilder = ImmutableMap.builder(); 49 50 if (builder.getApiClientHeaderKey() != null) { 51 StringBuilder apiClientHeaderValue = new StringBuilder(); 52 // Order of tokens matters!!! 53 appendToken(apiClientHeaderValue, builder.getJvmToken()); 54 appendToken(apiClientHeaderValue, builder.getClientLibToken()); 55 appendToken(apiClientHeaderValue, builder.getGeneratedLibToken()); 56 appendToken(apiClientHeaderValue, builder.getGeneratedRuntimeToken()); 57 appendToken(apiClientHeaderValue, builder.getTransportToken()); 58 if (apiClientHeaderValue.length() > 0) { 59 headersBuilder.put(builder.getApiClientHeaderKey(), apiClientHeaderValue.toString()); 60 } 61 } 62 63 if (builder.getResourceHeaderKey() != null && builder.getResourceToken() != null) { 64 headersBuilder.put(builder.getResourceHeaderKey(), builder.getResourceToken()); 65 } 66 67 if (builder.getQuotaProjectIdToken() != null) { 68 headersBuilder.put(QUOTA_PROJECT_ID_HEADER_KEY, builder.getQuotaProjectIdToken()); 69 } 70 71 this.headers = headersBuilder.build(); 72 } 73 74 @Override getHeaders()75 public Map<String, String> getHeaders() { 76 return headers; 77 } 78 appendToken(StringBuilder sb, String token)79 protected static void appendToken(StringBuilder sb, String token) { 80 if (token != null) { 81 if (sb.length() > 0) { 82 sb.append(' '); 83 } 84 sb.append(token); 85 } 86 } 87 newBuilder()88 public static Builder newBuilder() { 89 return new Builder(); 90 } 91 getDefaultApiClientHeaderKey()92 public static String getDefaultApiClientHeaderKey() { 93 return "x-goog-api-client"; 94 } 95 getDefaultResourceHeaderKey()96 public static String getDefaultResourceHeaderKey() { 97 return "google-cloud-resource-prefix"; 98 } 99 100 public static class Builder { 101 private String apiClientHeaderKey; 102 private String jvmToken; 103 private String clientLibToken; 104 private String generatedLibToken; 105 private String generatedRuntimeToken; 106 private String transportToken; 107 private String quotaProjectIdToken; 108 109 private String resourceHeaderKey; 110 private String resourceToken; 111 Builder()112 protected Builder() { 113 // Initialize with default values 114 apiClientHeaderKey = getDefaultApiClientHeaderKey(); 115 setJvmToken(GaxProperties.getJavaVersion()); 116 clientLibToken = null; 117 generatedLibToken = null; 118 setClientRuntimeToken(GaxProperties.getGaxVersion()); 119 transportToken = null; 120 quotaProjectIdToken = null; 121 122 resourceHeaderKey = getDefaultResourceHeaderKey(); 123 resourceToken = null; 124 } 125 getApiClientHeaderKey()126 public String getApiClientHeaderKey() { 127 return apiClientHeaderKey; 128 } 129 setApiClientHeaderKey(String apiClientHeaderKey)130 public Builder setApiClientHeaderKey(String apiClientHeaderKey) { 131 this.apiClientHeaderKey = apiClientHeaderKey; 132 return this; 133 } 134 getJvmToken()135 public String getJvmToken() { 136 return jvmToken; 137 } 138 setJvmToken(String version)139 public Builder setJvmToken(String version) { 140 this.jvmToken = constructToken("gl-java", version); 141 return this; 142 } 143 getClientLibToken()144 public String getClientLibToken() { 145 return clientLibToken; 146 } 147 setClientLibToken(String name, String version)148 public Builder setClientLibToken(String name, String version) { 149 this.clientLibToken = constructToken(name, version); 150 return this; 151 } 152 getGeneratedLibToken()153 public String getGeneratedLibToken() { 154 return generatedLibToken; 155 } 156 setGeneratedLibToken(String name, String version)157 public Builder setGeneratedLibToken(String name, String version) { 158 this.generatedLibToken = constructToken(name, version); 159 return this; 160 } 161 getGeneratedRuntimeToken()162 public String getGeneratedRuntimeToken() { 163 return generatedRuntimeToken; 164 } 165 setClientRuntimeToken(String version)166 public Builder setClientRuntimeToken(String version) { 167 this.generatedRuntimeToken = constructToken("gax", version); 168 return this; 169 } 170 getTransportToken()171 public String getTransportToken() { 172 return transportToken; 173 } 174 setTransportToken(String name, String version)175 public Builder setTransportToken(String name, String version) { 176 this.transportToken = constructToken(name, version); 177 return this; 178 } 179 180 /** @return the quotaProjectIdToken used for quota and billing purposes. */ getQuotaProjectIdToken()181 public String getQuotaProjectIdToken() { 182 return quotaProjectIdToken; 183 } 184 185 /** Sets the project ID used for quota and billing purposes. */ setQuotaProjectIdToken(String quotaProjectIdToken)186 public Builder setQuotaProjectIdToken(String quotaProjectIdToken) { 187 this.quotaProjectIdToken = quotaProjectIdToken; 188 return this; 189 } 190 getResourceHeaderKey()191 public String getResourceHeaderKey() { 192 return resourceHeaderKey; 193 } 194 setResourceHeaderKey(String resourceHeaderKey)195 public Builder setResourceHeaderKey(String resourceHeaderKey) { 196 this.resourceHeaderKey = resourceHeaderKey; 197 return this; 198 } 199 getResourceToken()200 public String getResourceToken() { 201 return resourceToken; 202 } 203 setResourceToken(String resourceToken)204 public Builder setResourceToken(String resourceToken) { 205 this.resourceToken = resourceToken; 206 return this; 207 } 208 constructToken(String name, String version)209 private String constructToken(String name, String version) { 210 if (version == null) { 211 return null; 212 } 213 if (name == null) { 214 throw new IllegalArgumentException("Token name cannot be null"); 215 } 216 return name + '/' + version; 217 } 218 build()219 public ApiClientHeaderProvider build() { 220 return new ApiClientHeaderProvider(this); 221 } 222 } 223 } 224