fixed conflict where multiple classes with the same method name and args tripped over themselves. enhanced trace logging and authz exception

This commit is contained in:
Adrian Cole 2010-07-21 15:25:22 -07:00
parent 9bffee1135
commit 13fa341a0e
5 changed files with 213 additions and 131 deletions

View File

@ -40,6 +40,12 @@ public class ClassMethodArgs {
this.args = args;
}
@Override
public String toString() {
return "[class=" + asyncClass.getSimpleName() + ", method=" + method.getName() + ", args="
+ Arrays.toString(args) + "]";
}
public Method getMethod() {
return method;
}

View File

@ -42,6 +42,10 @@ public class AuthorizationException extends RuntimeException {
super(String.format("%s -> %s", resource.getRequestLine(), error));
}
public AuthorizationException(HttpRequest resource, String error, Throwable arg1) {
super(String.format("%s -> %s", resource.getRequestLine(), error), arg1);
}
public AuthorizationException(Throwable arg0) {
super(arg0);
}

View File

@ -39,7 +39,8 @@ import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
/**
* Helper class to instantiate {@code RestContext} instances. "blobstore.properties"
* Helper class to instantiate {@code RestContext} instances.
* "blobstore.properties"
*
* At least one property is needed needed per context:
* <ul>
@ -62,18 +63,16 @@ import com.google.inject.Module;
*/
public class RestContextFactory {
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint,
String apiVersion, String identity, String credential, Class<S> sync, Class<A> async,
Class<PropertiesBuilder> propertiesBuilderClass,
Class<RestContextBuilder<S, A>> contextBuilderClass) {
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync,
async, propertiesBuilderClass, contextBuilderClass);
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
String identity, String credential, Class<S> sync, Class<A> async,
Class<PropertiesBuilder> propertiesBuilderClass, Class<RestContextBuilder<S, A>> contextBuilderClass) {
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async,
propertiesBuilderClass, contextBuilderClass);
}
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint,
String apiVersion, String identity, String credential, Class<S> sync, Class<A> async) {
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync,
async);
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
String identity, String credential, Class<S> sync, Class<A> async) {
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async);
}
public static class ContextSpec<S, A> {
@ -87,9 +86,8 @@ public class RestContextFactory {
final Class<PropertiesBuilder> propertiesBuilderClass;
final Class<RestContextBuilder<S, A>> contextBuilderClass;
ContextSpec(String provider, String endpoint, String apiVersion, String identity,
String credential, Class<S> sync, Class<A> async,
Class<PropertiesBuilder> propertiesBuilderClass,
ContextSpec(String provider, String endpoint, String apiVersion, String identity, String credential,
Class<S> sync, Class<A> async, Class<PropertiesBuilder> propertiesBuilderClass,
Class<RestContextBuilder<S, A>> contextBuilderClass) {
this.provider = checkNotNull(provider, "provider");
this.endpoint = endpoint;
@ -98,21 +96,99 @@ public class RestContextFactory {
this.credential = credential;
this.sync = sync;
this.async = async;
checkArgument(RestContextBuilder.class.isAssignableFrom(contextBuilderClass),
contextBuilderClass.getName() + " is not a subclass of "
+ RestContextBuilder.class.getName());
checkArgument(PropertiesBuilder.class.isAssignableFrom(propertiesBuilderClass),
propertiesBuilderClass.getName() + " is not a subclass of "
+ PropertiesBuilder.class.getName());
checkArgument(RestContextBuilder.class.isAssignableFrom(contextBuilderClass), contextBuilderClass.getName()
+ " is not a subclass of " + RestContextBuilder.class.getName());
checkArgument(PropertiesBuilder.class.isAssignableFrom(propertiesBuilderClass), propertiesBuilderClass
.getName()
+ " is not a subclass of " + PropertiesBuilder.class.getName());
this.propertiesBuilderClass = propertiesBuilderClass;
this.contextBuilderClass = contextBuilderClass;
}
@SuppressWarnings("unchecked")
public ContextSpec(String provider, String endpoint, String apiVersion, String identity,
String credential, Class<S> sync, Class<A> async) {
this(provider, endpoint, apiVersion, identity, credential, sync, async,
PropertiesBuilder.class, (Class) RestContextBuilder.class);
public ContextSpec(String provider, String endpoint, String apiVersion, String identity, String credential,
Class<S> sync, Class<A> async) {
this(provider, endpoint, apiVersion, identity, credential, sync, async, PropertiesBuilder.class,
(Class) RestContextBuilder.class);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((apiVersion == null) ? 0 : apiVersion.hashCode());
result = prime * result + ((async == null) ? 0 : async.hashCode());
result = prime * result + ((contextBuilderClass == null) ? 0 : contextBuilderClass.hashCode());
result = prime * result + ((credential == null) ? 0 : credential.hashCode());
result = prime * result + ((endpoint == null) ? 0 : endpoint.hashCode());
result = prime * result + ((identity == null) ? 0 : identity.hashCode());
result = prime * result + ((propertiesBuilderClass == null) ? 0 : propertiesBuilderClass.hashCode());
result = prime * result + ((provider == null) ? 0 : provider.hashCode());
result = prime * result + ((sync == null) ? 0 : sync.hashCode());
return result;
}
@Override
public String toString() {
return "[provider=" + provider + ", endpoint=" + endpoint + ", apiVersion=" + apiVersion + ", identity="
+ identity + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ContextSpec<?, ?> other = (ContextSpec<?, ?>) obj;
if (apiVersion == null) {
if (other.apiVersion != null)
return false;
} else if (!apiVersion.equals(other.apiVersion))
return false;
if (async == null) {
if (other.async != null)
return false;
} else if (!async.equals(other.async))
return false;
if (contextBuilderClass == null) {
if (other.contextBuilderClass != null)
return false;
} else if (!contextBuilderClass.equals(other.contextBuilderClass))
return false;
if (credential == null) {
if (other.credential != null)
return false;
} else if (!credential.equals(other.credential))
return false;
if (endpoint == null) {
if (other.endpoint != null)
return false;
} else if (!endpoint.equals(other.endpoint))
return false;
if (identity == null) {
if (other.identity != null)
return false;
} else if (!identity.equals(other.identity))
return false;
if (propertiesBuilderClass == null) {
if (other.propertiesBuilderClass != null)
return false;
} else if (!propertiesBuilderClass.equals(other.propertiesBuilderClass))
return false;
if (provider == null) {
if (other.provider != null)
return false;
} else if (!provider.equals(other.provider))
return false;
if (sync == null) {
if (other.sync != null)
return false;
} else if (!sync.equals(other.sync))
return false;
return true;
}
}
@ -120,8 +196,8 @@ public class RestContextFactory {
private final Properties properties;
/**
* Initializes with the default properties built-in to jclouds. This is typically stored in the
* classpath resource {@code rest.properties}
* Initializes with the default properties built-in to jclouds. This is
* typically stored in the classpath resource {@code rest.properties}
*
* @see RestContextFactory#getPropertiesFromResource
*/
@ -130,8 +206,8 @@ public class RestContextFactory {
}
/**
* Initializes with the default properties built-in to jclouds. This is typically stored in the
* classpath resource {@code filename}
* Initializes with the default properties built-in to jclouds. This is
* typically stored in the classpath resource {@code filename}
*
* @param filename
* name of the properties file to initialize from
@ -144,8 +220,8 @@ public class RestContextFactory {
}
/**
* Loads the default properties that define the {@code RestContext} objects. <h3>properties file
* format</h3>
* Loads the default properties that define the {@code RestContext} objects.
* <h3>properties file format</h3>
*
* Two properties are needed per context:
* <ul>
@ -175,22 +251,21 @@ public class RestContextFactory {
}
/**
* Initializes the {@code RestContext} definitions from the specified properties.
* Initializes the {@code RestContext} definitions from the specified
* properties.
*/
@Inject
public RestContextFactory(Properties properties) {
this.properties = properties;
}
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, String identity,
String credential) {
return createContextBuilder(provider, identity, credential, ImmutableSet.<Module> of(),
NO_PROPERTIES);
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, String identity, String credential) {
return createContextBuilder(provider, identity, credential, ImmutableSet.<Module> of(), NO_PROPERTIES);
}
/**
* @see RestContextFactory#createContextBuilder(String, Properties, Iterable<? extends Module>,
* Properties)
* @see RestContextFactory#createContextBuilder(String, Properties,
* Iterable<? extends Module>, Properties)
*/
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Properties overrides) {
return createContextBuilder(provider, overrides.getProperty("jclouds.identity"), overrides
@ -199,32 +274,32 @@ public class RestContextFactory {
/**
*
* Identity will be found by searching {@code jclouds.identity} failing that {@code
* provider.identity} where provider corresponds to the parameter. Same pattern is used for
* credential ({@code jclouds.credential} failing that {@code provider.credential}).
* Identity will be found by searching {@code jclouds.identity} failing that
* {@code provider.identity} where provider corresponds to the parameter.
* Same pattern is used for credential ({@code jclouds.credential} failing
* that {@code provider.credential}).
*
* @param <S>
* Type of the provider specific client
* @param <A>
* Type of the provide specific async client (same as above, yet all methods return
* {@code Future} results)
* Type of the provide specific async client (same as above, yet
* all methods return {@code Future} results)
* @param provider
* name of the provider (ex. s3, bluelock, etc.)
* @param wiring
* defines how objects are bound to interfaces, pass in here to override this, or
* specify service implementations.
* defines how objects are bound to interfaces, pass in here to
* override this, or specify service implementations.
* @param overrides
* properties to pass to the context.
*/
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider,
Iterable<? extends Module> wiring, Properties overrides) {
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Iterable<? extends Module> wiring,
Properties overrides) {
return createContextBuilder(provider, overrides.getProperty("jclouds.identity"), overrides
.getProperty("jclouds.credential"), wiring, overrides);
}
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider,
@Nullable String identity, @Nullable String credential,
Iterable<? extends Module> wiring) {
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, @Nullable String identity,
@Nullable String credential, Iterable<? extends Module> wiring) {
return createContextBuilder(provider, identity, credential, wiring, new Properties());
}
@ -237,18 +312,16 @@ public class RestContextFactory {
* @param credential
* nullable, if credentials are present in the overrides
* @param wiring
* Configuration you'd like to pass to the context. Ex. ImmutableSet.<Module>of(new
* ExecutorServiceModule(myexecutor))
* Configuration you'd like to pass to the context. Ex.
* ImmutableSet.<Module>of(new ExecutorServiceModule(myexecutor))
* @param overrides
* properties to override defaults with.
* @return initialized context ready for use
*/
public <S, A> RestContextBuilder<S, A> createContextBuilder(String providerName,
@Nullable String identity, @Nullable String credential,
Iterable<? extends Module> wiring, Properties _overrides) {
public <S, A> RestContextBuilder<S, A> createContextBuilder(String providerName, @Nullable String identity,
@Nullable String credential, Iterable<? extends Module> wiring, Properties _overrides) {
checkNotNull(wiring, "wiring");
ContextSpec<S, A> contextSpec = createContextSpec(providerName, identity, credential,
_overrides);
ContextSpec<S, A> contextSpec = createContextSpec(providerName, identity, credential, _overrides);
return createContextBuilder(contextSpec, wiring, _overrides);
}
@ -264,23 +337,22 @@ public class RestContextFactory {
props.setProperty(contextSpec.provider + ".credential", contextSpec.credential);
if (contextSpec.sync != null) {
props.setProperty(contextSpec.provider + ".sync", contextSpec.sync.getName());
props.setProperty(contextSpec.provider + ".async", checkNotNull(contextSpec.async,
"contextSpec.async").getName());
props.setProperty(contextSpec.provider + ".async", checkNotNull(contextSpec.async, "contextSpec.async")
.getName());
} else {
props.setProperty(contextSpec.provider + ".contextbuilder", checkNotNull(
contextSpec.contextBuilderClass, "contextSpec.contextBuilderClass").getName());
props.setProperty(contextSpec.provider + ".contextbuilder", checkNotNull(contextSpec.contextBuilderClass,
"contextSpec.contextBuilderClass").getName());
props.setProperty(contextSpec.provider + ".propertiesbuilder", checkNotNull(
contextSpec.propertiesBuilderClass, "contextSpec.propertiesBuilderClass")
.getName());
contextSpec.propertiesBuilderClass, "contextSpec.propertiesBuilderClass").getName());
}
return props;
}
@SuppressWarnings("unchecked")
public <A, S> ContextSpec<S, A> createContextSpec(String providerName, String identity,
String credential, Properties _overrides) {
public <A, S> ContextSpec<S, A> createContextSpec(String providerName, String identity, String credential,
Properties _overrides) {
checkNotNull(providerName, "providerName");
checkNotNull(_overrides, "overrides");
@ -310,8 +382,8 @@ public class RestContextFactory {
return null;
}
ContextSpec<S, A> contextSpec = new ContextSpec<S, A>(providerName, endpoint, apiVersion,
identity, credential, sync, async, propertiesBuilderClass, contextBuilderClass);
ContextSpec<S, A> contextSpec = new ContextSpec<S, A>(providerName, endpoint, apiVersion, identity, credential,
sync, async, propertiesBuilderClass, contextBuilderClass);
return contextSpec;
}
@ -319,21 +391,21 @@ public class RestContextFactory {
return createContextBuilder(contextSpec, new Properties());
}
public static <S, A> RestContextBuilder<S, A> createContextBuilder(
ContextSpec<S, A> contextSpec, Properties overrides) {
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
Properties overrides) {
return createContextBuilder(contextSpec, ImmutableSet.<Module> of(), overrides);
}
public static <S, A> RestContextBuilder<S, A> createContextBuilder(
ContextSpec<S, A> contextSpec, Iterable<? extends Module> wiring) {
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
Iterable<? extends Module> wiring) {
return createContextBuilder(contextSpec, wiring, new Properties());
}
public static <S, A> RestContextBuilder<S, A> createContextBuilder(
ContextSpec<S, A> contextSpec, Iterable<? extends Module> wiring, Properties overrides) {
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
Iterable<? extends Module> wiring, Properties overrides) {
try {
PropertiesBuilder builder = contextSpec.propertiesBuilderClass.getConstructor(
Properties.class).newInstance(overrides);
PropertiesBuilder builder = contextSpec.propertiesBuilderClass.getConstructor(Properties.class).newInstance(
overrides);
builder.provider(contextSpec.provider);
if (contextSpec.apiVersion != null)
@ -343,9 +415,8 @@ public class RestContextFactory {
if (contextSpec.endpoint != null)
builder.endpoint(contextSpec.endpoint);
RestContextBuilder<S, A> contextBuilder = initContextBuilder(
contextSpec.contextBuilderClass, contextSpec.sync, contextSpec.async, builder
.build());
RestContextBuilder<S, A> contextBuilder = initContextBuilder(contextSpec.contextBuilderClass,
contextSpec.sync, contextSpec.async, builder.build());
contextBuilder.withModules(toArray(wiring, Module.class));
@ -363,8 +434,7 @@ public class RestContextFactory {
return buildContextUnwrappingExceptions(builder);
}
public static <S, A> RestContext<S, A> buildContextUnwrappingExceptions(
RestContextBuilder<S, A> builder) {
public static <S, A> RestContext<S, A> buildContextUnwrappingExceptions(RestContextBuilder<S, A> builder) {
try {
return builder.buildContext();
} catch (Exception e) {
@ -383,34 +453,35 @@ public class RestContextFactory {
/**
* @see RestContextFactory#createContextBuilder(String, Iterable)
*/
public <S, A> RestContext<S, A> createContext(String provider,
Iterable<? extends Module> wiring, Properties overrides) {
public <S, A> RestContext<S, A> createContext(String provider, Iterable<? extends Module> wiring,
Properties overrides) {
RestContextBuilder<S, A> builder = createContextBuilder(provider, wiring, overrides);
return buildContextUnwrappingExceptions(builder);
}
/**
* @see RestContextFactory#createContextBuilder(String, String,String, Iterable)
* @see RestContextFactory#createContextBuilder(String, String,String,
* Iterable)
*/
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
@Nullable String credential, Iterable<? extends Module> wiring) {
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential,
wiring);
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, wiring);
return buildContextUnwrappingExceptions(builder);
}
/**
* @see RestContextFactory#createContextBuilder(String, String,String, Iterable, Properties)
* @see RestContextFactory#createContextBuilder(String, String,String,
* Iterable, Properties)
*/
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
@Nullable String credential, Iterable<? extends Module> wiring, Properties overrides) {
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential,
wiring, overrides);
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, wiring, overrides);
return buildContextUnwrappingExceptions(builder);
}
/**
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable, Properties)
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable,
* Properties)
*/
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec,
Iterable<? extends Module> wiring, Properties overrides) {
@ -429,8 +500,7 @@ public class RestContextFactory {
/**
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable)
*/
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec,
Iterable<? extends Module> wiring) {
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec, Iterable<? extends Module> wiring) {
RestContextBuilder<S, A> builder = createContextBuilder(contextSpec, wiring);
return buildContextUnwrappingExceptions(builder);
}
@ -438,8 +508,7 @@ public class RestContextFactory {
/**
* @see RestContextFactory#createContextBuilder(ContextSpec, Properties)
*/
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec,
Properties overrides) {
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec, Properties overrides) {
RestContextBuilder<S, A> builder = createContextBuilder(contextSpec, overrides);
return buildContextUnwrappingExceptions(builder);
}

View File

@ -69,9 +69,8 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
@SuppressWarnings("unchecked")
@Inject
public AsyncRestClientProxy(Injector injector, Factory factory,
RestAnnotationProcessor<T> util, TypeLiteral<T> typeLiteral,
@Named("async") ConcurrentMap<ClassMethodArgs, Object> delegateMap) {
public AsyncRestClientProxy(Injector injector, Factory factory, RestAnnotationProcessor<T> util,
TypeLiteral<T> typeLiteral, @Named("async") ConcurrentMap<ClassMethodArgs, Object> delegateMap) {
this.injector = injector;
this.annotationProcessor = util;
this.declaring = (Class<T>) typeLiteral.getRawType();
@ -79,8 +78,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
this.delegateMap = delegateMap;
}
public Object invoke(Object o, Method method, Object[] args)
throws Throwable {
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if (method.getName().equals("equals")) {
return this.equals(o);
} else if (method.getName().equals("toString")) {
@ -90,23 +88,19 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
} else if (method.getName().startsWith("new")) {
return injector.getInstance(method.getReturnType());
} else if (method.isAnnotationPresent(Delegate.class)) {
return delegateMap.get(new ClassMethodArgs(method.getReturnType(),
method, args));
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
} else if (annotationProcessor.getDelegateOrNull(method) != null
&& ListenableFuture.class.isAssignableFrom(method.getReturnType())) {
return createFuture(method, args);
} else {
throw new RuntimeException(
"method is intended solely to set constants: " + method);
throw new RuntimeException("method is intended solely to set constants: " + method);
}
}
@SuppressWarnings("unchecked")
private ListenableFuture<?> createFuture(Method method, Object[] args)
throws ExecutionException {
private ListenableFuture<?> createFuture(Method method, Object[] args) throws ExecutionException {
method = annotationProcessor.getDelegateOrNull(method);
logger.trace("Converting %s.%s", declaring.getSimpleName(), method
.getName());
logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName());
Function<Exception, ?> exceptionParser = annotationProcessor
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method);
// in case there is an exception creating the request, we should at least
@ -118,8 +112,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
try {
request = annotationProcessor.createRequest(method, args);
if (exceptionParser instanceof InvocationContext) {
((InvocationContext) exceptionParser)
.setContext((GeneratedHttpRequest<T>) request);
((InvocationContext) exceptionParser).setContext((GeneratedHttpRequest<T>) request);
}
} catch (RuntimeException e) {
if (exceptionParser != null) {
@ -131,32 +124,25 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
}
return Futures.immediateFailedFuture(e);
}
logger.trace("Converted %s.%s to %s", declaring.getSimpleName(), method
.getName(), request.getRequestLine());
logger.trace("Converted %s.%s to %s", declaring.getSimpleName(), method.getName(), request.getRequestLine());
Function<HttpResponse, ?> transformer = annotationProcessor
.createResponseParser(method, request);
logger.trace("Response from %s.%s is parsed by %s", declaring
.getSimpleName(), method.getName(), transformer.getClass()
.getSimpleName());
Function<HttpResponse, ?> transformer = annotationProcessor.createResponseParser(method, request);
logger.trace("Response from %s.%s is parsed by %s", declaring.getSimpleName(), method.getName(), transformer
.getClass().getSimpleName());
logger.debug("Invoking %s.%s", declaring.getSimpleName(), method
.getName());
ListenableFuture<?> result = commandFactory.create(request, transformer)
.execute();
logger.debug("Invoking %s.%s", declaring.getSimpleName(), method.getName());
ListenableFuture<?> result = commandFactory.create(request, transformer).execute();
if (exceptionParser != null) {
logger.trace("Exceptions from %s.%s are parsed by %s", declaring
.getSimpleName(), method.getName(), exceptionParser.getClass()
.getSimpleName());
logger.trace("Exceptions from %s.%s are parsed by %s", declaring.getSimpleName(), method.getName(),
exceptionParser.getClass().getSimpleName());
result = new FutureExceptionParser(result, exceptionParser);
}
return result;
}
public static interface Factory {
public TransformingHttpCommand<?> create(HttpRequest request,
Function<HttpResponse, ?> transformer);
public TransformingHttpCommand<?> create(HttpRequest request, Function<HttpResponse, ?> transformer);
}
@Override

View File

@ -321,6 +321,7 @@ public class RestAnnotationProcessor<T> {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((declaringPackage == null) ? 0 : declaringPackage.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + parameterCount;
return result;
@ -335,6 +336,11 @@ public class RestAnnotationProcessor<T> {
if (getClass() != obj.getClass())
return false;
MethodKey other = (MethodKey) obj;
if (declaringPackage == null) {
if (other.declaringPackage != null)
return false;
} else if (!declaringPackage.equals(other.declaringPackage))
return false;
if (name == null) {
if (other.name != null)
return false;
@ -347,9 +353,11 @@ public class RestAnnotationProcessor<T> {
private final String name;
private final int parameterCount;
private final Package declaringPackage;
public MethodKey(Method method) {
this.name = method.getName();
this.declaringPackage = method.getDeclaringClass().getPackage();
this.parameterCount = method.getParameterTypes().length;
}
@ -371,14 +379,23 @@ public class RestAnnotationProcessor<T> {
public GeneratedHttpRequest<T> createRequest(Method method, Object... args) {
inputParamValidator.validateMethodParametersOrThrow(method, args);
URI endpoint = callerEndpoint;
ClassMethodArgs cma = logger.isTraceEnabled() ? new ClassMethodArgs(method.getDeclaringClass(), method, args)
: null;
URI endpoint = callerEndpoint;
try {
if (endpoint == null)
if (endpoint == null) {
endpoint = getEndpointFor(method, args, injector);
} catch (IllegalStateException e) {
endpoint = injector.getInstance(Key.get(URI.class, org.jclouds.rest.annotations.Provider.class));
logger.trace("using endpoint %s for %s", endpoint, cma);
} else {
logger.trace("using endpoint %s from caller %s for %s", caller, endpoint, cma);
}
} catch (IllegalStateException e) {
logger.trace("looking up default endpoint for %s", cma);
endpoint = injector.getInstance(Key.get(URI.class, org.jclouds.rest.annotations.Provider.class));
logger.trace("using default endpoint %s for %s", endpoint, cma);
}
String httpMethod = getHttpMethodOrConstantOrThrowException(method);
UriBuilder builder = uriBuilderProvider.get().uri(endpoint);