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

Reply via email to