/*
 * Copyright 2010 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.web.bindery.requestfactory.server;

import com.google.gwt.dev.asm.AnnotationVisitor;
import com.google.gwt.dev.asm.ClassReader;
import com.google.gwt.dev.asm.ClassVisitor;
import com.google.gwt.dev.asm.MethodVisitor;
import com.google.gwt.dev.asm.Opcodes;
import com.google.gwt.dev.asm.Type;
import com.google.gwt.dev.asm.commons.EmptyVisitor;
import com.google.gwt.dev.asm.commons.Method;
import com.google.gwt.dev.asm.signature.SignatureReader;
import com.google.gwt.dev.asm.signature.SignatureVisitor;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.BinaryName;
import com.google.gwt.dev.util.Name.SourceOrBinaryName;
import com.google.web.bindery.autobean.shared.ValueCodex;
import com.google.web.bindery.requestfactory.shared.BaseProxy;
import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ExtraTypes;
import com.google.web.bindery.requestfactory.shared.InstanceRequest;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.ProxyForName;
import com.google.web.bindery.requestfactory.shared.Request;
import com.google.web.bindery.requestfactory.shared.RequestContext;
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ServiceName;
import com.google.web.bindery.requestfactory.shared.SkipInterfaceValidation;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import com.google.web.bindery.requestfactory.vm.impl.OperationKey;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Encapsulates validation logic to determine if a {@link RequestFactory}
 * interface, its {@link RequestContext}, and associated {@link EntityProxy}
 * interfaces match their domain counterparts. This implementation examines the
 * classfiles directly in order to avoid the need to load the types into the
 * JVM.
 * <p>
 * This class is amenable to being used as a unit test:
 * 
 * <pre>
 * public void testRequestFactory() {
 *   Logger logger = Logger.getLogger("");
 *   RequestFactoryInterfaceValidator v = new RequestFactoryInterfaceValidator(
 *     logger, new ClassLoaderLoader(MyRequestContext.class.getClassLoader()));
 *   v.validateRequestContext(MyRequestContext.class.getName());
 *   assertFalse(v.isPoisoned());
 * }
 * </pre>
 * This class also has a {@code main} method and can be used as a build-time
 * tool:
 * 
 * <pre>
 * java -cp gwt-servlet.jar:your-code.jar \
 *   com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator \
 *   com.example.MyRequestFactory
 * </pre>
 */
public class RequestFactoryInterfaceValidator {
  /**
   * An implementation of {@link Loader} that uses a {@link ClassLoader} to
   * retrieve the class files.
   */
  public static class ClassLoaderLoader implements Loader {
    private final ClassLoader loader;

    public ClassLoaderLoader(ClassLoader loader) {
      this.loader = loader;
    }

    public boolean exists(String resource) {
      return loader.getResource(resource) != null;
    }

    public InputStream getResourceAsStream(String resource) {
      return loader.getResourceAsStream(resource);
    }
  }

  /**
   * Abstracts the mechanism by which class files are loaded.
   * 
   * @see ClassLoaderLoader
   */
  public interface Loader {
    /**
     * Returns true if the specified resource can be loaded.
     * 
     * @param resource a resource name (e.g. <code>com/example/Foo.class</code>)
     */
    boolean exists(String resource);

    /**
     * Returns an InputStream to access the specified resource, or
     * <code>null</code> if no such resource exists.
     * 
     * @param resource a resource name (e.g. <code>com/example/Foo.class</code>)
     */
    InputStream getResourceAsStream(String resource);
  }

  /**
   * Improves error messages by providing context for the user.
   * <p>
   * Visible for testing.
   */
  static class ErrorContext {
    private final Logger logger;
    private final ErrorContext parent;
    private Type currentType;
    private Method currentMethod;
    private RequestFactoryInterfaceValidator validator;

    public ErrorContext(Logger logger) {
      this.logger = logger;
      this.parent = null;
    }

    protected ErrorContext(ErrorContext parent) {
      this.logger = parent.logger;
      this.parent = parent;
      this.validator = parent.validator;
    }

    public void poison(String msg, Object... args) {
      poison();
      logger.logp(Level.SEVERE, currentType(), currentMethod(), String.format(msg, args));
      validator.poisoned = true;
    }

    public void poison(String msg, Throwable t) {
      poison();
      logger.logp(Level.SEVERE, currentType(), currentMethod(), msg, t);
      validator.poisoned = true;
    }

    public ErrorContext setMethod(Method method) {
      ErrorContext toReturn = fork();
      toReturn.currentMethod = method;
      return toReturn;
    }

    public ErrorContext setType(Type type) {
      ErrorContext toReturn = fork();
      toReturn.currentType = type;
      return toReturn;
    }

    public void spam(String msg, Object... args) {
      logger.logp(Level.FINEST, currentType(), currentMethod(), String.format(msg, args));
    }

    protected ErrorContext fork() {
      return new ErrorContext(this);
    }

    void setValidator(RequestFactoryInterfaceValidator validator) {
      assert this.validator == null : "Cannot set validator twice";
      this.validator = validator;
    }

    private String currentMethod() {
      if (currentMethod != null) {
        return print(currentMethod);
      }
      if (parent != null) {
        return parent.currentMethod();
      }
      return null;
    }

    private String currentType() {
      if (currentType != null) {
        return print(currentType);
      }
      if (parent != null) {
        return parent.currentType();
      }
      return null;
    }

    /**
     * Populate {@link RequestFactoryInterfaceValidator#badTypes} with the
     * current context.
     */
    private void poison() {
      if (currentType != null) {
        validator.badTypes.add(currentType.getClassName());
      }
      if (parent != null) {
        parent.poison();
      }
    }
  }

  /**
   * Used internally as a placeholder for types that cannot be mapped to a
   * domain object.
   */
  interface MissingDomainType {
  }

  /**
   * Collects the ProxyFor or Service annotation from an EntityProxy or
   * RequestContext type.
   */
  private class DomainMapper extends EmptyVisitor {
    private final ErrorContext logger;
    private String domainInternalName;
    private List<Class<? extends Annotation>> found = new ArrayList<Class<? extends Annotation>>();
    private String locatorInternalName;

    public DomainMapper(ErrorContext logger) {
      this.logger = logger;
      logger.spam("Finding domain mapping annotation");
    }

    public String getDomainInternalName() {
      return domainInternalName;
    }

    public String getLocatorInternalName() {
      return locatorInternalName;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName,
        String[] interfaces) {
      if ((access & Opcodes.ACC_INTERFACE) == 0) {
        logger.poison("Type must be an interface");
      }
    }

    /**
     * This method examines one annotation at a time.
     */
    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      // Set to true if the annotation should have class literal values
      boolean expectClasses = false;
      // Set to true if the annonation has string values
      boolean expectNames = false;

      if (desc.equals(Type.getDescriptor(ProxyFor.class))) {
        expectClasses = true;
        found.add(ProxyFor.class);
      } else if (desc.equals(Type.getDescriptor(ProxyForName.class))) {
        expectNames = true;
        found.add(ProxyForName.class);
      } else if (desc.equals(Type.getDescriptor(Service.class))) {
        expectClasses = true;
        found.add(Service.class);
      } else if (desc.equals(Type.getDescriptor(ServiceName.class))) {
        expectNames = true;
        found.add(ServiceName.class);
      }

      if (expectClasses) {
        return new EmptyVisitor() {
          @Override
          public void visit(String name, Object value) {
            if ("value".equals(name)) {
              domainInternalName = ((Type) value).getInternalName();
            } else if ("locator".equals(name)) {
              locatorInternalName = ((Type) value).getInternalName();
            }
          }
        };
      }

      if (expectNames) {
        return new EmptyVisitor() {
          @Override
          public void visit(String name, Object value) {
            String sourceName;
            boolean locatorRequired = "locator".equals(name);
            boolean valueRequired = "value".equals(name);
            if (valueRequired || locatorRequired) {
              sourceName = (String) value;
            } else {
              return;
            }

            /*
             * The input is a source name, so we need to convert it to an
             * internal name. We'll do this by substituting dollar signs for the
             * last slash in the name until there are no more slashes.
             */
            StringBuffer desc = new StringBuffer(sourceName.replace('.', '/'));
            while (!loader.exists(desc.toString() + ".class")) {
              logger.spam("Did not find " + desc.toString());
              int idx = desc.lastIndexOf("/");
              if (idx == -1) {
                if (locatorRequired) {
                  logger.poison("Cannot find locator named %s", value);
                } else if (valueRequired) {
                  logger.poison("Cannot find domain type named %s", value);
                }
                return;
              }
              desc.setCharAt(idx, '$');
            }

            if (locatorRequired) {
              locatorInternalName = desc.toString();
              logger.spam(locatorInternalName);
            } else if (valueRequired) {
              domainInternalName = desc.toString();
              logger.spam(domainInternalName);
            } else {
              throw new RuntimeException("Should not reach here");
            }
          }
        };
      }
      return null;
    }

    @Override
    public void visitEnd() {
      // Only allow one annotation
      if (found.size() > 1) {
        StringBuilder sb = new StringBuilder();
        for (Class<?> clazz : found) {
          sb.append(" @").append(clazz.getSimpleName());
        }
        logger.poison("Redundant domain mapping annotations present:%s", sb.toString());
      }
    }
  }

  private class ExtraTypesCollector extends EmptyVisitor {
    private final ErrorContext logger;
    private final Set<Type> collected = new HashSet<Type>();

    public ExtraTypesCollector(ErrorContext logger) {
      this.logger = logger;
      logger.spam("Collecting extra types");
    }

    public Type[] exec(Type type) {
      for (Type toExamine : getSupertypes(logger, type)) {
        RequestFactoryInterfaceValidator.this.visit(logger, toExamine.getInternalName(), this);
      }
      return collected.toArray(new Type[collected.size()]);
    }

    @Override
    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
      if (!desc.equals(Type.getDescriptor(ExtraTypes.class))) {
        return null;
      }

      return new EmptyVisitor() {

        @Override
        public AnnotationVisitor visitArray(String name) {
          if (!"value".equals(name)) {
            return null;
          }
          return new EmptyVisitor() {
            @Override
            public void visit(String name, Object value) {
              collected.add((Type) value);
            }
          };
        }

      };
    }
  }

  /**
   * Collects information about domain objects. This visitor is intended to be
   * iteratively applied to collect all methods in a type hierarchy.
   */
  private class MethodsInHierarchyCollector extends EmptyVisitor {
    private final ErrorContext logger;
    private Set<RFMethod> methods = new LinkedHashSet<RFMethod>();
    private Set<String> seen = new HashSet<String>();

    private MethodsInHierarchyCollector(ErrorContext logger) {
      this.logger = logger;
    }

    public Set<RFMethod> exec(String internalName) {
      RequestFactoryInterfaceValidator.this.visit(logger, internalName, this);

      Map<RFMethod, RFMethod> toReturn = new HashMap<RFMethod, RFMethod>();
      // Return most-derived methods
      for (RFMethod method : methods) {
        RFMethod key =
            new RFMethod(method.getName(), Type.getMethodDescriptor(Type.VOID_TYPE, method
                .getArgumentTypes()));

        RFMethod compareTo = toReturn.get(key);
        if (compareTo == null) {
          toReturn.put(key, method);
        } else if (isAssignable(logger, compareTo.getReturnType(), method.getReturnType())) {
          toReturn.put(key, method);
        }
      }

      return new HashSet<RFMethod>(toReturn.values());
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName,
        String[] interfaces) {
      if (!seen.add(name)) {
        return;
      }
      if (!objectType.getInternalName().equals(superName)) {
        RequestFactoryInterfaceValidator.this.visit(logger, superName, this);
      }
      if (interfaces != null) {
        for (String intf : interfaces) {
          RequestFactoryInterfaceValidator.this.visit(logger, intf, this);
        }
      }
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature,
        String[] exceptions) {
      // Ignore initializers
      if ("<clinit>".equals(name) || "<init>".equals(name)) {
        return null;
      }
      final RFMethod method = new RFMethod(name, desc);
      method.setDeclaredStatic((access & Opcodes.ACC_STATIC) != 0);
      method.setDeclaredSignature(signature);
      methods.add(method);

      return new EmptyVisitor() {
        @Override
        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
          if (desc.equals(Type.getDescriptor(SkipInterfaceValidation.class))) {
            method.setValidationSkipped(true);
          }
          return null;
        }
      };
    }
  }

  private static class RFMethod extends Method {
    private boolean isDeclaredStatic;
    private String signature;
    private boolean isValidationSkipped;

    public RFMethod(String name, String desc) {
      super(name, desc);
    }

    public String getSignature() {
      return signature;
    }

    public boolean isDeclaredStatic() {
      return isDeclaredStatic;
    }

    public boolean isValidationSkipped() {
      return isValidationSkipped;
    }

    public void setDeclaredSignature(String signature) {
      this.signature = signature;
    }

    public void setDeclaredStatic(boolean value) {
      isDeclaredStatic = value;
    }

    public void setValidationSkipped(boolean isValidationSkipped) {
      this.isValidationSkipped = isValidationSkipped;
    }

    @Override
    public String toString() {
      return (isDeclaredStatic ? "static " : "") + super.toString();
    }
  }

  private class SupertypeCollector extends EmptyVisitor {
    private final ErrorContext logger;
    private final Set<String> seen = new HashSet<String>();
    private final List<Type> supers = new ArrayList<Type>();

    public SupertypeCollector(ErrorContext logger) {
      this.logger = logger;
    }

    public List<Type> exec(Type type) {
      RequestFactoryInterfaceValidator.this.visit(logger, type.getInternalName(), this);
      return supers;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName,
        String[] interfaces) {
      if (!seen.add(name)) {
        return;
      }
      supers.add(Type.getObjectType(name));
      if (!objectType.getInternalName().equals(name)) {
        RequestFactoryInterfaceValidator.this.visit(logger, superName, this);
      }
      if (interfaces != null) {
        for (String intf : interfaces) {
          RequestFactoryInterfaceValidator.this.visit(logger, intf, this);
        }
      }
    }
  }

  /**
   * Return all types referenced by a method signature.
   */
  private static class TypesInSignatureCollector extends SignatureAdapter {
    private final Set<Type> found = new HashSet<Type>();

    public Type[] getFound() {
      return found.toArray(new Type[found.size()]);
    }

    @Override
    public SignatureVisitor visitArrayType() {
      return this;
    }

    @Override
    public SignatureVisitor visitClassBound() {
      return this;
    }

    @Override
    public void visitClassType(String name) {
      found.add(Type.getObjectType(name));
    }

    @Override
    public SignatureVisitor visitExceptionType() {
      return this;
    }

    @Override
    public SignatureVisitor visitInterface() {
      return this;
    }

    @Override
    public SignatureVisitor visitInterfaceBound() {
      return this;
    }

    @Override
    public SignatureVisitor visitParameterType() {
      return this;
    }

    @Override
    public SignatureVisitor visitReturnType() {
      return this;
    }

    @Override
    public SignatureVisitor visitSuperclass() {
      return this;
    }

    @Override
    public SignatureVisitor visitTypeArgument(char wildcard) {
      return this;
    }
  }

  static final Set<Class<?>> VALUE_TYPES = ValueCodex.getAllValueTypes();

  public static void main(String[] args) {
    if (args.length == 0) {
      System.err.println("Usage: java -cp gwt-servlet.jar:your-code.jar "
          + RequestFactoryInterfaceValidator.class.getCanonicalName()
          + " com.example.MyRequestFactory");
      System.exit(1);
    }
    RequestFactoryInterfaceValidator validator =
        new RequestFactoryInterfaceValidator(Logger
            .getLogger(RequestFactoryInterfaceValidator.class.getName()), new ClassLoaderLoader(
            Thread.currentThread().getContextClassLoader()));
    validator.validateRequestFactory(args[0]);
    System.exit(validator.isPoisoned() ? 1 : 0);
  }

  static String messageCouldNotFindMethod(Type domainType, List<? extends Method> methods) {
    StringBuilder sb = new StringBuilder();
    sb.append(String.format("Could not find matching method in %s.\nPossible matches:\n",
        print(domainType)));
    for (Method domainMethod : methods) {
      sb.append("  ").append(print(domainMethod)).append("\n");
    }
    return sb.toString();
  }

  private static String print(Method method) {
    StringBuilder sb = new StringBuilder();
    sb.append(print(method.getReturnType())).append(" ").append(method.getName()).append("(");
    for (Type t : method.getArgumentTypes()) {
      sb.append(print(t)).append(" ");
    }
    sb.append(")");
    return sb.toString();
  }

  private static String print(Type type) {
    return SourceOrBinaryName.toSourceName(type.getClassName());
  }

  /**
   * A set of binary type names that are known to be bad.
   */
  private final Set<String> badTypes = new HashSet<String>();
  /**
   * The type {@link BaseProxy}.
   */
  private final Type baseProxyIntf = Type.getType(BaseProxy.class);
  /**
   * Maps client types (e.g. FooProxy) to server domain types (e.g. Foo).
   */
  private final Map<Type, Type> clientToDomainType = new HashMap<Type, Type>();
  /**
   * Maps client types (e.g. FooProxy or FooContext) to their locator types
   * (e.g. FooLocator or FooServiceLocator).
   */
  private final Map<Type, Type> clientToLocatorMap = new HashMap<Type, Type>();
  /**
   * Maps domain types (e.g Foo) to client proxy types (e.g. FooAProxy,
   * FooBProxy).
   */
  private final Map<Type, SortedSet<Type>> domainToClientType =
      new HashMap<Type, SortedSet<Type>>();
  /**
   * The type {@link EntityProxy}.
   */
  private final Type entityProxyIntf = Type.getType(EntityProxy.class);
  /**
   * The type {@link Enum}.
   */
  private final Type enumType = Type.getType(Enum.class);
  /**
   * A placeholder type for client types that could not be resolved to a domain
   * type.
   */
  private final Type errorType = Type.getType(MissingDomainType.class);
  /**
   * The type {@link InstanceRequest}.
   */
  private final Type instanceRequestIntf = Type.getType(InstanceRequest.class);
  private final Loader loader;
  /**
   * A cache of all methods defined in a type hierarchy.
   */
  private final Map<Type, Set<RFMethod>> methodsInHierarchy = new HashMap<Type, Set<RFMethod>>();
  /**
   * Not static because it depends on {@link #parentLogger}.
   */
  private final Comparator<Type> typeNameComparator = new Comparator<Type>() {
    @Override
    public int compare(Type a, Type b) {
      if (isAssignable(parentLogger, a, b)) {
        return 1;
      } else if (isAssignable(parentLogger, b, a)) {
        return -1;
      }
      return a.getInternalName().compareTo(b.getInternalName());
    }
  };
  /**
   * Used to resolve obfuscated type tokens.
   */
  private final Map<String, Type> typeTokens = new HashMap<String, Type>();
  /**
   * The type {@link Object}.
   */
  private final Type objectType = Type.getObjectType("java/lang/Object");
  /**
   * Maps obfuscated operation names to dispatch information.
   */
  private final Map<OperationKey, OperationData> operationData =
      new HashMap<OperationKey, OperationData>();
  private final ErrorContext parentLogger;
  private boolean poisoned;
  /**
   * The type {@link Request}.
   */
  private final Type requestIntf = Type.getType(Request.class);

  /**
   * The type {@link RequestContext}.
   */
  private final Type requestContextIntf = Type.getType(RequestContext.class);

  /**
   * A map of a type to all types that it could be assigned to.
   */
  private final Map<Type, List<Type>> supertypes = new HashMap<Type, List<Type>>();

  /**
   * The type {@link ValueProxy}.
   */
  private final Type valueProxyIntf = Type.getType(ValueProxy.class);

  /**
   * A set to prevent re-validation of a type.
   */
  private final Set<String> validatedTypes = new HashSet<String>();

  /**
   * Contains vaue types (e.g. Integer).
   */
  private final Set<Type> valueTypes = new HashSet<Type>();

  /**
   * Maps a domain object to the type returned from its getId method.
   */
  private final Map<Type, Type> unresolvedKeyTypes = new HashMap<Type, Type>();

  {
    for (Class<?> clazz : VALUE_TYPES) {
      valueTypes.add(Type.getType(clazz));
    }
  }

  public RequestFactoryInterfaceValidator(Logger logger, Loader loader) {
    this.parentLogger = new ErrorContext(logger);
    parentLogger.setValidator(this);
    this.loader = loader;
  }

  /**
   * Visible for testing.
   */
  RequestFactoryInterfaceValidator(ErrorContext errorContext, Loader loader) {
    this.parentLogger = errorContext;
    this.loader = loader;
    errorContext.setValidator(this);
  }

  /**
   * Reset the poisoned status of the validator so that it may be reused without
   * destroying cached state.
   */
  public void antidote() {
    poisoned = false;
  }

  public Deobfuscator getDeobfuscator() {
    return new Deobfuscator.Builder().addClientToDomainMappings(domainToClientType)
        .addOperationData(operationData).addTypeTokens(typeTokens).build();
  }

  /**
   * Returns true if validation failed.
   */
  public boolean isPoisoned() {
    return poisoned;
  }

  /**
   * This method checks an EntityProxy interface against its peer domain object
   * to determine if the server code would be able to process a request using
   * the methods defined in the EntityProxy interface. It does not perform any
   * checks as to whether or not the EntityProxy could actually be generated by
   * the Generator.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements EntityProxy</li>
   * <li><code>binaryName</code> has a {@link ProxyFor} or {@link ProxyForName}
   * annotation</li>
   * <li>The domain object has getId() and getVersion() methods</li>
   * <li>All property methods in the EntityProxy can be mapped onto an
   * equivalent domain method (unless validation is skipped for the method)</li>
   * <li>All referenced proxy types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          EntityProxy subtype
   */
  public void validateEntityProxy(String binaryName) {
    validateProxy(binaryName, entityProxyIntf, true);
  }

  /**
   * Determine if the specified type implements a proxy interface and apply the
   * appropriate validations. This can be used as a general-purpose entry method
   * when writing unit tests.
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          EntityProxy or ValueProxy subtype
   */
  public void validateProxy(String binaryName) {
    /*
     * Don't call fastFail() here or the proxy may not be validated, since
     * validateXProxy delegates to validateProxy() which would re-check.
     */
    Type proxyType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    if (isAssignable(parentLogger, entityProxyIntf, proxyType)) {
      validateEntityProxy(binaryName);
    } else if (isAssignable(parentLogger, valueProxyIntf, proxyType)) {
      validateValueProxy(binaryName);
    } else {
      parentLogger.poison("%s is neither an %s nor a %s", print(proxyType), print(entityProxyIntf),
          print(valueProxyIntf));
    }
  }

  /**
   * This method checks a RequestContext interface against its peer domain
   * domain object to determine if the server code would be able to process a
   * request using the the methods defined in the RequestContext interface. It
   * does not perform any checks as to whether or not the RequestContext could
   * actually be generated by the Generator.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements RequestContext</li>
   * <li><code>binaryName</code> has a {@link Service} or {@link ServiceName}
   * annotation</li>
   * <li>All service methods in the RequestContext can be mapped onto an
   * equivalent domain method (unless validation is skipped for the method)</li>
   * <li>All referenced EntityProxy types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          RequestContext subtype
   * @see #validateEntityProxy(String)
   */
  public void validateRequestContext(String binaryName) {
    if (fastFail(binaryName)) {
      return;
    }

    Type requestContextType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    final ErrorContext logger = parentLogger.setType(requestContextType);

    // Quick sanity check for calling code
    if (!isAssignable(logger, requestContextIntf, requestContextType)) {
      logger.poison("%s is not a %s", print(requestContextType), RequestContext.class
          .getSimpleName());
      return;
    }

    Type domainServiceType = getDomainType(logger, requestContextType, false);
    if (domainServiceType == errorType) {
      logger.poison("The type %s must be annotated with a @%s or @%s annotation", BinaryName
          .toSourceName(binaryName), Service.class.getSimpleName(), ServiceName.class
          .getSimpleName());
      return;
    }

    for (RFMethod method : getMethodsInHierarchy(logger, requestContextType)) {
      // Ignore methods in RequestContext itself
      if (findCompatibleMethod(logger, requestContextIntf, method, false, true, true) != null) {
        continue;
      }

      // Check the client method against the domain
      Method found =
          checkClientMethodInDomain(logger, method, domainServiceType, !clientToLocatorMap
              .containsKey(requestContextType));
      if (found != null) {
        OperationKey key = new OperationKey(binaryName, method.getName(), method.getDescriptor());
        OperationData data =
            new OperationData.Builder().setClientMethodDescriptor(method.getDescriptor())
                .setDomainMethodDescriptor(found.getDescriptor()).setMethodName(method.getName())
                .setRequestContext(requestContextType.getClassName()).build();
        operationData.put(key, data);
      }
      maybeCheckReferredProxies(logger, method);
    }

    maybeCheckExtraTypes(logger, requestContextType);
    checkUnresolvedKeyTypes(logger);
  }

  /**
   * This method checks a RequestFactory interface.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs. It does not perform any
   * checks as to whether or not the RequestContext could actually be generated
   * by the Generator.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements RequestFactory</li>
   * <li>All referenced RequestContext types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          RequestContext subtype
   * @see #validateRequestContext(String)
   */
  public void validateRequestFactory(String binaryName) {
    if (fastFail(binaryName)) {
      return;
    }

    Type requestFactoryType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    ErrorContext logger = parentLogger.setType(requestFactoryType);

    // Quick sanity check for calling code
    if (!isAssignable(logger, Type.getType(RequestFactory.class), requestFactoryType)) {
      logger.poison("%s is not a %s", print(requestFactoryType), RequestFactory.class
          .getSimpleName());
      return;
    }

    // Validate each RequestContext method in the RF
    for (Method contextMethod : getMethodsInHierarchy(logger, requestFactoryType)) {
      Type returnType = contextMethod.getReturnType();
      if (isAssignable(logger, requestContextIntf, returnType)) {
        validateRequestContext(returnType.getClassName());
      }
    }

    maybeCheckExtraTypes(logger, requestFactoryType);
  }

  /**
   * This method checks a ValueProxy interface against its peer domain object to
   * determine if the server code would be able to process a request using the
   * methods defined in the ValueProxy interface. It does not perform any checks
   * as to whether or not the ValueProxy could actually be generated by the
   * Generator.
   * <p>
   * This method may be called repeatedly on a single instance of the validator.
   * Doing so will amortize type calculation costs.
   * <p>
   * Checks implemented:
   * <ul>
   * <li> <code>binaryName</code> implements ValueProxy</li>
   * <li><code>binaryName</code> has a {@link ProxyFor} or {@link ProxyForName}
   * annotation</li>
   * <li>All property methods in the EntityProxy can be mapped onto an
   * equivalent domain method (unless validation is skipped for the method)</li>
   * <li>All referenced proxy types are valid</li>
   * </ul>
   * 
   * @param binaryName the binary name (e.g. {@link Class#getName()}) of the
   *          EntityProxy subtype
   */
  public void validateValueProxy(String binaryName) {
    validateProxy(binaryName, valueProxyIntf, false);
  }

  /**
   * Record the mapping of a domain type to a client type. Proxy types will be
   * added to {@link #domainToClientType}.
   */
  private void addToDomainMap(ErrorContext logger, Type domainType, Type clientType) {
    clientToDomainType.put(clientType, domainType);

    if (isAssignable(logger, baseProxyIntf, clientType)) {
      SortedSet<Type> list = domainToClientType.get(domainType);
      if (list == null) {
        list = new TreeSet<Type>(typeNameComparator);
        domainToClientType.put(domainType, list);
      }
      list.add(clientType);
    }
  }

  /**
   * Check that a given method RequestContext method declaration can be mapped
   * to the server's domain type.
   */
  private RFMethod checkClientMethodInDomain(ErrorContext logger, RFMethod method,
      Type domainServiceType, boolean requireStaticMethodsForRequestType) {
    logger = logger.setMethod(method);

    // Create a "translated" method declaration to search for
    // Request<BlahProxy> foo(int a, BarProxy bar) -> Blah foo(int a, Bar bar);
    Type returnType = getReturnType(logger, method);
    Method searchFor =
        createDomainMethod(logger, new Method(method.getName(), returnType, method
            .getArgumentTypes()));

    RFMethod found =
        findCompatibleServiceMethod(logger, domainServiceType, searchFor, !method
            .isValidationSkipped());

    if (found != null) {
      boolean isInstance = isAssignable(logger, instanceRequestIntf, method.getReturnType());
      if (isInstance && found.isDeclaredStatic()) {
        logger.poison("The method %s is declared to return %s, but the"
            + " service method is static", method.getName(), InstanceRequest.class
            .getCanonicalName());
      } else if (requireStaticMethodsForRequestType && !isInstance && !found.isDeclaredStatic()) {
        logger.poison("The method %s is declared to return %s, but the"
            + " service method is not static", method.getName(), Request.class.getCanonicalName());
      }
    }
    return found;
  }

  /**
   * Check that the domain object has <code>getId()</code> and
   * <code>getVersion</code> methods.
   */
  private void checkIdAndVersion(ErrorContext logger, Type domainType) {
    if (objectType.equals(domainType)) {
      return;
    }
    logger = logger.setType(domainType);
    String findMethodName = "find" + BinaryName.getShortClassName(domainType.getClassName());
    Type keyType = null;
    RFMethod findMethod = null;

    boolean foundFind = false;
    boolean foundId = false;
    boolean foundVersion = false;
    for (RFMethod method : getMethodsInHierarchy(logger, domainType)) {
      if ("getId".equals(method.getName()) && method.getArgumentTypes().length == 0) {
        foundId = true;
        keyType = method.getReturnType();
        if (!isResolvedKeyType(logger, keyType)) {
          unresolvedKeyTypes.put(domainType, keyType);
        }
      } else if ("getVersion".equals(method.getName()) && method.getArgumentTypes().length == 0) {
        foundVersion = true;
        if (!isResolvedKeyType(logger, method.getReturnType())) {
          unresolvedKeyTypes.put(domainType, method.getReturnType());
        }
      } else if (findMethodName.equals(method.getName()) && method.getArgumentTypes().length == 1) {
        foundFind = true;
        findMethod = method;
      }
      if (foundFind && foundId && foundVersion) {
        break;
      }
    }
    if (!foundId) {
      logger.poison("There is no getId() method in type %s", print(domainType));
    }
    if (!foundVersion) {
      logger.poison("There is no getVersion() method in type %s", print(domainType));
    }

    if (foundFind) {
      if (keyType != null && !isAssignable(logger, findMethod.getArgumentTypes()[0], keyType)) {
        logger.poison("The key type returned by %s getId()"
            + " cannot be used as the argument to %s(%s)", print(keyType), findMethod.getName(),
            print(findMethod.getArgumentTypes()[0]));
      }
      if (!findMethod.isDeclaredStatic()) {
        logger.poison("The %s method must be static", findMethodName);
      }
    } else {
      logger.poison("There is no %s method in type %s that returns %2$s", findMethodName,
          print(domainType));
    }
  }

  /**
   * Ensure that the given property method on an EntityProxy exists on the
   * domain object.
   */
  private void checkPropertyMethod(ErrorContext logger, RFMethod clientPropertyMethod,
      Type domainType) {
    logger = logger.setMethod(clientPropertyMethod);

    findCompatiblePropertyMethod(logger, domainType, createDomainMethod(logger,
        clientPropertyMethod), !clientPropertyMethod.isValidationSkipped());
  }

  private void checkUnresolvedKeyTypes(ErrorContext logger) {
    unresolvedKeyTypes.values().removeAll(domainToClientType.keySet());
    if (unresolvedKeyTypes.isEmpty()) {
      return;
    }

    for (Map.Entry<Type, Type> type : unresolvedKeyTypes.entrySet()) {
      logger.setType(type.getKey()).poison(
          "The domain type %s uses  a non-simple key type (%s)"
              + " in its getId() or getVersion() method that" + " does not have a proxy mapping.",
          print(type.getKey()), print(type.getValue()));
    }
  }

  /**
   * Convert a method declaration using client types (e.g. FooProxy) to domain
   * types (e.g. Foo).
   */
  private Method createDomainMethod(ErrorContext logger, Method clientMethod) {
    Type[] args = clientMethod.getArgumentTypes();
    for (int i = 0, j = args.length; i < j; i++) {
      args[i] = getDomainType(logger, args[i], true);
    }
    Type returnType = getDomainType(logger, clientMethod.getReturnType(), true);
    return new Method(clientMethod.getName(), returnType, args);
  }

  /**
   * Common checks to quickly determine if a type needs to be checked.
   */
  private boolean fastFail(String binaryName) {
    if (!Name.isBinaryName(binaryName)) {
      parentLogger.poison("%s is not a binary name", binaryName);
      return true;
    }

    // Allow the poisoned flag to be reset without losing data
    if (badTypes.contains(binaryName)) {
      parentLogger.poison("Type type %s was previously marked as bad", binaryName);
      return true;
    }

    // Don't revalidate the same type
    if (!validatedTypes.add(binaryName)) {
      return true;
    }
    return false;
  }

  /**
   * Finds a compatible method declaration in <code>domainType</code>'s
   * hierarchy that is assignment-compatible with the given Method.
   */
  private RFMethod findCompatibleMethod(final ErrorContext logger, Type domainType,
      Method searchFor, boolean mustFind, boolean allowOverloads, boolean boxReturnTypes) {
    String methodName = searchFor.getName();
    Type[] clientArgs = searchFor.getArgumentTypes();
    Type clientReturnType = searchFor.getReturnType();
    if (boxReturnTypes) {
      clientReturnType = maybeBoxType(clientReturnType);
    }
    // Pull all methods out of the domain type
    Map<String, List<RFMethod>> domainLookup = new LinkedHashMap<String, List<RFMethod>>();
    for (RFMethod method : getMethodsInHierarchy(logger, domainType)) {
      List<RFMethod> list = domainLookup.get(method.getName());
      if (list == null) {
        list = new ArrayList<RFMethod>();
        domainLookup.put(method.getName(), list);
      }
      list.add(method);
    }

    // Find the matching method in the domain object
    List<RFMethod> methods = domainLookup.get(methodName);
    if (methods == null) {
      if (mustFind) {
        logger.poison("Could not find any methods named %s in %s", methodName, print(domainType));
      }
      return null;
    }
    if (methods.size() > 1 && !allowOverloads) {
      StringBuilder sb = new StringBuilder();
      sb.append(String.format("Method overloads found in type %s named %s:\n", print(domainType),
          methodName));
      for (RFMethod method : methods) {
        sb.append("  ").append(print(method)).append("\n");
      }
      logger.poison(sb.toString());
      return null;
    }

    // Check each overloaded name
    for (RFMethod domainMethod : methods) {
      Type[] domainArgs = domainMethod.getArgumentTypes();
      Type domainReturnType = domainMethod.getReturnType();
      if (boxReturnTypes) {
        /*
         * When looking for the implementation of a Request<Integer>, we want to
         * match either int or Integer, so we'll box the domain method's return
         * type.
         */
        domainReturnType = maybeBoxType(domainReturnType);
      }

      /*
       * Make sure the client args can be passed into the domain args and the
       * domain return type into the client return type.
       */
      if (isAssignable(logger, domainArgs, clientArgs)
          && isAssignable(logger, clientReturnType, domainReturnType)) {

        logger.spam("Mapped client method " + print(searchFor) + " to " + print(domainMethod));
        return domainMethod;
      }
    }
    if (mustFind) {
      logger.poison(messageCouldNotFindMethod(domainType, methods));
    }
    return null;
  }

  /**
   * Finds a compatible method declaration in <code>domainType</code>'s
   * hierarchy that is assignment-compatible with the given Method.
   */
  private RFMethod findCompatiblePropertyMethod(final ErrorContext logger, Type domainType,
      Method searchFor, boolean mustFind) {
    return findCompatibleMethod(logger, domainType, searchFor, mustFind, false, false);
  }

  /**
   * Finds a compatible method declaration in <code>domainType</code>'s
   * hierarchy that is assignment-compatible with the given Method.
   */
  private RFMethod findCompatibleServiceMethod(final ErrorContext logger, Type domainType,
      Method searchFor, boolean mustFind) {
    return findCompatibleMethod(logger, domainType, searchFor, mustFind, true, true);
  }

  /**
   * This looks like it should be a utility method somewhere else, but I can't
   * find it.
   */
  private Type getBoxedType(Type primitive) {
    switch (primitive.getSort()) {
      case Type.BOOLEAN:
        return Type.getType(Boolean.class);
      case Type.BYTE:
        return Type.getType(Byte.class);
      case Type.CHAR:
        return Type.getType(Character.class);
      case Type.DOUBLE:
        return Type.getType(Double.class);
      case Type.FLOAT:
        return Type.getType(Float.class);
      case Type.INT:
        return Type.getType(Integer.class);
      case Type.LONG:
        return Type.getType(Long.class);
      case Type.SHORT:
        return Type.getType(Short.class);
      case Type.VOID:
        return Type.getType(Void.class);
    }
    throw new RuntimeException(primitive.getDescriptor() + " is not a primitive type");
  }

  /**
   * Convert the type used in a client-side EntityProxy or RequestContext
   * declaration to the equivalent domain type. Value types and supported
   * collections are a pass-through. EntityProxy types will be resolved to their
   * domain object type. RequestContext types will be resolved to their service
   * object.
   */
  private Type getDomainType(ErrorContext logger, Type clientType, boolean requireMapping) {
    Type domainType = clientToDomainType.get(clientType);
    if (domainType != null) {
      return domainType;
    }
    if (isValueType(logger, clientType) || isCollectionType(logger, clientType)) {
      domainType = clientType;
    } else if (entityProxyIntf.equals(clientType) || valueProxyIntf.equals(clientType)) {
      domainType = objectType;
    } else {
      logger = logger.setType(clientType);
      DomainMapper pv = new DomainMapper(logger);
      visit(logger, clientType.getInternalName(), pv);
      if (pv.getDomainInternalName() == null) {
        if (requireMapping) {
          logger.poison("%s has no mapping to a domain type (e.g. @%s or @%s)", print(clientType),
              ProxyFor.class.getSimpleName(), Service.class.getSimpleName());
        }
        domainType = errorType;
      } else {
        domainType = Type.getObjectType(pv.getDomainInternalName());
      }
      if (pv.getLocatorInternalName() != null) {
        Type locatorType = Type.getObjectType(pv.getLocatorInternalName());
        clientToLocatorMap.put(clientType, locatorType);
      }
    }
    addToDomainMap(logger, domainType, clientType);
    if (domainType != errorType) {
      maybeCheckProxyType(logger, clientType);
    }
    return domainType;
  }

  /**
   * Collect all of the methods defined within a type hierarchy.
   */
  private Set<RFMethod> getMethodsInHierarchy(ErrorContext logger, Type domainType) {
    Set<RFMethod> toReturn = methodsInHierarchy.get(domainType);
    if (toReturn == null) {
      logger = logger.setType(domainType);
      toReturn = new MethodsInHierarchyCollector(logger).exec(domainType.getInternalName());
      methodsInHierarchy.put(domainType, Collections.unmodifiableSet(toReturn));
    }
    return toReturn;
  }

  /**
   * Examines a generic RequestContext method declaration and determines the
   * expected domain return type. This implementation is limited in that it will
   * not attempt to resolve type bounds since that would essentially require
   * implementing TypeOracle. In the case where the type bound cannot be
   * resolved, this method will return Object's type.
   */
  private Type getReturnType(ErrorContext logger, RFMethod method) {
    logger = logger.setMethod(method);
    final String[] returnType = {objectType.getInternalName()};
    String signature = method.getSignature();

    final int expectedCount;
    if (method.getReturnType().equals(instanceRequestIntf)) {
      expectedCount = 2;
    } else if (method.getReturnType().equals(requestIntf)) {
      expectedCount = 1;
    } else {
      logger.spam("Punting on " + signature);
      return Type.getObjectType(returnType[0]);
    }

    // TODO(bobv): If a class-based TypeOracle is built, use that instead
    new SignatureReader(signature).accept(new SignatureAdapter() {
      @Override
      public SignatureVisitor visitReturnType() {
        return new SignatureAdapter() {
          int count;

          @Override
          public SignatureVisitor visitTypeArgument(char wildcard) {
            if (++count == expectedCount) {
              return new SignatureAdapter() {
                @Override
                public void visitClassType(String name) {
                  returnType[0] = name;
                }
              };
            }
            return super.visitTypeArgument(wildcard);
          }
        };
      }
    });

    logger.spam("Extracted " + returnType[0]);
    return Type.getObjectType(returnType[0]);
  }

  private List<Type> getSupertypes(ErrorContext logger, Type type) {
    if (type.getSort() != Type.OBJECT) {
      return Collections.emptyList();
    }
    List<Type> toReturn = supertypes.get(type);
    if (toReturn != null) {
      return toReturn;
    }

    logger = logger.setType(type);

    toReturn = new SupertypeCollector(logger).exec(type);
    supertypes.put(type, Collections.unmodifiableList(toReturn));
    return toReturn;
  }

  private boolean isAssignable(ErrorContext logger, Type possibleSupertype, Type possibleSubtype) {
    // Fast-path for same type
    if (possibleSupertype.equals(possibleSubtype)) {
      return true;
    }

    // Supertype calculation is cached
    List<Type> allSupertypes = getSupertypes(logger, possibleSubtype);
    return allSupertypes.contains(possibleSupertype);
  }

  private boolean isAssignable(ErrorContext logger, Type[] possibleSupertypes,
      Type[] possibleSubtypes) {
    // Check the same number of types
    if (possibleSupertypes.length != possibleSubtypes.length) {
      return false;
    }
    for (int i = 0, j = possibleSupertypes.length; i < j; i++) {
      if (!isAssignable(logger, possibleSupertypes[i], possibleSubtypes[i])) {
        return false;
      }
    }
    return true;
  }

  private boolean isCollectionType(@SuppressWarnings("unused") ErrorContext logger, Type type) {
    // keeping the logger arg just for internal consistency for our small minds
    return "java/util/List".equals(type.getInternalName())
        || "java/util/Set".equals(type.getInternalName());
  }

  /**
   * Keep in sync with {@code ReflectiveServiceLayer.isKeyType()}.
   */
  private boolean isResolvedKeyType(ErrorContext logger, Type type) {
    if (isValueType(logger, type)) {
      return true;
    }

    // We have already seen a mapping for the key type
    if (domainToClientType.containsKey(type)) {
      return true;
    }

    return false;
  }

  private boolean isValueType(ErrorContext logger, Type type) {
    if (type.getSort() != Type.OBJECT) {
      return true;
    }
    if (valueTypes.contains(type)) {
      return true;
    }
    logger = logger.setType(type);
    if (isAssignable(logger, enumType, type)) {
      return true;
    }
    return false;
  }

  private Type maybeBoxType(Type maybePrimitive) {
    if (maybePrimitive.getSort() == Type.OBJECT) {
      return maybePrimitive;
    }
    return getBoxedType(maybePrimitive);
  }

  /**
   * Examines a type for an {@link ExtraTypes} annotation and processes the
   * referred types.
   */
  private void maybeCheckExtraTypes(ErrorContext logger, Type type) {
    maybeCheckProxyType(logger, new ExtraTypesCollector(logger.setType(type)).exec(type));
  }

  /**
   * Examine an array of Types and call {@link #validateEntityProxy(String)} or
   * {@link #validateValueProxy(String)} if the type is a proxy.
   */
  private void maybeCheckProxyType(ErrorContext logger, Type... types) {
    for (Type type : types) {
      if (isAssignable(logger, entityProxyIntf, type)) {
        validateEntityProxy(type.getClassName());
      } else if (isAssignable(logger, valueProxyIntf, type)) {
        validateValueProxy(type.getClassName());
      } else if (isAssignable(logger, baseProxyIntf, type)) {
        logger.poison(
            "Invalid type hierarchy for %s. Only types derived from %s or %s may be used.",
            print(type), print(entityProxyIntf), print(valueProxyIntf));
      }
    }
  }

  /**
   * Examine the arguments and return value of a method and check any
   * EntityProxies referred.
   */
  private void maybeCheckReferredProxies(ErrorContext logger, RFMethod method) {
    if (method.getSignature() != null) {
      TypesInSignatureCollector collector = new TypesInSignatureCollector();
      SignatureReader reader = new SignatureReader(method.getSignature());
      reader.accept(collector);
      maybeCheckProxyType(logger, collector.getFound());
    } else {
      Type[] argTypes = method.getArgumentTypes();
      Type returnType = getReturnType(logger, method);

      // Check EntityProxy args ond return types against the domain
      maybeCheckProxyType(logger, argTypes);
      maybeCheckProxyType(logger, returnType);
    }
  }

  /**
   * Returns {@code true} if the type is assignable to EntityProxy or ValueProxy
   * and has a mapping to a domain type.
   * 
   * @see com.google.web.bindery.requestfactory.gwt.rebind.model.RequestFactoryModel#shouldAttemptProxyValidation()
   */
  private boolean shouldAttemptProxyValidation(ErrorContext logger, Type type) {
    logger = logger.setType(type);
    if (!isAssignable(logger, entityProxyIntf, type) && !isAssignable(logger, valueProxyIntf, type)) {
      return false;
    }
    if (getDomainType(logger, type, false) == errorType) {
      return false;
    }
    return true;
  }

  private void validateProxy(String binaryName, Type expectedType, boolean requireId) {
    if (fastFail(binaryName)) {
      return;
    }

    Type proxyType = Type.getObjectType(BinaryName.toInternalName(binaryName));
    typeTokens.put(OperationKey.hash(binaryName), proxyType);
    ErrorContext logger = parentLogger.setType(proxyType);

    // Quick sanity check for calling code
    if (!isAssignable(logger, expectedType, proxyType)) {
      parentLogger.poison("%s is not a %s", print(proxyType), print(expectedType));
      return;
    }

    // Check supertypes first
    for (Type supertype : getSupertypes(logger, proxyType)) {
      if (shouldAttemptProxyValidation(logger, supertype)) {
        maybeCheckProxyType(logger, supertype);
      }
    }

    // Find the domain type
    Type domainType = getDomainType(logger, proxyType, false);
    if (domainType == errorType) {
      logger.poison("The type %s must be annotated with a @%s or @%s annotation", BinaryName
          .toSourceName(binaryName), ProxyFor.class.getSimpleName(), ProxyForName.class
          .getSimpleName());
      return;
    }

    // Check for getId() and getVersion() in domain if no locator is specified
    if (requireId) {
      Type locatorType = clientToLocatorMap.get(proxyType);
      if (locatorType == null) {
        checkIdAndVersion(logger, domainType);
      }
    }

    // Collect all methods in the client proxy type
    Set<RFMethod> clientPropertyMethods = getMethodsInHierarchy(logger, proxyType);

    // Find the equivalent domain getter/setter method
    for (RFMethod clientPropertyMethod : clientPropertyMethods) {
      // Ignore stableId(). Can't use descriptor due to overrides
      if ("stableId".equals(clientPropertyMethod.getName())
          && clientPropertyMethod.getArgumentTypes().length == 0) {
        continue;
      }
      checkPropertyMethod(logger, clientPropertyMethod, domainType);
      maybeCheckReferredProxies(logger, clientPropertyMethod);
    }
    maybeCheckExtraTypes(logger, proxyType);
  }

  /**
   * Load the classfile for the given binary name and apply the provided
   * visitor.
   * 
   * @return <code>true</code> if the visitor was successfully visited
   */
  private boolean visit(ErrorContext logger, String internalName, ClassVisitor visitor) {
    assert Name.isInternalName(internalName) : "internalName";
    logger.spam("Visiting " + internalName);
    InputStream inputStream = null;
    try {
      inputStream = loader.getResourceAsStream(internalName + ".class");
      if (inputStream == null) {
        logger.poison("Could not find class file for " + internalName);
        return false;
      }
      ClassReader reader = new ClassReader(inputStream);
      reader.accept(visitor, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG
          | ClassReader.SKIP_FRAMES);
      return true;
    } catch (IOException e) {
      logger.poison("Unable to open " + internalName, e);
    } finally {
      if (inputStream != null) {
        try {
          inputStream.close();
        } catch (IOException ignored) {
        }
      }
    }
    return false;
  }
}
