mirror of https://github.com/apache/jclouds.git
updated to employ Reflection.newProxy + AbstractInvocationHandler
This commit is contained in:
parent
4d2124bada
commit
c30fedec20
|
@ -62,11 +62,11 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
||||||
org.jclouds.openstack.v2_0.services.Extension.class));
|
org.jclouds.openstack.v2_0.services.Extension.class));
|
||||||
if (ext.isPresent()) {
|
if (ext.isPresent()) {
|
||||||
URI namespace = URI.create(ext.get().namespace());
|
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(""),
|
if (Iterables.any(extensions.getUnchecked(""),
|
||||||
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||||
return Optional.of(input.getReturnVal());
|
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()),
|
if (Iterables.any(extensions.getUnchecked(checkNotNull(input.getArgs()[0], "arg[0] in %s", input).toString()),
|
||||||
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||||
return Optional.of(input.getReturnVal());
|
return Optional.of(input.getReturnVal());
|
||||||
|
|
|
@ -63,7 +63,7 @@ public abstract class CallerArg0ToPagedIterable<T, I extends CallerArg0ToPagedIt
|
||||||
return PagedIterables.of(input);
|
return PagedIterables.of(input);
|
||||||
|
|
||||||
Optional<String> arg0Option = Optional.absent();
|
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];
|
Object arg0 = request.getCaller().get().getArgs()[0];
|
||||||
if (arg0 != null)
|
if (arg0 != null)
|
||||||
arg0Option = Optional.of(arg0.toString());
|
arg0Option = Optional.of(arg0.toString());
|
||||||
|
|
|
@ -19,11 +19,10 @@
|
||||||
package org.jclouds.concurrent.internal;
|
package org.jclouds.concurrent.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
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.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -46,6 +45,7 @@ import com.google.common.base.Throwables;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.reflect.AbstractInvocationHandler;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.ProvisionException;
|
import com.google.inject.ProvisionException;
|
||||||
|
|
||||||
|
@ -54,15 +54,13 @@ import com.google.inject.ProvisionException;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @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,
|
public static <T> T proxy(Function<ClassMethodArgsAndReturnVal, Optional<Object>> optionalConverter, Class<T> clazz, Object async,
|
||||||
@Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap,
|
@Named("sync") LoadingCache<ClassMethodArgs, Object> delegateMap,
|
||||||
Map<Class<?>, Class<?>> sync2Async, Map<String, Long> timeouts) throws IllegalArgumentException, SecurityException,
|
Map<Class<?>, Class<?>> sync2Async, Map<String, Long> timeouts) throws IllegalArgumentException, SecurityException,
|
||||||
NoSuchMethodException {
|
NoSuchMethodException {
|
||||||
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[] { clazz },
|
return newProxy(clazz, new SyncProxy(optionalConverter, clazz, async, delegateMap, sync2Async, timeouts));
|
||||||
new SyncProxy(optionalConverter, clazz, async, delegateMap, sync2Async, timeouts));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Function<ClassMethodArgsAndReturnVal, Optional<Object>> optionalConverter;
|
private final Function<ClassMethodArgsAndReturnVal, Optional<Object>> optionalConverter;
|
||||||
|
@ -134,14 +132,9 @@ public class SyncProxy implements InvocationHandler {
|
||||||
return methodNanos;
|
return methodNanos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object invoke(Object o, Method method, Object[] args) throws Exception {
|
@Override
|
||||||
if (method.getName().equals("equals")) {
|
protected Object handleInvocation(Object o, Method method, Object[] args) throws Exception {
|
||||||
return this.equals(o);
|
if (method.isAnnotationPresent(Delegate.class)) {
|
||||||
} else if (method.getName().equals("hashCode")) {
|
|
||||||
return this.hashCode();
|
|
||||||
} else if (method.getName().equals("toString")) {
|
|
||||||
return this.toString();
|
|
||||||
} else if (method.isAnnotationPresent(Delegate.class)) {
|
|
||||||
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(method);
|
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(method);
|
||||||
// get the return type of the asynchronous class associated with this client
|
// get the return type of the asynchronous class associated with this client
|
||||||
// ex. FloatingIPClient is associated with FloatingIPAsyncClient
|
// ex. FloatingIPClient is associated with FloatingIPAsyncClient
|
||||||
|
@ -191,24 +184,8 @@ public class SyncProxy implements InvocationHandler {
|
||||||
}
|
}
|
||||||
return timeout != null ? TimeUnit.MILLISECONDS.toNanos(timeout) : null;
|
return timeout != null ? TimeUnit.MILLISECONDS.toNanos(timeout) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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() {
|
public String toString() {
|
||||||
return "Sync Proxy for: " + delegate.getClass().getSimpleName();
|
return "Sync Proxy for: " + delegate.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Objects.ToStringHelper;
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
@ -48,7 +46,7 @@ public class ClassMethodArgs {
|
||||||
public abstract static class Builder<B extends Builder<B>> {
|
public abstract static class Builder<B extends Builder<B>> {
|
||||||
private Class<?> clazz;
|
private Class<?> clazz;
|
||||||
private Method method;
|
private Method method;
|
||||||
private Object[] args;
|
private Object[] args = {};
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected B self() {
|
protected B self() {
|
||||||
|
@ -96,10 +94,10 @@ public class ClassMethodArgs {
|
||||||
this(builder.clazz, builder.method, builder.args);
|
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.clazz = checkNotNull(clazz, "clazz");
|
||||||
this.method = checkNotNull(method, "method");
|
this.method = checkNotNull(method, "method");
|
||||||
this.args = args;
|
this.args = checkNotNull(args, "args");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> getClazz() {
|
public Class<?> getClazz() {
|
||||||
|
@ -110,7 +108,7 @@ public class ClassMethodArgs {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable public Object[] getArgs() {
|
public Object[] getArgs() {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +134,6 @@ public class ClassMethodArgs {
|
||||||
|
|
||||||
protected ToStringHelper string() {
|
protected ToStringHelper string() {
|
||||||
return Objects.toStringHelper("").omitNullValues().add("clazz", clazz).add("method", method)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@ import static com.google.common.base.Objects.equal;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Objects.ToStringHelper;
|
import com.google.common.base.Objects.ToStringHelper;
|
||||||
|
|
||||||
|
@ -68,7 +66,7 @@ public class ClassMethodArgsAndReturnVal extends ClassMethodArgs {
|
||||||
|
|
||||||
private final Object returnVal;
|
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);
|
super(clazz, method, args);
|
||||||
this.returnVal = returnVal;
|
this.returnVal = returnVal;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest;
|
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.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -28,7 +29,6 @@ import org.jclouds.rest.internal.AsyncRestClientProxy;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
import com.google.inject.util.Types;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -45,12 +45,9 @@ public class AsyncClientFactory {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T create(Class<T> clazz) {
|
public <T> T create(Class<T> clazz) {
|
||||||
return (T) create(clazz, (AsyncRestClientProxy<T>) injector.getInstance(Key.get(TypeLiteral
|
Key<AsyncRestClientProxy<T>> key = (Key<AsyncRestClientProxy<T>>) Key.get(TypeLiteral.get(newParameterizedType(
|
||||||
.get(Types.newParameterizedType(AsyncRestClientProxy.class, clazz)))));
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,15 +94,4 @@ public class BinderUtils {
|
||||||
binder.bind(asyncClientType).toProvider(asyncProvider);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.config;
|
package org.jclouds.rest.config;
|
||||||
|
|
||||||
|
import static com.google.common.reflect.Reflection.newProxy;
|
||||||
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
|
import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
@ -40,7 +41,6 @@ import org.jclouds.internal.ClassMethodArgs;
|
||||||
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
|
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
|
||||||
import org.jclouds.json.config.GsonModule;
|
import org.jclouds.json.config.GsonModule;
|
||||||
import org.jclouds.location.config.LocationModule;
|
import org.jclouds.location.config.LocationModule;
|
||||||
import org.jclouds.rest.AsyncClientFactory;
|
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.HttpAsyncClient;
|
import org.jclouds.rest.HttpAsyncClient;
|
||||||
import org.jclouds.rest.HttpClient;
|
import org.jclouds.rest.HttpClient;
|
||||||
|
@ -178,15 +178,14 @@ public class RestModule extends AbstractModule {
|
||||||
TypeLiteral typeLiteral = TypeLiteral.get(clazz);
|
TypeLiteral typeLiteral = TypeLiteral.get(clazz);
|
||||||
RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key.get(TypeLiteral.get(Types
|
RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key.get(TypeLiteral.get(Types
|
||||||
.newParameterizedType(RestAnnotationProcessor.class, clazz))));
|
.newParameterizedType(RestAnnotationProcessor.class, clazz))));
|
||||||
// cannot use child injectors due to the super coarse guice lock on
|
// cannot use child injectors due to the super coarse guice lock on Singleton
|
||||||
// Singleton
|
|
||||||
util.setCaller(from);
|
util.setCaller(from);
|
||||||
LoadingCache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
|
LoadingCache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
|
||||||
new TypeLiteral<LoadingCache<ClassMethodArgs, Object>>() {
|
new TypeLiteral<LoadingCache<ClassMethodArgs, Object>>() {
|
||||||
}, Names.named("async")));
|
}, Names.named("async")));
|
||||||
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util, typeLiteral, delegateMap);
|
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util, typeLiteral, delegateMap);
|
||||||
injector.injectMembers(proxy);
|
injector.injectMembers(proxy);
|
||||||
return AsyncClientFactory.create(clazz, proxy);
|
return newProxy(clazz, proxy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.rest.internal;
|
package org.jclouds.rest.internal;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.InvocationHandler;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -28,6 +27,7 @@ import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Qualifier;
|
import javax.inject.Qualifier;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.concurrent.ExceptionParsingListenableFuture;
|
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.cache.LoadingCache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Iterables;
|
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.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Binding;
|
import com.google.inject.Binding;
|
||||||
|
@ -88,7 +89,7 @@ import com.google.inject.util.Types;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AsyncRestClientProxy<T> implements InvocationHandler {
|
public class AsyncRestClientProxy<T> extends AbstractInvocationHandler {
|
||||||
public Class<T> getDeclaring() {
|
public Class<T> getDeclaring() {
|
||||||
return declaring;
|
return declaring;
|
||||||
}
|
}
|
||||||
|
@ -133,14 +134,9 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public Object invoke(Object o, Method method, Object[] args) throws ExecutionException {
|
@Override
|
||||||
if (method.getName().equals("equals")) {
|
protected Object handleInvocation(Object proxy, Method method, Object[] args) throws ExecutionException {
|
||||||
return this.equals(o);
|
if (method.isAnnotationPresent(Provides.class)) {
|
||||||
} else if (method.getName().equals("toString")) {
|
|
||||||
return this.toString();
|
|
||||||
} else if (method.getName().equals("hashCode")) {
|
|
||||||
return this.hashCode();
|
|
||||||
} else if (method.isAnnotationPresent(Provides.class)) {
|
|
||||||
return lookupValueFromGuice(method);
|
return lookupValueFromGuice(method);
|
||||||
} else if (method.isAnnotationPresent(Delegate.class)) {
|
} else if (method.isAnnotationPresent(Delegate.class)) {
|
||||||
return propagateContextToDelegate(method, args);
|
return propagateContextToDelegate(method, args);
|
||||||
|
@ -279,23 +275,6 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
||||||
public TransformingHttpCommand<?> create(HttpRequest request, Function<HttpResponse, ?> transformer);
|
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() {
|
public String toString() {
|
||||||
return "Client Proxy for :" + declaring.getName();
|
return "Client Proxy for :" + declaring.getName();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue