updated to employ Reflection.newProxy + AbstractInvocationHandler

This commit is contained in:
Adrian Cole 2012-12-02 12:27:57 -08:00
parent 4d2124bada
commit c30fedec20
9 changed files with 31 additions and 94 deletions

View File

@ -62,11 +62,11 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
org.jclouds.openstack.v2_0.services.Extension.class));
if (ext.isPresent()) {
URI namespace = URI.create(ext.get().namespace());
if (input.getArgs() == null || input.getArgs().length == 0) {
if (input.getArgs().length == 0) {
if (Iterables.any(extensions.getUnchecked(""),
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
return Optional.of(input.getReturnVal());
} else if (input.getArgs() != null && input.getArgs().length == 1) {
} else if (input.getArgs().length == 1) {
if (Iterables.any(extensions.getUnchecked(checkNotNull(input.getArgs()[0], "arg[0] in %s", input).toString()),
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
return Optional.of(input.getReturnVal());

View File

@ -63,7 +63,7 @@ public abstract class CallerArg0ToPagedIterable<T, I extends CallerArg0ToPagedIt
return PagedIterables.of(input);
Optional<String> arg0Option = Optional.absent();
if (request.getCaller().get().getArgs() != null && request.getCaller().get().getArgs().length > 0) {
if (request.getCaller().get().getArgs().length > 0) {
Object arg0 = request.getCaller().get().getArgs()[0];
if (arg0 != null)
arg0Option = Optional.of(arg0.toString());

View File

@ -19,11 +19,10 @@
package org.jclouds.concurrent.internal;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.reflect.Reflection.newProxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
@ -46,6 +45,7 @@ import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.AbstractInvocationHandler;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.ProvisionException;
@ -54,15 +54,13 @@ import com.google.inject.ProvisionException;
*
* @author Adrian Cole
*/
public class SyncProxy implements InvocationHandler {
public class SyncProxy extends AbstractInvocationHandler {
@SuppressWarnings("unchecked")
public static <T> T proxy(Function<ClassMethodArgsAndReturnVal, Optional<Object>> optionalConverter, Class<T> clazz, Object async,
@Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap,
Map<Class<?>, Class<?>> sync2Async, Map<String, Long> timeouts) throws IllegalArgumentException, SecurityException,
NoSuchMethodException {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz },
new SyncProxy(optionalConverter, clazz, async, delegateMap, sync2Async, timeouts));
return newProxy(clazz, new SyncProxy(optionalConverter, clazz, async, delegateMap, sync2Async, timeouts));
}
private final Function<ClassMethodArgsAndReturnVal, Optional<Object>> optionalConverter;
@ -134,14 +132,9 @@ public class SyncProxy implements InvocationHandler {
return methodNanos;
}
public Object invoke(Object o, Method method, Object[] args) throws Exception {
if (method.getName().equals("equals")) {
return this.equals(o);
} else if (method.getName().equals("hashCode")) {
return this.hashCode();
} else if (method.getName().equals("toString")) {
return this.toString();
} else if (method.isAnnotationPresent(Delegate.class)) {
@Override
protected Object handleInvocation(Object o, Method method, Object[] args) throws Exception {
if (method.isAnnotationPresent(Delegate.class)) {
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(method);
// get the return type of the asynchronous class associated with this client
// ex. FloatingIPClient is associated with FloatingIPAsyncClient
@ -191,24 +184,8 @@ public class SyncProxy implements InvocationHandler {
}
return timeout != null ? TimeUnit.MILLISECONDS.toNanos(timeout) : null;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof SyncProxy))
return false;
SyncProxy other = (SyncProxy) obj;
if (other == this)
return true;
if (other.declaring != this.declaring)
return false;
return super.equals(obj);
}
@Override
public int hashCode() {
return declaring.hashCode();
}
public String toString() {
return "Sync Proxy for: " + delegate.getClass().getSimpleName();
}

View File

@ -24,8 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -48,7 +46,7 @@ public class ClassMethodArgs {
public abstract static class Builder<B extends Builder<B>> {
private Class<?> clazz;
private Method method;
private Object[] args;
private Object[] args = {};
@SuppressWarnings("unchecked")
protected B self() {
@ -96,10 +94,10 @@ public class ClassMethodArgs {
this(builder.clazz, builder.method, builder.args);
}
public ClassMethodArgs(Class<?> clazz, Method method, @Nullable Object[] args) {
public ClassMethodArgs(Class<?> clazz, Method method, Object[] args) {
this.clazz = checkNotNull(clazz, "clazz");
this.method = checkNotNull(method, "method");
this.args = args;
this.args = checkNotNull(args, "args");
}
public Class<?> getClazz() {
@ -110,7 +108,7 @@ public class ClassMethodArgs {
return method;
}
@Nullable public Object[] getArgs() {
public Object[] getArgs() {
return args;
}
@ -136,6 +134,6 @@ public class ClassMethodArgs {
protected ToStringHelper string() {
return Objects.toStringHelper("").omitNullValues().add("clazz", clazz).add("method", method)
.add("args", args != null ? Arrays.asList(args) : null);
.add("args", args.length != 0 ? Arrays.asList(args) : null);
}
}

View File

@ -22,8 +22,6 @@ import static com.google.common.base.Objects.equal;
import java.lang.reflect.Method;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -68,7 +66,7 @@ public class ClassMethodArgsAndReturnVal extends ClassMethodArgs {
private final Object returnVal;
public ClassMethodArgsAndReturnVal(Class<?> clazz, Method method, @Nullable Object[] args, Object returnVal) {
public ClassMethodArgsAndReturnVal(Class<?> clazz, Method method, Object[] args, Object returnVal) {
super(clazz, method, args);
this.returnVal = returnVal;
}

View File

@ -18,7 +18,8 @@
*/
package org.jclouds.rest;
import java.lang.reflect.Proxy;
import static com.google.common.reflect.Reflection.newProxy;
import static com.google.inject.util.Types.newParameterizedType;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -28,7 +29,6 @@ import org.jclouds.rest.internal.AsyncRestClientProxy;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Types;
/**
*
@ -45,12 +45,9 @@ public class AsyncClientFactory {
@SuppressWarnings("unchecked")
public <T> T create(Class<T> clazz) {
return (T) create(clazz, (AsyncRestClientProxy<T>) injector.getInstance(Key.get(TypeLiteral
.get(Types.newParameterizedType(AsyncRestClientProxy.class, clazz)))));
Key<AsyncRestClientProxy<T>> key = (Key<AsyncRestClientProxy<T>>) Key.get(TypeLiteral.get(newParameterizedType(
AsyncRestClientProxy.class, clazz)));
return newProxy(clazz, injector.getInstance(key));
}
@SuppressWarnings("unchecked")
public static <T> T create(Class<T> clazz, AsyncRestClientProxy<T> proxy) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz }, proxy);
}
}

View File

@ -94,15 +94,4 @@ public class BinderUtils {
binder.bind(asyncClientType).toProvider(asyncProvider);
}
@SuppressWarnings("unchecked")
public static <T> T newNullProxy(Class<T> clazz) {
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
return null;
}
});
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.rest.config;
import static com.google.common.reflect.Reflection.newProxy;
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
import java.lang.reflect.Method;
@ -40,7 +41,6 @@ import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.json.config.GsonModule;
import org.jclouds.location.config.LocationModule;
import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.HttpAsyncClient;
import org.jclouds.rest.HttpClient;
@ -178,15 +178,14 @@ public class RestModule extends AbstractModule {
TypeLiteral typeLiteral = TypeLiteral.get(clazz);
RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key.get(TypeLiteral.get(Types
.newParameterizedType(RestAnnotationProcessor.class, clazz))));
// cannot use child injectors due to the super coarse guice lock on
// Singleton
// cannot use child injectors due to the super coarse guice lock on Singleton
util.setCaller(from);
LoadingCache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
new TypeLiteral<LoadingCache<ClassMethodArgs, Object>>() {
}, Names.named("async")));
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util, typeLiteral, delegateMap);
injector.injectMembers(proxy);
return AsyncClientFactory.create(clazz, proxy);
return newProxy(clazz, proxy);
}
}

View File

@ -19,7 +19,6 @@
package org.jclouds.rest.internal;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.concurrent.ExecutionException;
@ -28,6 +27,7 @@ import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import javax.ws.rs.Path;
import org.jclouds.Constants;
import org.jclouds.concurrent.ExceptionParsingListenableFuture;
@ -51,6 +51,7 @@ import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.reflect.AbstractInvocationHandler;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Binding;
@ -88,7 +89,7 @@ import com.google.inject.util.Types;
* @author Adrian Cole
*/
@Singleton
public class AsyncRestClientProxy<T> implements InvocationHandler {
public class AsyncRestClientProxy<T> extends AbstractInvocationHandler {
public Class<T> getDeclaring() {
return declaring;
}
@ -133,14 +134,9 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
};
public Object invoke(Object o, Method method, Object[] args) throws ExecutionException {
if (method.getName().equals("equals")) {
return this.equals(o);
} else if (method.getName().equals("toString")) {
return this.toString();
} else if (method.getName().equals("hashCode")) {
return this.hashCode();
} else if (method.isAnnotationPresent(Provides.class)) {
@Override
protected Object handleInvocation(Object proxy, Method method, Object[] args) throws ExecutionException {
if (method.isAnnotationPresent(Provides.class)) {
return lookupValueFromGuice(method);
} else if (method.isAnnotationPresent(Delegate.class)) {
return propagateContextToDelegate(method, args);
@ -279,23 +275,6 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
public TransformingHttpCommand<?> create(HttpRequest request, Function<HttpResponse, ?> transformer);
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof AsyncRestClientProxy<?>))
return false;
AsyncRestClientProxy<?> other = (AsyncRestClientProxy<?>) obj;
if (other == this)
return true;
if (other.declaring != this.declaring)
return false;
return super.equals(obj);
}
@Override
public int hashCode() {
return declaring.hashCode();
}
public String toString() {
return "Client Proxy for :" + declaring.getName();
}