// Copyright 2016 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.adwords.extension.ratelimiter;
import com.google.api.ads.adwords.lib.AdWordsPluginModule;
import com.google.api.ads.adwords.lib.client.AdWordsSession;
import com.google.api.ads.adwords.lib.factory.AdWordsServicesInterface;
import com.google.common.reflect.Reflection;
import java.lang.reflect.InvocationHandler;
/** An AdWordsServices with built-in rate limit handling logic. */
public class AdWordsServicesWithRateLimiter implements AdWordsServicesInterface {
private final AdWordsServicesInterface adWordsServices;
public AdWordsServicesWithRateLimiter(AdWordsServicesInterface adwordsServices) {
this.adWordsServices =
adwordsServices.withPluginModule(
new AdWordsPluginModule(new RateLimiterUserAgentProvider()));
}
/**
* Gets a rate-limit-aware client for the service represented by the interface with a reference to
* the session.
*
* <p>The objects returned by this method are not thread-safe.
*
* @param <T> the service type
* @param session your current session
* @param interfaceClass the service interface class. This is a class representing a SOAP service
* @return the rate-limit-aware client for the service
*/
@Override
public <T> T get(AdWordsSession session, Class<T> interfaceClass) {
T originalInterfaceObject = adWordsServices.get(session, interfaceClass);
return getProxyObject(originalInterfaceObject, session, interfaceClass, false);
}
/**
* Gets a rate-limit-aware instance of the utility represented by the utilityClass with a
* reference to the session.
*
* <p>The objects returned by this method are not thread-safe.
*
* @param <T> the service type
* @param session your current session
* @param utilityClass the AdWords utility class
* @return the rate-limit-aware client for the utility
*/
@Override
public <T> T getUtility(AdWordsSession session, Class<T> utilityClass) {
T originalUtilityObject = adWordsServices.getUtility(session, utilityClass);
return getProxyObject(originalUtilityObject, session, utilityClass, true);
}
/**
* Decide whether this RateLimiter extension is applicable to the original service / utility
* object. If so, wrap it in a proxy object with rate-limit-aware invocation handle; if not, just
* return the original object.
*/
private <T> T getProxyObject(
T originalObject, AdWordsSession session, Class<T> cls, boolean isUtility) {
// Find the retry strategy of this class type.
ApiRetryStrategy retryStrategy =
ApiRetryStrategyManager.getRetryStrategy(cls.getSimpleName(), isUtility);
// If no corresponding retry strategy, just use the original object instead of a wrapping proxy.
if (retryStrategy == null) {
return originalObject;
}
InvocationHandler invocationHandler =
new ApiInvocationHandlerWithRateLimiter(originalObject, session, retryStrategy);
return Reflection.newProxy(cls, invocationHandler);
}
@Override
public AdWordsServicesInterface withPluginModule(AdWordsPluginModule pluginModule) {
throw new UnsupportedOperationException(
"This AdWordsServices is already configured with an AdWordsPluginModule");
}
}