|
35 | 35 | import com.google.api.client.util.Strings; |
36 | 36 | import com.google.api.core.ApiClock; |
37 | 37 | import com.google.api.core.BetaApi; |
| 38 | +import com.google.api.core.InternalApi; |
38 | 39 | import com.google.api.core.NanoClock; |
39 | 40 | import com.google.api.core.ObsoleteApi; |
40 | 41 | import com.google.api.gax.core.BackgroundResource; |
@@ -292,6 +293,80 @@ public static ClientContext create(StubSettings settings) throws IOException { |
292 | 293 | .build(); |
293 | 294 | } |
294 | 295 |
|
| 296 | + /** |
| 297 | + * Derives a {@link ClientContext} for a second transport from {@code parent}, replacing the |
| 298 | + * transport channel, endpoint and internal headers and inheriting everything else. |
| 299 | + */ |
| 300 | + @InternalApi |
| 301 | + public static ClientContext createWithTransport( |
| 302 | + ClientContext parent, |
| 303 | + String endpoint, |
| 304 | + TransportChannelProvider transportChannelProvider, |
| 305 | + HeaderProvider internalHeaderProvider) |
| 306 | + throws IOException { |
| 307 | + Credentials credentials = parent.getCredentials(); |
| 308 | + EndpointContext endpointContext = parent.getEndpointContext(); |
| 309 | + |
| 310 | + Map<String, String> internal = internalHeaderProvider.getHeaders(); |
| 311 | + Map<String, String> user = parent.getHeaders(); |
| 312 | + Map<String, String> conflictResolution = new HashMap<>(); |
| 313 | + |
| 314 | + for (String key : Sets.intersection(user.keySet(), internal.keySet())) { |
| 315 | + if ("user-agent".equals(key)) { |
| 316 | + conflictResolution.put(key, user.get(key) + " " + internal.get(key)); |
| 317 | + continue; |
| 318 | + } |
| 319 | + if (QUOTA_PROJECT_ID_HEADER_KEY.equals(key) && parent.getQuotaProjectId() != null) { |
| 320 | + continue; |
| 321 | + } |
| 322 | + throw new IllegalArgumentException("Header provider can't override the header: " + key); |
| 323 | + } |
| 324 | + if (parent.getQuotaProjectId() != null) { |
| 325 | + conflictResolution.put(QUOTA_PROJECT_ID_HEADER_KEY, parent.getQuotaProjectId()); |
| 326 | + } |
| 327 | + |
| 328 | + Map<String, String> effective = new HashMap<>(); |
| 329 | + effective.putAll(internal); |
| 330 | + effective.putAll(user); |
| 331 | + effective.putAll(conflictResolution); |
| 332 | + Map<String, String> headers = appendCredentialTypeToHeaderIfPresent(effective, credentials); |
| 333 | + |
| 334 | + TransportChannelProvider provider = transportChannelProvider; |
| 335 | + if (provider.needsHeaders()) { |
| 336 | + provider = provider.withHeaders(headers); |
| 337 | + } |
| 338 | + if (provider.needsCredentials() && credentials != null) { |
| 339 | + provider = provider.withCredentials(credentials); |
| 340 | + } |
| 341 | + if (provider.needsEndpoint()) { |
| 342 | + provider = provider.withEndpoint(endpoint); |
| 343 | + } |
| 344 | + provider = provider.withUseS2A(endpointContext.useS2A()); |
| 345 | + if (provider.needsMtlsEndpoint() && endpointContext.mtlsEndpoint() != null) { |
| 346 | + provider = provider.withMtlsEndpoint(endpointContext.mtlsEndpoint()); |
| 347 | + } |
| 348 | + TransportChannel channel = provider.getTransportChannel(); |
| 349 | + |
| 350 | + ApiCallContext defaultCallContext = channel.getEmptyCallContext().withTransportChannel(channel); |
| 351 | + if (credentials != null) { |
| 352 | + defaultCallContext = defaultCallContext.withCredentials(credentials); |
| 353 | + } |
| 354 | + defaultCallContext = defaultCallContext.withEndpointContext(endpointContext); |
| 355 | + |
| 356 | + ImmutableList.Builder<BackgroundResource> backgroundResources = ImmutableList.builder(); |
| 357 | + if (provider.shouldAutoClose()) { |
| 358 | + backgroundResources.add(channel); |
| 359 | + } |
| 360 | + |
| 361 | + return parent.toBuilder() |
| 362 | + .setEndpoint(endpoint) |
| 363 | + .setTransportChannel(channel) |
| 364 | + .setInternalHeaders(ImmutableMap.copyOf(internal)) |
| 365 | + .setDefaultCallContext(defaultCallContext) |
| 366 | + .setBackgroundResources(backgroundResources.build()) |
| 367 | + .build(); |
| 368 | + } |
| 369 | + |
295 | 370 | @VisibleForTesting |
296 | 371 | static ApiTracerFactory getApiTracerFactory( |
297 | 372 | StubSettings settings, EndpointContext endpointContext) { |
|
0 commit comments