Revision: 10322
Author: b...@google.com
Date: Sat Jun 11 03:17:07 2011
Log: Clean up RequestFactoryInterfaceValidator and Deobfuscator to
simplify
ResolverServiceLayer.
This allows the validator to be jettisoned in favor of a lighter-weight
object.
Patch by: bobv
Review by: rjrjr
Review at http://gwt-code-reviews.appspot.com/1455803
http://code.google.com/p/google-web-toolkit/source/detail?r=10322
Modified:
/trunk/user/src/com/google/web/bindery/requestfactory/server/Deobfuscator.java
/trunk/user/src/com/google/web/bindery/requestfactory/server/OperationData.java
/trunk/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java
/trunk/user/src/com/google/web/bindery/requestfactory/server/ResolverServiceLayer.java
/trunk/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
/trunk/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryPolymorphicJreTest.java
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/server/Deobfuscator.java
Fri Jun 10 11:06:22 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/server/Deobfuscator.java
Sat Jun 11 03:17:07 2011
@@ -16,12 +16,14 @@
package com.google.web.bindery.requestfactory.server;
import com.google.gwt.dev.asm.Type;
-import com.google.gwt.dev.util.Name.BinaryName;
import com.google.web.bindery.requestfactory.vm.impl.OperationKey;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import java.util.SortedSet;
/**
* Provides access to payload deobfuscation services.
@@ -30,8 +32,38 @@
public static class Builder {
private Deobfuscator d = new Deobfuscator();
{
+ d.domainToClientType = new HashMap<String, List<String>>();
d.operationData = new HashMap<OperationKey, OperationData>();
- d.typeTokens = new HashMap<String, Type>();
+ d.typeTokens = new HashMap<String, String>();
+ }
+
+ public Builder addClientToDomainMapping(String domainBinaryName,
SortedSet<Type> value) {
+ List<String> clientBinaryNames;
+ switch (value.size()) {
+ case 0:
+ clientBinaryNames = Collections.emptyList();
+ break;
+ case 1:
+ clientBinaryNames =
Collections.singletonList(value.first().getClassName());
+ break;
+ default:
+ clientBinaryNames = new ArrayList<String>(value.size());
+ for (Type t : value) {
+ clientBinaryNames.add(t.getClassName());
+ }
+ clientBinaryNames =
Collections.unmodifiableList(clientBinaryNames);
+ }
+ d.domainToClientType.put(domainBinaryName, clientBinaryNames);
+ return this;
+ }
+
+ public Builder addClientToDomainMappings(Map<Type, SortedSet<Type>>
data) {
+ for (Map.Entry<Type, SortedSet<Type>> entry : data.entrySet()) {
+ String domainBinaryName = entry.getKey().getClassName();
+ SortedSet<Type> value = entry.getValue();
+ addClientToDomainMapping(domainBinaryName, value);
+ }
+ return this;
}
public Builder addOperation(OperationKey key, OperationData data) {
@@ -45,7 +77,7 @@
}
public Builder addRawTypeToken(String token, String binaryName) {
- d.typeTokens.put(token,
Type.getObjectType(BinaryName.toInternalName(binaryName)));
+ d.typeTokens.put(token, binaryName);
return this;
}
@@ -55,64 +87,74 @@
}
return this;
}
+
+ public Builder addTypeTokens(Map<String, Type> typeTokens) {
+ for (Map.Entry<String, Type> entry : typeTokens.entrySet()) {
+ d.typeTokens.put(entry.getKey(), entry.getValue().getClassName());
+ }
+ return this;
+ }
public Deobfuscator build() {
Deobfuscator toReturn = d;
+ toReturn.domainToClientType =
Collections.unmodifiableMap(toReturn.domainToClientType);
toReturn.operationData =
Collections.unmodifiableMap(toReturn.operationData);
toReturn.typeTokens =
Collections.unmodifiableMap(toReturn.typeTokens);
d = null;
return toReturn;
}
- /**
- * This method should be removed in favor of having a map of
RequestFactory
- * to Deobfuscators in ResolverServiceLayer and getting rid of the
static
- * validator instance.
- */
- public Builder setOperationData(Map<OperationKey, OperationData>
operationData) {
- d.operationData = operationData;
+ public Builder merge(Deobfuscator deobfuscator) {
+ d.domainToClientType.putAll(deobfuscator.domainToClientType);
+ d.operationData.putAll(deobfuscator.operationData);
+ d.typeTokens.putAll(deobfuscator.typeTokens);
return this;
}
-
- /**
- * To be removed as well.
- */
- public Builder setTypeTokens(Map<String, Type> typeTokens) {
- d.typeTokens = typeTokens;
- return this;
- }
}
+ /**
+ * Maps domain types (e.g Foo) to client proxy types (e.g. FooAProxy,
+ * FooBProxy).
+ */
+ private Map<String, List<String>> domainToClientType;
private Map<OperationKey, OperationData> operationData;
-
/**
* Map of obfuscated ids to binary class names.
*/
- private Map<String, Type> typeTokens;
+ private Map<String, String> typeTokens;
Deobfuscator() {
}
+
+ /**
+ * Returns the client proxy types whose {@code @ProxyFor} is exactly
+ * {@code binaryTypeName}. Ordered such that the most-derived types will
be
+ * iterated over first.
+ */
+ public List<String> getClientProxies(String binaryTypeName) {
+ return domainToClientType.get(binaryTypeName);
+ }
/**
* Returns a method descriptor that should be invoked on the service
object.
*/
public String getDomainMethodDescriptor(String operation) {
- OperationData data = operationData.get(new OperationKey(operation));
+ OperationData data = getData(operation);
return data == null ? null : data.getDomainMethodDescriptor();
}
public String getRequestContext(String operation) {
- OperationData data = operationData.get(new OperationKey(operation));
+ OperationData data = getData(operation);
return data == null ? null : data.getRequestContext();
}
public String getRequestContextMethodDescriptor(String operation) {
- OperationData data = operationData.get(new OperationKey(operation));
+ OperationData data = getData(operation);
return data == null ? null : data.getClientMethodDescriptor();
}
public String getRequestContextMethodName(String operation) {
- OperationData data = operationData.get(new OperationKey(operation));
+ OperationData data = getData(operation);
return data == null ? null : data.getMethodName();
}
@@ -120,7 +162,11 @@
* Returns a type's binary name based on an obfuscated token.
*/
public String getTypeFromToken(String token) {
- Type type = typeTokens.get(token);
- return type == null ? null : type.getClassName();
+ return typeTokens.get(token);
+ }
+
+ private OperationData getData(String operation) {
+ OperationData data = operationData.get(new OperationKey(operation));
+ return data;
}
}
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/server/OperationData.java
Thu Jun 9 11:31:51 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/server/OperationData.java
Sat Jun 11 03:17:07 2011
@@ -93,4 +93,12 @@
public String getRequestContext() {
return requestContextBinaryName;
}
-}
+
+ /**
+ * For debugging use only.
+ */
+ @Override
+ public String toString() {
+ return getRequestContext() + "::" + getMethodName() +
getDomainMethodDescriptor();
+ }
+}
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java
Fri Jun 10 11:06:22 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java
Sat Jun 11 03:17:07 2011
@@ -789,8 +789,8 @@
}
public Deobfuscator getDeobfuscator() {
- return new
Deobfuscator.Builder().setOperationData(operationData).setTypeTokens(typeTokens)
- .build();
+ return new
Deobfuscator.Builder().addClientToDomainMappings(domainToClientType)
+ .addOperationData(operationData).addTypeTokens(typeTokens).build();
}
/**
@@ -994,59 +994,6 @@
public void validateValueProxy(String binaryName) {
validateProxy(binaryName, valueProxyIntf, false);
}
-
- /**
- * Given the binary name of a domain type, return the BaseProxy type
that is
- * assignable to {@code clientType}. This method allows multiple proxy
types
- * to be assigned to a domain type for use in different contexts (e.g.
API
- * slices). If there are multiple client types mapped to
- * {@code domainTypeBinaryName} and assignable to {@code
clientTypeBinaryName}
- * , the first matching type will be returned.
- */
- String getEntityProxyTypeName(String domainTypeBinaryName, String
clientTypeBinaryName) {
- Type key =
Type.getObjectType(BinaryName.toInternalName(domainTypeBinaryName));
- SortedSet<Type> found = domainToClientType.get(key);
-
- /*
- * If nothing was found look for proxyable supertypes the domain
object can
- * be upcast to.
- */
- if (found == null || found.isEmpty()) {
- List<Type> types = getSupertypes(parentLogger, key);
- for (Type type : types) {
- if (objectType.equals(type)) {
- break;
- }
-
- found = domainToClientType.get(type);
- if (found != null && !found.isEmpty()) {
- break;
- }
- }
- }
-
- if (found == null || found.isEmpty()) {
- return null;
- }
-
- Type typeToReturn = null;
-
- // Common case
- if (found.size() == 1) {
- typeToReturn = found.first();
- } else {
- // Search for the first assignable type
- Type assignableTo =
Type.getObjectType(BinaryName.toInternalName(clientTypeBinaryName));
- for (Type t : found) {
- if (isAssignable(parentLogger, assignableTo, t)) {
- typeToReturn = t;
- break;
- }
- }
- }
-
- return typeToReturn == null ? null : typeToReturn.getClassName();
- }
/**
* Record the mapping of a domain type to a client type. Proxy types
will be
=======================================
---
/trunk/user/src/com/google/web/bindery/requestfactory/server/ResolverServiceLayer.java
Thu Jun 9 11:31:51 2011
+++
/trunk/user/src/com/google/web/bindery/requestfactory/server/ResolverServiceLayer.java
Sat Jun 11 03:17:07 2011
@@ -36,18 +36,26 @@
*/
final class ResolverServiceLayer extends ServiceLayerDecorator {
+ private static Deobfuscator deobfuscator;
private static final Logger log =
Logger.getLogger(ServiceLayer.class.getName());
- /**
- * All instances of the service layer that are loaded by the same
classloader
- * can use a shared validator. The use of the validator should be
- * synchronized, since it is stateful.
- */
- private static final RequestFactoryInterfaceValidator validator =
- new RequestFactoryInterfaceValidator(log,
- new
RequestFactoryInterfaceValidator.ClassLoaderLoader(ServiceLayer.class
- .getClassLoader()));
- private static final Deobfuscator deobfuscator =
validator.getDeobfuscator();
+ private static synchronized boolean updateDeobfuscator(ClassLoader
classLoader, String binaryName) {
+ RequestFactoryInterfaceValidator validator =
+ new RequestFactoryInterfaceValidator(log,
+ new
RequestFactoryInterfaceValidator.ClassLoaderLoader(classLoader));
+ validator.antidote();
+ validator.validateRequestFactory(binaryName);
+ if (validator.isPoisoned()) {
+ return false;
+ }
+ if (deobfuscator == null) {
+ deobfuscator = validator.getDeobfuscator();
+ } else {
+ deobfuscator =
+ new
Deobfuscator.Builder().merge(deobfuscator).merge(validator.getDeobfuscator()).build();
+ }
+ return true;
+ }
@Override
public ClassLoader getDomainClassLoader() {
@@ -56,11 +64,7 @@
@Override
public Class<? extends BaseProxy> resolveClass(String typeToken) {
- String deobfuscated;
- synchronized (validator) {
- deobfuscated = deobfuscator.getTypeFromToken(typeToken);
- }
-
+ String deobfuscated = deobfuscator.getTypeFromToken(typeToken);
if (deobfuscated == null) {
die(null, "No type for token %s", typeToken);
}
@@ -71,13 +75,6 @@
@Override
public <T> Class<? extends T> resolveClientType(Class<?> domainClass,
Class<T> clientClass,
boolean required) {
- String name;
- synchronized (validator) {
- name = validator.getEntityProxyTypeName(domainClass.getName(),
clientClass.getName());
- }
- if (name != null) {
- return forName(name).asSubclass(clientClass);
- }
if (List.class.isAssignableFrom(domainClass)) {
return List.class.asSubclass(clientClass);
}
@@ -87,6 +84,19 @@
if (TypeUtils.isValueType(domainClass)) {
return domainClass.asSubclass(clientClass);
}
+ Class<?> toSearch = domainClass;
+ while (toSearch != null) {
+ List<String> clientTypes =
deobfuscator.getClientProxies(toSearch.getName());
+ if (clientTypes != null) {
+ for (String clientType : clientTypes) {
+ Class<?> proxy = forName(clientType);
+ if (clientClass.isAssignableFrom(proxy)) {
+ return proxy.asSubclass(clientClass);
+ }
+ }
+ }
+ toSearch = toSearch.getSuperclass();
+ }
if (required) {
die(null, "The domain type %s cannot be sent to the client",
domainClass.getCanonicalName());
}
@@ -120,10 +130,7 @@
* method to a domain method signature. We'll reuse this calculation
instead
* of iterating over all methods.
*/
- String domainDescriptor;
- synchronized (validator) {
- domainDescriptor = deobfuscator.getDomainMethodDescriptor(operation);
- }
+ String domainDescriptor =
deobfuscator.getDomainMethodDescriptor(operation);
if (domainDescriptor == null) {
return die(null, "No domain method descriptor is mapped to
operation %s", operation);
@@ -152,10 +159,7 @@
@Override
public Class<? extends RequestContext> resolveRequestContext(String
operation) {
- String requestContextClass;
- synchronized (validator) {
- requestContextClass = deobfuscator.getRequestContext(operation);
- }
+ String requestContextClass = deobfuscator.getRequestContext(operation);
if (requestContextClass == null) {
die(null, "No RequestContext for operation %s", operation);
}
@@ -165,12 +169,8 @@
@Override
public Method resolveRequestContextMethod(String operation) {
Class<?> searchIn = getTop().resolveRequestContext(operation);
- String methodName;
- String descriptor;
- synchronized (validator) {
- methodName = deobfuscator.getRequestContextMethodName(operation);
- descriptor =
deobfuscator.getRequestContextMethodDescriptor(operation);
- }
+ String methodName =
deobfuscator.getRequestContextMethodName(operation);
+ String descriptor =
deobfuscator.getRequestContextMethodDescriptor(operation);
Class<?>[] params = getArgumentTypes(descriptor);
try {
return searchIn.getMethod(methodName, params);
@@ -182,12 +182,8 @@
@Override
public Class<? extends RequestFactory> resolveRequestFactory(String
binaryName) {
- synchronized (validator) {
- validator.antidote();
- validator.validateRequestFactory(binaryName);
- if (validator.isPoisoned()) {
- die(null, "The RequestFactory %s did not pass validation",
binaryName);
- }
+ if (!updateDeobfuscator(getTop().getDomainClassLoader(), binaryName)) {
+ die(null, "The RequestFactory %s did not pass validation",
binaryName);
}
return forName(binaryName).asSubclass(RequestFactory.class);
}
=======================================
---
/trunk/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
Wed Jun 1 10:19:05 2011
+++
/trunk/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
Sat Jun 11 03:17:07 2011
@@ -44,7 +44,7 @@
*/
public class RequestFactoryInterfaceValidatorTest extends TestCase {
static class ClinitEntity {
- static ClinitEntity findClinitEntity(String key) {
+ static ClinitEntity findClinitEntity(@SuppressWarnings("unused")
String key) {
return null;
}
@@ -80,11 +80,11 @@
}
static class Domain {
- static int fooStatic(int a) {
+ static int fooStatic(@SuppressWarnings("unused") int a) {
return 0;
}
- int foo(int a) {
+ int foo(@SuppressWarnings("unused") int a) {
return 0;
}
@@ -104,7 +104,7 @@
void foo() {
}
- void foo(int a) {
+ void foo(@SuppressWarnings("unused") int a) {
}
String getId() {
@@ -141,7 +141,7 @@
/**
* This method should be static.
*/
- EntityWithInstanceFind findEntityWithInstanceFind(String key) {
+ EntityWithInstanceFind
findEntityWithInstanceFind(@SuppressWarnings("unused") String key) {
return null;
}
}
@@ -173,7 +173,7 @@
return null;
}
- void setList(List<Domain> value) {
+ void setList(@SuppressWarnings("unused") List<Domain> value) {
}
}
@@ -405,10 +405,11 @@
*/
public void testFollowingTypeParameters() {
v.validateEntityProxy(HasList.class.getName());
- assertNotNull(v.getEntityProxyTypeName(HasListDomain.class.getName(),
HasList.class.getName()));
- assertNotNull(v.getEntityProxyTypeName(Domain.class.getName(),
+ Deobfuscator d = v.getDeobfuscator();
+ assertNotNull(d.getClientProxies(HasListDomain.class.getName()));
+ assertTrue(d.getClientProxies(Domain.class.getName()).contains(
ReachableOnlyThroughParamaterList.class.getName()));
- assertNotNull(v.getEntityProxyTypeName(Domain.class.getName(),
+ assertTrue(d.getClientProxies(Domain.class.getName()).contains(
ReachableOnlyThroughReturnedList.class.getName()));
}
=======================================
---
/trunk/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryPolymorphicJreTest.java
Fri Jun 10 11:06:22 2011
+++
/trunk/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryPolymorphicJreTest.java
Sat Jun 11 03:17:07 2011
@@ -19,6 +19,7 @@
import
com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator.ClassLoaderLoader;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
+import java.util.List;
import java.util.logging.Logger;
/**
@@ -27,7 +28,7 @@
* to type-hierarchy mapping.
*/
public class RequestFactoryPolymorphicJreTest extends
RequestFactoryPolymorphicTest {
- RequestFactoryInterfaceValidator v;
+ private Deobfuscator deobfuscator;
@Override
public String getModuleName() {
@@ -44,16 +45,16 @@
/**
* Check related proxy types with unrelated domain types.
* */
- public void testUnrelatedDomainTypes() {
+ public void testUnrelatedDomainTypes() throws ClassNotFoundException {
// Simple mappings
- check(v, W.class, WProxy.class, WProxy.class);
- check(v, W.class, WZProxy.class, WZProxy.class);
- check(v, Z.class, ZProxy.class, ZProxy.class);
- check(v, Z.class, ZWProxy.class, ZWProxy.class);
+ check(W.class, WProxy.class, WProxy.class);
+ check(W.class, WZProxy.class, WZProxy.class);
+ check(Z.class, ZProxy.class, ZProxy.class);
+ check(Z.class, ZWProxy.class, ZWProxy.class);
// Look for derived proxy types that map to the domain type
- check(v, Z.class, WProxy.class, ZWProxy.class);
- check(v, W.class, ZProxy.class, WZProxy.class);
+ check(Z.class, WProxy.class, ZWProxy.class);
+ check(W.class, ZProxy.class, WZProxy.class);
/*
* This test is included to verify that the validator will fail
gracefully
@@ -68,47 +69,47 @@
* only ever crop up when the SkipInterfaceValidation annotation has
been
* used.
*/
- check(v, Z.class, WZProxy.class, null);
- check(v, W.class, ZWProxy.class, null);
+ check(Z.class, WZProxy.class, null);
+ check(W.class, ZWProxy.class, null);
}
/**
* Tests that the RequestFactoryInterfaceValidator is producing the
correct
* mappings from domain types back to client types.
*/
- public void testValidator() {
+ public void testValidator() throws ClassNotFoundException {
/*
* Check explicit mappings. Not all of the types are directly
referenced in
* the method declarations, so this also tests the ExtraTypes
annotation.
*/
- check(v, A.class, AProxy.class, AProxy.class);
- check(v, B.class, B1Proxy.class, B1Proxy.class);
- check(v, B.class, B2Proxy.class, B2Proxy.class);
- check(v, C.class, C1Proxy.class, C1Proxy.class);
- check(v, C.class, C2Proxy.class, C2Proxy.class);
+ check(A.class, AProxy.class, AProxy.class);
+ check(B.class, B1Proxy.class, B1Proxy.class);
+ check(B.class, B2Proxy.class, B2Proxy.class);
+ check(C.class, C1Proxy.class, C1Proxy.class);
+ check(C.class, C2Proxy.class, C2Proxy.class);
// Check types without explicit mappings.
- check(v, ASub.class, AProxy.class, AProxy.class);
- check(v, BSub.class, B1Proxy.class, B1Proxy.class);
- check(v, BSub.class, B2Proxy.class, B2Proxy.class);
- check(v, CSub.class, C1Proxy.class, C1Proxy.class);
- check(v, CSub.class, C2Proxy.class, C2Proxy.class);
+ check(ASub.class, AProxy.class, AProxy.class);
+ check(BSub.class, B1Proxy.class, B1Proxy.class);
+ check(BSub.class, B2Proxy.class, B2Proxy.class);
+ check(CSub.class, C1Proxy.class, C1Proxy.class);
+ check(CSub.class, C2Proxy.class, C2Proxy.class);
// Check assignments with proxies extending proxies
- check(v, C.class, B1Proxy.class, C1Proxy.class);
- check(v, C.class, B2Proxy.class, C2Proxy.class);
+ check(C.class, B1Proxy.class, C1Proxy.class);
+ check(C.class, B2Proxy.class, C2Proxy.class);
// Should prefer more-derived interfaces when possible
- check(v, D.class, AProxy.class, MoreDerivedProxy.class);
- check(v, D.class, D1Proxy.class, MoreDerivedProxy.class);
- check(v, D.class, D2Proxy.class, MoreDerivedProxy.class);
- check(v, D.class, D3Proxy.class, MoreDerivedProxy.class);
- check(v, D.class, MoreDerivedProxy.class, MoreDerivedProxy.class);
- check(v, DSub.class, AProxy.class, MoreDerivedProxy.class);
- check(v, DSub.class, D1Proxy.class, MoreDerivedProxy.class);
- check(v, DSub.class, D2Proxy.class, MoreDerivedProxy.class);
- check(v, DSub.class, D3Proxy.class, MoreDerivedProxy.class);
- check(v, DSub.class, MoreDerivedProxy.class, MoreDerivedProxy.class);
+ check(D.class, AProxy.class, MoreDerivedProxy.class);
+ check(D.class, D1Proxy.class, MoreDerivedProxy.class);
+ check(D.class, D2Proxy.class, MoreDerivedProxy.class);
+ check(D.class, D3Proxy.class, MoreDerivedProxy.class);
+ check(D.class, MoreDerivedProxy.class, MoreDerivedProxy.class);
+ check(DSub.class, AProxy.class, MoreDerivedProxy.class);
+ check(DSub.class, D1Proxy.class, MoreDerivedProxy.class);
+ check(DSub.class, D2Proxy.class, MoreDerivedProxy.class);
+ check(DSub.class, D3Proxy.class, MoreDerivedProxy.class);
+ check(DSub.class, MoreDerivedProxy.class, MoreDerivedProxy.class);
}
@Override
@@ -121,17 +122,31 @@
super.gwtSetUp();
Logger logger = Logger.getLogger(getClass().getName());
ClassLoaderLoader loader = new
ClassLoaderLoader(getClass().getClassLoader());
- v = new RequestFactoryInterfaceValidator(logger, loader);
+ RequestFactoryInterfaceValidator v = new
RequestFactoryInterfaceValidator(logger, loader);
v.validateRequestFactory(Factory.class.getName());
+ deobfuscator = v.getDeobfuscator();
}
- private void check(RequestFactoryInterfaceValidator v, Class<?>
domainType,
- Class<? extends BaseProxy> declaredReturnType, Class<? extends
BaseProxy> expectedClientType) {
- String type = v.getEntityProxyTypeName(domainType.getName(),
declaredReturnType.getName());
- if (expectedClientType == null) {
- assertNull(type, type);
- } else {
- assertEquals(expectedClientType.getName(), type);
+ private void check(Class<?> domainType, Class<? extends BaseProxy>
declaredReturnType,
+ Class<? extends BaseProxy> expectedClientType) throws
ClassNotFoundException {
+ while (domainType != null) {
+ List<String> types =
deobfuscator.getClientProxies(domainType.getName());
+ if (types != null) {
+ for (String type : types) {
+ Class<?> clientType = Class.forName(type);
+ if (declaredReturnType.isAssignableFrom(clientType)) {
+ if (expectedClientType == null) {
+ fail("Should not have found any matches");
+ }
+ assertEquals(expectedClientType, clientType);
+ return;
+ }
+ }
+ }
+ domainType = domainType.getSuperclass();
+ }
+ if (expectedClientType != null) {
+ fail("Expecting to find " + expectedClientType.getCanonicalName());
}
}
}
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors