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; this.args = args;
} }
@Override
public String toString() {
return "[class=" + asyncClass.getSimpleName() + ", method=" + method.getName() + ", args="
+ Arrays.toString(args) + "]";
}
public Method getMethod() { public Method getMethod() {
return method; return method;
} }

View File

@ -42,6 +42,10 @@ public class AuthorizationException extends RuntimeException {
super(String.format("%s -> %s", resource.getRequestLine(), error)); 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) { public AuthorizationException(Throwable arg0) {
super(arg0); super(arg0);
} }

View File

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

View File

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

View File

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