// Copyright 2012 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.api.ads.common.lib.useragent; import com.google.api.ads.adwords.lib.AdWordsPluginModule; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.inject.Inject; import java.util.List; import javax.annotation.Nullable; /** * Combines all user agents along with a user supplied string. */ public class UserAgentCombiner { private ImmutableList<UserAgentProvider> userAgentProviders; /** * Constructor that builds an instance based on a list of underlying user agent * providers. The {@code xyzHolder} parameters are for user agent providers that * may be null in certain contexts. * * @param productUserAgentProvider the product user agent library user agent provider * @param productFrameworkProviderHolder holder for the product/framework user agent * provider * @param adsLibraryUserAgentProvider the ads library user agent provider * @param frameworkProviderHolder holder for the framework user agent provider * @param runtimeUserAgentProvider the runtime user agent provider * @param buildTypeUserAgentProvider the build type user agent provider * @param extensionProviderHolder holder for the extension user agent provider */ @Inject public UserAgentCombiner(ProductUserAgentProvider productUserAgentProvider, ProductFrameworkProviderHolder productFrameworkProviderHolder, AdsLibraryUserAgentProvider adsLibraryUserAgentProvider, FrameworkProviderHolder frameworkProviderHolder, RuntimeUserAgentProvider runtimeUserAgentProvider, BuildTypeUserAgentProvider buildTypeUserAgentProvider, AdsUtilitiesUserAgentProvider adsUtilitiesUserAgentProvider, ExtensionProviderHolder extensionProviderHolder) { this( Lists.newArrayList( productUserAgentProvider, productFrameworkProviderHolder.value, adsLibraryUserAgentProvider, frameworkProviderHolder.value, runtimeUserAgentProvider, buildTypeUserAgentProvider, adsUtilitiesUserAgentProvider, extensionProviderHolder.value)); } /** * Constructor used for testing. * * @param userAgentProviders the user agent providers * utilities agent provider */ @VisibleForTesting UserAgentCombiner( List<UserAgentProvider> userAgentProviders) { // Remove any nulls from the list, since ImmutableList does not support null entries. this.userAgentProviders = ImmutableList.<UserAgentProvider>copyOf( Collections2.filter(userAgentProviders, Predicates.notNull())); } /** * Gets the full user agent in the form of * {@code "(UserAgent1,UserAgent2,UserAgent3,...)"} */ public String getUserAgent(String nonLibraryUserAgent) { StringBuilder agentStringBuilder = new StringBuilder(); agentStringBuilder.append(nonLibraryUserAgent); agentStringBuilder.append(" ("); agentStringBuilder.append(Joiner.on(", ").skipNulls().join( Iterables.transform(userAgentProviders, new Function<UserAgentProvider, String>() { @Override public String apply(@Nullable UserAgentProvider input) { return input == null ? null : input.getUserAgent(); }}))); agentStringBuilder.append(')'); return agentStringBuilder.toString(); } /** * Holder that allows for <em>optional</em> injection of a {@link * ProductFrameworkUserAgentProvider}. * This is necessary because UserAgentCombiner instances are used in multiple contexts, some of * which do not have an associated SOAP toolkit. In such cases, the {@code value} will be null. */ static class ProductFrameworkProviderHolder { @Inject(optional = true) ProductFrameworkUserAgentProvider value; } /** * Holder that allows for <em>optional</em> injection of a {@link FrameworkUserAgentProvider}. * This is necessary because UserAgentCombiner instances are used in multiple contexts, some of * which do not have an associated SOAP toolkit. In such cases, the {@code value} will be null. */ static class FrameworkProviderHolder { @Inject(optional = true) FrameworkUserAgentProvider value; } /** * Holder that allows for <em>optional</em> injection of a {@link ExtensionUserAgentProvider}. * This is necessary because the {@link ExtensionUserAgentProvider} type will only be bound if an * extension or application provided an {@link AdWordsPluginModule} to the Guice injector. * Otherwise, the {@code value} will be null. */ static class ExtensionProviderHolder { @Inject(optional = true) ExtensionUserAgentProvider value; } }