/*
 * Copyright 2008 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.gwt.dev.shell;

import com.google.gwt.core.client.GWTBridge;
import com.google.gwt.core.client.GwtScriptOnly;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.javac.CompilationProblemReporter;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.javac.CompilationUnit;
import com.google.gwt.dev.javac.CompiledClass;
import com.google.gwt.dev.javac.JsniMethod;
import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.shell.rewrite.HasAnnotation;
import com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter;
import com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter.InstanceMethodOracle;
import com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter.SingleJsoImplData;
import com.google.gwt.dev.util.JsniRef;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Name.InternalName;
import com.google.gwt.dev.util.Name.SourceOrBinaryName;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.collect.MapMaker;
import com.google.gwt.util.tools.Utility;

import java.beans.Beans;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.Stack;
import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantLock;

/**
 * An isolated {@link ClassLoader} for running all user code. All user files are
 * compiled from source code byte a {@link ByteCodeCompiler}. After compilation,
 * some byte code rewriting is performed to support
 * <code>JavaScriptObject</code> and its subtypes.
 * 
 * TODO: we should refactor this class to move the getClassInfoByDispId,
 * getDispId, getMethodDispatch and putMethodDispatch into a separate entity
 * since they really do not interact with the CompilingClassLoader
 * functionality.
 */
public final class CompilingClassLoader extends ClassLoader implements
    DispatchIdOracle {

  /**
   * Oracle that can answer questions about {@link DispatchClassInfo
   * DispatchClassInfos}.
   */
  private final class DispatchClassInfoOracle {

    /**
     * Class identifier to DispatchClassInfo mapping.
     */
    private final ArrayList<DispatchClassInfo> classIdToClassInfo = new ArrayList<DispatchClassInfo>();

    /**
     * Binary or source class name to DispatchClassInfo map.
     */
    private final Map<String, DispatchClassInfo> classNameToClassInfo = new HashMap<String, DispatchClassInfo>();

    /**
     * Clears out the contents of this oracle.
     */
    public synchronized void clear() {
      classIdToClassInfo.clear();
      classNameToClassInfo.clear();
    }

    /**
     * Returns the {@link DispatchClassInfo} for a given dispatch id.
     * 
     * @param dispId dispatch id
     * @return DispatchClassInfo for the requested dispatch id
     */
    public synchronized DispatchClassInfo getClassInfoByDispId(int dispId) {
      int classId = extractClassIdFromDispId(dispId);

      return classIdToClassInfo.get(classId);
    }

    /**
     * Returns the dispatch id for a given member reference. Member references
     * can be encoded as: "@class::field" or "@class::method(typesigs)".
     * 
     * @param jsniMemberRef a string encoding a JSNI member to use
     * @return integer encoded as ((classId << 16) | memberId)
     */
    public synchronized int getDispId(String jsniMemberRef) {
      /*
       * Map JS toString() onto the Java toString() method.
       */
      if (jsniMemberRef.equals("toString")) {
        jsniMemberRef = "@java.lang.Object::toString()";
      }

      JsniRef parsed = JsniRef.parse(jsniMemberRef);
      if (parsed == null) {
        logger.log(TreeLogger.ERROR, "Malformed JSNI reference '"
            + jsniMemberRef + "'; expect subsequent failures",
            new NoSuchFieldError(jsniMemberRef));
        return -1;
      }

      // Do the lookup by class name.
      String className = parsed.className();
      DispatchClassInfo dispClassInfo = getClassInfoFromClassName(className);
      if (dispClassInfo != null) {
        String memberName = parsed.memberSignature();

        /*
         * Disallow the use of JSNI references to SingleJsoImpl interface
         * methods. This policy is due to web-mode dispatch implementation
         * details; resolving the JSNI reference wouldn't be just be a name
         * replacement, instead it would be necessary to significantly alter the
         * semantics of the hand-written JS.
         */
        if (singleJsoImplTypes.contains(canonicalizeClassName(className))) {
          logger.log(TreeLogger.ERROR,
              "Invalid JSNI reference to SingleJsoImpl interface (" + className
                  + "); consider using a trampoline. "
                  + "Expect subsequent failures.", new NoSuchFieldError(
                  jsniMemberRef));
          return -1;
        }

        int memberId = dispClassInfo.getMemberId(memberName);
        if (memberId < 0) {
          if (!className.startsWith("java.")) {
            logger.log(TreeLogger.ERROR, "Member '" + memberName
                + "' in JSNI reference '" + jsniMemberRef
                + "' could not be found; expect subsequent failures",
                new NoSuchFieldError(memberName));
          }
        }

        return synthesizeDispId(dispClassInfo.getClassId(), memberId);
      }

      logger.log(TreeLogger.ERROR, "Class '" + className
          + "' in JSNI reference '" + jsniMemberRef
          + "' could not be found; expect subsequent failures",
          new ClassNotFoundException(className));
      return -1;
    }

    /**
     * Extracts the class id from the dispatch id.
     * 
     * @param dispId
     * @return the classId encoded into this dispatch id
     */
    private int extractClassIdFromDispId(int dispId) {
      return (dispId >> 16) & 0xffff;
    }

    /**
     * Returns the {@link java.lang.Class} instance for a given binary class
     * name. It is important to avoid initializing the class because this would
     * potentially cause initializers to be run in a different order than in web
     * mode. Moreover, we may not have injected all of the JSNI code required to
     * initialize the class.
     * 
     * @param binaryClassName the binary name of a class
     * @return {@link java.lang.Class} instance or null if the given binary
     *         class name could not be found
     */
    private Class<?> getClassFromBinaryName(String binaryClassName) {
      int dims = 0;
      while (binaryClassName.endsWith("[]")) {
        dims++;
        binaryClassName = binaryClassName.substring(0,
            binaryClassName.length() - 2);
      }

      Class<?> clazz = primitiveTypes.get(binaryClassName);
      if (clazz == null) {
        try {
          clazz = Class.forName(binaryClassName, false,
              CompilingClassLoader.this);
        } catch (ClassNotFoundException e) {
        }
      }
      // TODO(deprecation): remove this support eventually.
      if (clazz == null && binaryClassName.length() == 1
          && "ZBCDFIJSV".indexOf(binaryClassName.charAt(0)) >= 0) {
        clazz = getDeprecatedPrimitiveType(binaryClassName.charAt(0));
        assert clazz != null;
      }
      if (dims > 0) {
        return Array.newInstance(clazz, new int[dims]).getClass();
      } else {
        return clazz;
      }
    }

    /**
     * Returns the {@link java.lang.Class} object for a class that matches the
     * source or binary name given.
     * 
     * @param className binary or source name
     * @return {@link java.lang.Class} instance, if found, or null
     */
    private Class<?> getClassFromBinaryOrSourceName(String className) {
      // Try the type oracle first
      JClassType type = typeOracle.findType(SourceOrBinaryName.toSourceName(className));
      if (type != null) {
        // Use the type oracle to compute the exact binary name
        String jniSig = type.getJNISignature();
        jniSig = jniSig.substring(1, jniSig.length() - 1);
        className = InternalName.toBinaryName(jniSig);
      }
      return getClassFromBinaryName(className);
    }

    /**
     * Returns the {@link DispatchClassInfo} associated with the class name.
     * Since we allow both binary and source names to be used in JSNI class
     * references, we need to be able to deal with the fact that multiple
     * permutations of the class name with regards to source or binary forms map
     * on the same {@link DispatchClassInfo}.
     * 
     * @param className binary or source name for a class
     * @return {@link DispatchClassInfo} associated with the binary or source
     *         class name; null if there is none
     */
    private DispatchClassInfo getClassInfoFromClassName(String className) {

      DispatchClassInfo dispClassInfo = classNameToClassInfo.get(className);
      if (dispClassInfo != null) {
        // return the cached value
        return dispClassInfo;
      }

      Class<?> cls = getClassFromBinaryOrSourceName(className);
      if (cls == null) {
        /*
         * default to return null; mask the specific error and let the caller
         * handle it
         */
        return null;
      }

      // Map JSO type references to the appropriate impl class.
      if (classRewriter.isJsoIntf(cls.getName())) {
        cls = getClassFromBinaryName(cls.getName() + "$");
      }

      /*
       * we need to create a new DispatchClassInfo since we have never seen this
       * class before under any source or binary class name
       */
      int classId = classIdToClassInfo.size();

      dispClassInfo = new DispatchClassInfo(cls, classId);
      classIdToClassInfo.add(dispClassInfo);

      /*
       * Whether we created a new DispatchClassInfo or not, we need to add a
       * mapping for this name
       */
      classNameToClassInfo.put(className, dispClassInfo);

      return dispClassInfo;
    }

    @Deprecated
    private Class<?> getDeprecatedPrimitiveType(char c) {
      switch (c) {
        case 'Z':
          return boolean.class;
        case 'B':
          return byte.class;
        case 'C':
          return char.class;
        case 'D':
          return double.class;
        case 'F':
          return float.class;
        case 'I':
          return int.class;
        case 'J':
          return long.class;
        case 'S':
          return short.class;
        case 'V':
          return void.class;
        default:
          return null;
      }
    }

    /**
     * Synthesizes a dispatch identifier for the given class and member ids.
     * 
     * @param classId class index
     * @param memberId member index
     * @return dispatch identifier for the given class and member ids
     */
    private int synthesizeDispId(int classId, int memberId) {
      return (classId << 16) | memberId;
    }
  }

  /**
   * A ClassLoader that will delegate to a parent ClassLoader and fall back to
   * loading bytecode as resources from an alternate parent ClassLoader.
   */
  private static class MultiParentClassLoader extends ClassLoader {
    private final ClassLoader resources;

    public MultiParentClassLoader(ClassLoader parent, ClassLoader resources) {
      super(parent);
      assert parent != null;
      this.resources = resources;
    }

    @Override
    protected synchronized Class<?> findClass(String name)
        throws ClassNotFoundException {
      String resourceName = name.replace('.', '/') + ".class";
      URL url = resources.getResource(resourceName);
      if (url == null) {
        throw new ClassNotFoundException();
      }
      byte[] bytes = Util.readURLAsBytes(url);
      return defineClass(name, bytes, 0, bytes.length);
    }
    
    @Override
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
      try {
        Class c = findLoadedClass(name);
        if (c != null) {
          if (resolve) {
            resolveClass(c);
          }
          return c;
        }
        return getParent().loadClass(name);
      } catch (Throwable t) {
        // Make a second attempt not only on ClassNotFoundExceptions, but also errors like 
        // ClassCircularityError
        Class c = findClass(name);
        if (resolve) {
          resolveClass(c);
        }
        return c;
      }
    }    
  }

  /**
   * Implements {@link InstanceMethodOracle} on behalf of the
   * {@link HostedModeClassRewriter}. Implemented using {@link TypeOracle}.
   */
  private class MyInstanceMethodOracle implements InstanceMethodOracle {

    private final Map<String, Set<JClassType>> signatureToDeclaringClasses = new HashMap<String, Set<JClassType>>();

    public MyInstanceMethodOracle(Set<JClassType> jsoTypes,
        JClassType javaLangObject, SingleJsoImplData jsoData) {

      // Record that the JSO implements its own methods
      for (JClassType type : jsoTypes) {
        for (JMethod method : type.getMethods()) {
          if (!method.isStatic()) {
            assert !method.isAbstract() : "Abstract method in JSO type "
                + method;
            add(type, method);
          }
        }
      }

      /*
       * Record the implementing types for methods defined in SingleJsoImpl
       * interfaces. We have to make this pass because of possible variance in
       * the return types between the abstract method declaration in the
       * interface and the concrete method.
       */
      for (String intfName : jsoData.getSingleJsoIntfTypes()) {
        // We only store the name in the data block to keep it lightweight
        JClassType intf = typeOracle.findType(Name.InternalName.toSourceName(intfName));
        JClassType jso = typeOracle.getSingleJsoImpl(intf);
        for (JMethod method : intf.getMethods()) {
          JClassType implementingJso = findImplementingTypeForMethod(jso,
              method);
          assert implementingJso != null : "Jso should contain method: "
              + method.getJsniSignature();
          add(implementingJso, method);
        }
      }

      // Object clobbers everything.
      for (JMethod method : javaLangObject.getMethods()) {
        if (!method.isStatic()) {
          String signature = createSignature(method);
          Set<JClassType> declaringClasses = new HashSet<JClassType>();
          signatureToDeclaringClasses.put(signature, declaringClasses);
          declaringClasses.add(javaLangObject);
        }
      }
    }

    public String findOriginalDeclaringClass(String desc, String signature) {
      // Lookup the method.
      Set<JClassType> declaringClasses = signatureToDeclaringClasses.get(signature);
      assert declaringClasses != null : "No classes for " + signature;
      if (declaringClasses.size() == 1) {
        // Shortcut: if there's only one answer, it must be right.
        return createDescriptor(declaringClasses.iterator().next());
      }
      // Must check for assignability.
      String sourceName = desc.replace('/', '.');
      sourceName = sourceName.replace('$', '.');
      JClassType declaredType = typeOracle.findType(sourceName);

      // Check if I declare this directly.
      if (declaringClasses.contains(declaredType)) {
        return desc;
      }

      // Check to see what type I am assignable to.
      for (JClassType possibleSupertype : declaringClasses) {
        if (declaredType.isAssignableTo(possibleSupertype)) {
          return createDescriptor(possibleSupertype);
        }
      }
      throw new IllegalArgumentException("Could not resolve signature '"
          + signature + "' from class '" + desc + "'");
    }

    /**
     * Record that a given JSO type contains the concrete implementation of a
     * (possibly abstract) method.
     */
    private void add(JClassType type, JMethod method) {
      String signature = createSignature(method);
      Set<JClassType> declaringClasses = signatureToDeclaringClasses.get(signature);
      if (declaringClasses == null) {
        declaringClasses = new HashSet<JClassType>();
        signatureToDeclaringClasses.put(signature, declaringClasses);
      }
      declaringClasses.add(type);
    }

    private String createDescriptor(JClassType type) {
      String jniSignature = type.getJNISignature();
      return jniSignature.substring(1, jniSignature.length() - 1);
    }

    private String createSignature(JMethod method) {
      StringBuffer sb = new StringBuffer(method.getName());
      sb.append('(');
      for (JParameter param : method.getParameters()) {
        sb.append(param.getType().getJNISignature());
      }
      sb.append(')');
      sb.append(method.getReturnType().getJNISignature());
      String signature = sb.toString();
      return signature;
    }
  }

  /**
   * Cook up the data we need to support JSO subtypes that implement interfaces
   * with methods. This includes the set of SingleJsoImpl interfaces actually
   * implemented by a JSO type, the mangled method names, and the names of the
   * Methods that should actually implement the virtual functions.
   * 
   * Given the current implementation of JSO$ and incremental execution of
   * rebinds, it's not possible for Generators to produce additional
   * JavaScriptObject subtypes, so this data can remain static.
   */
  private class MySingleJsoImplData implements SingleJsoImplData {
    private final SortedSet<String> mangledNames = new TreeSet<String>();
    private final Map<String, List<com.google.gwt.dev.asm.commons.Method>> mangledNamesToDeclarations = new HashMap<String, List<com.google.gwt.dev.asm.commons.Method>>();
    private final Map<String, List<com.google.gwt.dev.asm.commons.Method>> mangledNamesToImplementations = new HashMap<String, List<com.google.gwt.dev.asm.commons.Method>>();
    private final Set<String> unmodifiableIntfNames = Collections.unmodifiableSet(singleJsoImplTypes);
    private final SortedSet<String> unmodifiableNames = Collections.unmodifiableSortedSet(mangledNames);

    public MySingleJsoImplData() {
      // Loop over all interfaces with JSO implementations
      typeLoop : for (JClassType type : typeOracle.getSingleJsoImplInterfaces()) {
        assert type.isInterface() == type : "Expecting interfaces only";

        /*
         * By preemptively adding all possible mangled names by which a method
         * could be called, we greatly simplify the logic necessary to rewrite
         * the call-site.
         * 
         * interface A {void m();}
         * 
         * interface B extends A {void z();}
         * 
         * becomes
         * 
         * c_g_p_A_m() -> JsoA$.m$()
         * 
         * c_g_p_B_m() -> JsoA$.m$()
         * 
         * c_g_p_B_z() -> JsoB$.z$()
         */
        for (JMethod intfMethod : type.getOverridableMethods()) {
          assert intfMethod.isAbstract() : "Expecting only abstract methods";

          /*
           * It is necessary to locate the implementing type on a per-method
           * basis. Consider the case of
           * 
           * @SingleJsoImpl interface C extends A, B {}
           * 
           * Methods inherited from interfaces A and B must be dispatched to
           * their respective JSO implementations.
           */
          JClassType implementingType = typeOracle.getSingleJsoImpl(intfMethod.getEnclosingType());

          if (implementingType == null || implementingType.isAnnotationPresent(GwtScriptOnly.class)) {
            /*
             * This means that there is no concrete implementation of the
             * interface by a JSO. Any implementation that might be created by a
             * Generator won't be a JSO subtype, so we'll just ignore it as an
             * actionable type. Were Generators ever able to create new JSO
             * subtypes, we'd have to speculatively rewrite the callsite.
             */
            continue typeLoop;
          }

          /*
           * Record the type as being actionable.
           */
          singleJsoImplTypes.add(canonicalizeClassName(getBinaryName(type)));

          /*
           * The mangled name adds the current interface like
           * 
           * com_foo_Bar_methodName
           */
          String mangledName = getBinaryName(type).replace('.', '_') + "_"
              + intfMethod.getName();
          mangledNames.add(mangledName);

          /*
           * Handle virtual overrides by finding the method that we would
           * normally invoke and using its declaring class as the dispatch
           * target.
           */
          JMethod implementingMethod;
          while ((implementingMethod = findOverloadUsingErasure(
              implementingType, intfMethod)) == null) {
            implementingType = implementingType.getSuperclass();
          }
          // implementingmethod and implementingType cannot be null here

          /*
           * Create a pseudo-method declaration for the interface method. This
           * should look something like
           * 
           * ReturnType method$ (ParamType, ParamType)
           * 
           * This must be kept in sync with the WriteJsoImpl class.
           */
          {
            String decl = getBinaryOrPrimitiveName(intfMethod.getReturnType().getErasedType())
                + " " + intfMethod.getName() + "(";
            for (JParameter param : intfMethod.getParameters()) {
              decl += ",";
              decl += getBinaryOrPrimitiveName(param.getType().getErasedType());
            }
            decl += ")";

            com.google.gwt.dev.asm.commons.Method declaration = com.google.gwt.dev.asm.commons.Method.getMethod(decl);
            addToMap(mangledNamesToDeclarations, mangledName, declaration);
          }

          /*
           * Cook up the a pseudo-method declaration for the concrete type. This
           * should look something like
           * 
           * ReturnType method$ (JsoType, ParamType, ParamType)
           * 
           * This must be kept in sync with the WriteJsoImpl class.
           */
          {
            String returnName = getBinaryOrPrimitiveName(implementingMethod.getReturnType().getErasedType());
            String jsoName = getBinaryOrPrimitiveName(implementingType);

            String decl = returnName + " " + intfMethod.getName() + "$ ("
                + jsoName;
            for (JParameter param : implementingMethod.getParameters()) {
              decl += ",";
              decl += getBinaryOrPrimitiveName(param.getType().getErasedType());
            }
            decl += ")";

            com.google.gwt.dev.asm.commons.Method toImplement = com.google.gwt.dev.asm.commons.Method.getMethod(decl);
            addToMap(mangledNamesToImplementations, mangledName, toImplement);
          }
        }
      }

      if (logger.isLoggable(TreeLogger.SPAM)) {
        TreeLogger dumpLogger = logger.branch(TreeLogger.SPAM,
            "SingleJsoImpl method mappings");
        for (Map.Entry<String, List<com.google.gwt.dev.asm.commons.Method>> entry : mangledNamesToImplementations.entrySet()) {
          dumpLogger.log(TreeLogger.SPAM, entry.getKey() + " -> " + entry.getValue());
        }
      }
    }

    public List<com.google.gwt.dev.asm.commons.Method> getDeclarations(
        String mangledName) {
      List<com.google.gwt.dev.asm.commons.Method> toReturn = mangledNamesToDeclarations.get(mangledName);
      return toReturn == null ? null : Collections.unmodifiableList(toReturn);
    }

    public List<com.google.gwt.dev.asm.commons.Method> getImplementations(
        String mangledName) {
      List<com.google.gwt.dev.asm.commons.Method> toReturn = mangledNamesToImplementations.get(mangledName);
      return toReturn == null ? toReturn
          : Collections.unmodifiableList(toReturn);
    }

    public SortedSet<String> getMangledNames() {
      return unmodifiableNames;
    }

    public Set<String> getSingleJsoIntfTypes() {
      return unmodifiableIntfNames;
    }

    /**
     * Assumes that the usual case is a 1:1 mapping.
     */
    private <K, V> void addToMap(Map<K, List<V>> map, K key, V value) {
      List<V> list = map.get(key);
      if (list == null) {
        map.put(key, Lists.create(value));
      } else {
        List<V> maybeOther = Lists.add(list, value);
        if (maybeOther != list) {
          map.put(key, maybeOther);
        }
      }
    }

    /**
     * Looks for a concrete implementation of <code>intfMethod</code> in
     * <code>implementingType</code>.
     */
    private JMethod findOverloadUsingErasure(JClassType implementingType,
        JMethod intfMethod) {

      int numParams = intfMethod.getParameters().length;
      JType[] erasedTypes = new JType[numParams];
      for (int i = 0; i < numParams; i++) {
        erasedTypes[i] = intfMethod.getParameters()[i].getType().getErasedType();
      }

      outer : for (JMethod method : implementingType.getOverloads(intfMethod.getName())) {
        JParameter[] params = method.getParameters();
        if (params.length != numParams) {
          continue;
        }
        for (int i = 0; i < numParams; i++) {
          if (params[i].getType().getErasedType() != erasedTypes[i]) {
            continue outer;
          }
        }
        return method;
      }
      return null;
    }
  }

  /**
   * Only loads bootstrap classes, specifically excluding classes from the classpath. 
   */
  private static final ClassLoader bootstrapClassLoader = new ClassLoader(null) { };
  
  /**
   * The names of the bridge classes.
   */
  private static final Map<String, Class<?>> BRIDGE_CLASS_NAMES = new HashMap<String, Class<?>>();

  /**
   * The set of classes exposed into user space that actually live in hosted
   * space (thus, they bridge across the spaces).
   */
  private static final Class<?>[] BRIDGE_CLASSES = new Class<?>[]{
      // Have to include the shared GWTBridge class since the client one
      // inherits from it, otherwise we get verify errors
      ShellJavaScriptHost.class, GWTBridge.class, com.google.gwt.core.shared.GWTBridge.class};

  private static final boolean CLASS_DUMP = Boolean.getBoolean("gwt.dev.classDump");

  private static final String CLASS_DUMP_PATH = System.getProperty(
      "gwt.dev.classDumpPath", "rewritten-classes");

  private static boolean emmaAvailable = false;

  private static EmmaStrategy emmaStrategy;

  /**
   * Caches the byte code for {@link JavaScriptHost}.
   */
  private static byte[] javaScriptHostBytes;

  private static final Map<String, Class<?>> primitiveTypes = new HashMap<String, Class<?>>();

  static {
    primitiveTypes.put(boolean.class.getSimpleName(), boolean.class);
    primitiveTypes.put(byte.class.getSimpleName(), boolean.class);
    primitiveTypes.put(char.class.getSimpleName(), boolean.class);
    primitiveTypes.put(double.class.getSimpleName(), boolean.class);
    primitiveTypes.put(float.class.getSimpleName(), boolean.class);
    primitiveTypes.put(int.class.getSimpleName(), boolean.class);
    primitiveTypes.put(long.class.getSimpleName(), boolean.class);
    primitiveTypes.put(short.class.getSimpleName(), boolean.class);
    primitiveTypes.put(void.class.getSimpleName(), boolean.class);
  }

  static {
    for (Class<?> c : BRIDGE_CLASSES) {
      BRIDGE_CLASS_NAMES.put(c.getName(), c);
    }
    /*
     * Specific support for bridging to Emma since the user classloader is
     * generally completely isolated.
     * 
     * We are looking for a specific emma class "com.vladium.emma.rt.RT". If
     * that changes in the future, this code would need to be updated as well.
     */
    try {
      Class<?> emmaBridge = Class.forName(EmmaStrategy.EMMA_RT_CLASSNAME,
          false, Thread.currentThread().getContextClassLoader());
      BRIDGE_CLASS_NAMES.put(EmmaStrategy.EMMA_RT_CLASSNAME, emmaBridge);
      emmaAvailable = true;
    } catch (ClassNotFoundException ignored) {
    }
    emmaStrategy = EmmaStrategy.get(emmaAvailable);
  }

  private static void classDump(String name, byte[] bytes) {
    String packageName, className;
    int pos = name.lastIndexOf('.');
    if (pos < 0) {
      packageName = "";
      className = name;
    } else {
      packageName = name.substring(0, pos);
      className = name.substring(pos + 1);
    }

    File dir = new File(CLASS_DUMP_PATH + File.separator
        + packageName.replace('.', File.separatorChar));
    if (!dir.exists()) {
      // No need to check mkdirs result because an IOException will occur anyway
      dir.mkdirs();
    }

    File file = new File(dir, className + ".class");
    FileOutputStream fileOutput = null;
    try {
      fileOutput = new FileOutputStream(file);
      fileOutput.write(bytes);
      fileOutput.close();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (fileOutput != null) {
        try {
          fileOutput.close();
        } catch (IOException e) {
          // oh well, we tried
        }
      }
    }
  }

  /**
   * Magic: {@link JavaScriptHost} was never compiled because it's a part of the
   * hosted mode infrastructure. However, unlike {@link #BRIDGE_CLASSES},
   * {@code JavaScriptHost} needs a separate copy per inside the ClassLoader for
   * each module.
   */
  private static void ensureJavaScriptHostBytes(TreeLogger logger)
      throws UnableToCompleteException {

    if (javaScriptHostBytes != null) {
      return;
    }

    String className = JavaScriptHost.class.getName();
    try {
      String path = className.replace('.', '/') + ".class";
      ClassLoader cl = Thread.currentThread().getContextClassLoader();
      URL url = cl.getResource(path);
      if (url != null) {
        javaScriptHostBytes = getClassBytesFromStream(url.openStream());
      } else {
        logger.log(TreeLogger.ERROR,
            "Could not find required bootstrap class '" + className
                + "' in the classpath", null);
        throw new UnableToCompleteException();
      }
    } catch (IOException e) {
      logger.log(TreeLogger.ERROR,
          "Error reading class bytes for " + className, e);
      throw new UnableToCompleteException();
    }
  }

  private static JClassType findImplementingTypeForMethod(JClassType type,
      JMethod method) {
    JType[] methodParamTypes = method.getErasedParameterTypes();
    while (type != null) {
      for (JMethod candidate : type.getMethods()) {
        if (hasMatchingErasedSignature(method, methodParamTypes, candidate)) {
          return type;
        }
      }
      type = type.getSuperclass();
    }
    return null;
  }

  private static byte[] getClassBytesFromStream(InputStream is)
      throws IOException {
    try {
      byte classBytes[] = new byte[is.available()];
      int read = 0;
      while (read < classBytes.length) {
        read += is.read(classBytes, read, classBytes.length - read);
      }
      return classBytes;
    } finally {
      Utility.close(is);
    }
  }

  private static boolean hasMatchingErasedSignature(JMethod a,
      JType[] aParamTypes, JMethod b) {
    if (!a.getName().equals(b.getName())) {
      return false;
    }

    JType[] bParamTypes = b.getErasedParameterTypes();
    if (aParamTypes.length != bParamTypes.length) {
      return false;
    }

    for (int i = 0; i < aParamTypes.length; ++i) {
      if (aParamTypes[i] != bParamTypes[i]) {
        return false;
      }
    }

    return true;
  }

  /**
   * The set of units whose JSNI has already been injected.
   */
  private Set<CompilationUnit> alreadyInjected = new HashSet<CompilationUnit>();

  private final HostedModeClassRewriter classRewriter;

  private CompilationState compilationState;

  private final DispatchClassInfoOracle dispClassInfoOracle = new DispatchClassInfoOracle();

  private Class<?> gwtClass, javaScriptHostClass;

  /**
   * Used by {@link #findClass(String)} to prevent reentrant JSNI injection.
   */
  private boolean isInjectingClass = false;

  private final ReentrantLock loadLock = new ReentrantLock();
  
  private final TreeLogger logger;

  private final Set<String> scriptOnlyClasses = new HashSet<String>();

  private ClassLoader scriptOnlyClassLoader;

  private ShellJavaScriptHost shellJavaScriptHost;

  private final Set<String> singleJsoImplTypes = new HashSet<String>();

  /**
   * Used by {@link #findClass(String)} to prevent reentrant JSNI injection.
   */
  private Stack<CompilationUnit> toInject = new Stack<CompilationUnit>();

  private final TypeOracle typeOracle;

  private final Map<Object, Object> weakJavaWrapperCache = new MapMaker().weakKeys().weakValues().makeMap();

  private final Map<Integer, Object> weakJsoCache = new MapMaker().weakValues().makeMap();

  public CompilingClassLoader(TreeLogger logger,
      CompilationState compilationState, ShellJavaScriptHost javaScriptHost)
      throws UnableToCompleteException {
    super(null);
    this.logger = logger;
    this.compilationState = compilationState;
    this.shellJavaScriptHost = javaScriptHost;
    this.typeOracle = compilationState.getTypeOracle();

    // Assertions are always on in hosted mode.
    setDefaultAssertionStatus(true);

    ensureJavaScriptHostBytes(logger);

    // Create a class rewriter based on all the subtypes of the JSO class.
    JClassType jsoType = typeOracle.findType(JsValueGlue.JSO_CLASS);
    if (jsoType != null) {

      // Create a set of binary names.
      Set<JClassType> jsoTypes = new HashSet<JClassType>();
      JClassType[] jsoSubtypes = jsoType.getSubtypes();
      Collections.addAll(jsoTypes, jsoSubtypes);
      jsoTypes.add(jsoType);

      Set<String> jsoTypeNames = new HashSet<String>();
      Map<String, List<String>> jsoSuperTypes = new HashMap<String, List<String>>();
      for (JClassType type : jsoTypes) {
        List<String> types = new ArrayList<String>();
        types.add(getBinaryName(type.getSuperclass()));
        for (JClassType impl : type.getImplementedInterfaces()) {
          types.add(getBinaryName(impl));
        }

        String binaryName = getBinaryName(type);
        jsoTypeNames.add(binaryName);
        jsoSuperTypes.put(binaryName, types);
      }

      SingleJsoImplData singleJsoImplData = new MySingleJsoImplData();

      MyInstanceMethodOracle mapper = new MyInstanceMethodOracle(jsoTypes,
          typeOracle.getJavaLangObject(), singleJsoImplData);
      classRewriter = new HostedModeClassRewriter(jsoTypeNames, jsoSuperTypes,
          singleJsoImplData, mapper);
    } else {
      // If we couldn't find the JSO class, we don't need to do any rewrites.
      classRewriter = null;
    }
  }

  /**
   * Retrieves the mapped JSO for a given unique id, provided the id was
   * previously cached and the JSO has not been garbage collected.
   * 
   * @param uniqueId the previously stored unique id
   * @return the mapped JSO, or <code>null</code> if the id was not previously
   *         mapped or if the JSO has been garbage collected
   */
  public Object getCachedJso(int uniqueId) {
    return weakJsoCache.get(uniqueId);
  }

  /**
   * Returns the {@link DispatchClassInfo} for a given dispatch id.
   * 
   * @param dispId dispatch identifier
   * @return {@link DispatchClassInfo} for a given dispatch id or null if one
   *         does not exist
   */
  public DispatchClassInfo getClassInfoByDispId(int dispId) {
    return dispClassInfoOracle.getClassInfoByDispId(dispId);
  }

  /**
   * Returns the dispatch id for a JSNI member reference.
   * 
   * @param jsniMemberRef a JSNI member reference
   * @return dispatch id or -1 if the JSNI member reference could not be found
   */
  public int getDispId(String jsniMemberRef) {
    return dispClassInfoOracle.getDispId(jsniMemberRef);
  }

  /**
   * Retrieves the mapped wrapper for a given Java Object, provided the wrapper
   * was previously cached and has not been garbage collected.
   * 
   * @param javaObject the Object being wrapped
   * @return the mapped wrapper, or <code>null</code> if the Java object mapped
   *         or if the wrapper has been garbage collected
   */
  public Object getWrapperForObject(Object javaObject) {
    return weakJavaWrapperCache.get(javaObject);
  }

  /**
   * Weakly caches a given JSO by unique id. A cached JSO can be looked up by
   * unique id until it is garbage collected.
   * 
   * @param uniqueId a unique id associated with the JSO
   * @param jso the value to cache
   */
  public void putCachedJso(int uniqueId, Object jso) {
    weakJsoCache.put(uniqueId, jso);
  }

  /**
   * Weakly caches a wrapper for a given Java Object.
   * 
   * @param javaObject the Object being wrapped
   * @param wrapper the mapped wrapper
   */
  public void putWrapperForObject(Object javaObject, Object wrapper) {
    weakJavaWrapperCache.put(javaObject, wrapper);
  }

  @Override
  protected Class<?> findClass(String className) throws ClassNotFoundException {
    if (className == null) {
      throw new ClassNotFoundException("null class name",
          new NullPointerException());
    }

    if (className.equals("com.google.gwt.core.ext.debug.JsoEval")) {
      // In addition to the system ClassLoader, we let JsoEval be available
      // from this CompilingClassLoader in case that's where the debugger
      // happens to look.
      return ClassLoader.getSystemClassLoader().loadClass(className);
    }

    loadLock.lock();
    try {

      if (scriptOnlyClasses.contains(className)) {
        // Allow the child ClassLoader to handle this
        throw new ClassNotFoundException();
      }

      // Check for a bridge class that spans hosted and user space.
      if (BRIDGE_CLASS_NAMES.containsKey(className)) {
        return BRIDGE_CLASS_NAMES.get(className);
      }

      // Get the bytes, compiling if necessary.
      byte[] classBytes = findClassBytes(className);
      if (classBytes == null) {
        throw new ClassNotFoundException(className);
      }

      if (HasAnnotation.hasAnnotation(classBytes, GwtScriptOnly.class)) {
        scriptOnlyClasses.add(className);
        maybeInitializeScriptOnlyClassLoader();

        /*
         * Release the lock before side-loading from scriptOnlyClassLoader. This prevents deadlock
         * conditions when a class from scriptOnlyClassLoader ends up trying to call back into this
         * classloader from another thread. 
         */
        loadLock.unlock();

        // Also don't run the static initializer to lower the risk of deadlock. 
        return Class.forName(className, false, scriptOnlyClassLoader);
      }

     /*
      * Prevent reentrant problems where classes that need to be injected have
      * circular dependencies on one another via JSNI and inheritance. This check
      * ensures that a class's supertype can refer to the subtype (static
      * members, etc) via JSNI references by ensuring that the Class for the
      * subtype will have been defined before injecting the JSNI for the
      * supertype.
      */
      boolean localInjection;
      if (!isInjectingClass) {
        localInjection = isInjectingClass = true;
      } else {
        localInjection = false;
      }

      Class<?> newClass = defineClass(className, classBytes, 0, classBytes.length);
      if (className.equals(JavaScriptHost.class.getName())) {
        javaScriptHostClass = newClass;
        updateJavaScriptHost();
      }

      /*
      * We have to inject the JSNI code after defining the class, since dispId
      * assignment is based around reflection on Class objects. Don't inject JSNI
      * when loading a JSO interface class; just wait until the implementation
      * class is loaded.
      */
      if (!classRewriter.isJsoIntf(className)) {
        CompilationUnit unit = getUnitForClassName(canonicalizeClassName(className));
        if (unit != null) {
          toInject.push(unit);
        }
      }

      if (localInjection) {
        try {
          /*
          * Can't use an iterator here because calling injectJsniFor may cause
          * additional entries to be added.
          */
          while (toInject.size() > 0) {
            CompilationUnit unit = toInject.remove(0);
            if (!alreadyInjected.contains(unit)) {
              injectJsniMethods(unit);
              alreadyInjected.add(unit);
            }
          }
        } finally {
          isInjectingClass = false;
        }
      }

      if (className.equals("com.google.gwt.core.client.GWT")) {
        gwtClass = newClass;
        updateGwtClass();
      }

      return newClass;
    } finally {
      if (loadLock.isLocked()) {
        loadLock.unlock();
      }
    }
  }

  /**
   * Remove some of the excess locking that we'd normally inherit from loadClass.
   */
  @Override
  protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    // at design time we want to provide parent ClassLoader, so keep default implementation
    if (Beans.isDesignTime()) {
      return super.loadClass(name, resolve);
    }

    Class c = findLoadedClass(name);
    if (c != null) {
      if (resolve) {
        resolveClass(c);
      }
      return c;
    }
    
    assert getParent() == null;
    
    try {
      c = bootstrapClassLoader.loadClass(name);
    } catch (ClassNotFoundException e) {
      c = findClass(name);
    }
    
    if (resolve) {
      resolveClass(c);
    }
    
    return c;
  }

  void clear() {
    // Release our references to the shell.
    shellJavaScriptHost = null;
    scriptOnlyClasses.clear();
    scriptOnlyClassLoader = null;
    updateJavaScriptHost();
    weakJsoCache.clear();
    weakJavaWrapperCache.clear();
    dispClassInfoOracle.clear();
  }

  /**
   * Convert a binary class name into a resource-like name.
   */
  private String canonicalizeClassName(String className) {
    String lookupClassName = className.replace('.', '/');
    // A JSO impl class ends with $, strip it
    if (classRewriter != null && classRewriter.isJsoImpl(className)) {
      lookupClassName = lookupClassName.substring(0,
          lookupClassName.length() - 1);
    }
    return lookupClassName;
  }

  @SuppressWarnings("deprecation")
  private byte[] findClassBytes(String className) {
    if (JavaScriptHost.class.getName().equals(className)) {
      // No need to rewrite.
      return javaScriptHostBytes;
    }


    // A JSO impl class needs the class bytes for the original class.
    String lookupClassName = canonicalizeClassName(className);

    CompiledClass compiledClass = compilationState.getClassFileMap().get(
        lookupClassName);

    if (classRewriter != null && classRewriter.isJsoIntf(className)) {
      // Generate a synthetic JSO interface class.
      byte[] newBytes = classRewriter.writeJsoIntf(className, compiledClass != null ?
        compiledClass.getBytes() : null);
      if (CLASS_DUMP) {
        classDump(className, newBytes);
      }
      return newBytes;
    }

    CompilationUnit unit = (compiledClass == null)
        ? getUnitForClassName(lookupClassName) : compiledClass.getUnit();
    if (emmaAvailable) {
      /*
       * build the map for anonymous classes. Do so only if unit has anonymous
       * classes, jsni methods, is not super-source and the map has not been
       * built before.
       */
      List<JsniMethod> jsniMethods = (unit == null) ? null
          : unit.getJsniMethods();
      if (unit != null && !unit.isSuperSource() && !unit.isGenerated()
          && unit.hasAnonymousClasses() && jsniMethods != null
          && jsniMethods.size() > 0 && !unit.createdClassMapping()) {
        if (!unit.constructAnonymousClassMappings(logger)) {
          logger.log(TreeLogger.ERROR,
              "Our heuristic for mapping anonymous classes between compilers "
                  + "failed. Unsafe to continue because the wrong jsni code "
                  + "could end up running. className = " + className);
          return null;
        }
      }
    }

    byte classBytes[] = null;
    if (compiledClass != null) {
      classBytes = compiledClass.getBytes();
      if (!compiledClass.getUnit().isSuperSource()) {
        classBytes = emmaStrategy.getEmmaClassBytes(classBytes,
            lookupClassName, compiledClass.getUnit().getLastModified());
      } else {
        if (logger.isLoggable(TreeLogger.SPAM)) {
          logger.log(TreeLogger.SPAM, "no emma instrumentation for "
              + lookupClassName + " because it is from super-source");
        }
      }
    } else if (emmaAvailable) {
      /*
       * TypeOracle does not know about this class. Most probably, this class
       * was referenced in one of the classes loaded from disk. Check if we can
       * find it on disk. Typically this is a synthetic class added by the
       * compiler.
       */
      if (typeHasCompilationUnit(lookupClassName)
          && CompilationUnit.isClassnameGenerated(className)) {
        /*
         * modification time = 0 ensures that whatever is on the disk is always
         * loaded.
         */
        if (logger.isLoggable(TreeLogger.DEBUG)) {
          logger.log(TreeLogger.DEBUG, "EmmaStrategy: loading " + lookupClassName
              + " from disk even though TypeOracle does not know about it");
        }
        classBytes = emmaStrategy.getEmmaClassBytes(null, lookupClassName, 0);
      }
    }
    if (classBytes != null && classRewriter != null) {
      Map<String, String> anonymousClassMap = Collections.emptyMap();
      if (unit != null) {
        anonymousClassMap = unit.getAnonymousClassMap();
      }
      byte[] newBytes = classRewriter.rewrite(typeOracle, className,
          classBytes, anonymousClassMap);
      if (CLASS_DUMP) {
        if (!Arrays.equals(classBytes, newBytes)) {
          classDump(className, newBytes);
        }
      }
      classBytes = newBytes;
    }
    
    if (unit != null && unit.isError()) {
      // Compile worked, but the unit had some kind of error (JSNI?)
      CompilationProblemReporter.reportErrors(logger, unit, false);
    }

    return classBytes;
  }

  private String getBinaryName(JClassType type) {
    String name = type.getPackage().getName() + '.';
    name += type.getName().replace('.', '$');
    return name;
  }

  private String getBinaryOrPrimitiveName(JType type) {
    JArrayType asArray = type.isArray();
    JClassType asClass = type.isClassOrInterface();
    JPrimitiveType asPrimitive = type.isPrimitive();
    if (asClass != null) {
      return getBinaryName(asClass);
    } else if (asPrimitive != null) {
      return asPrimitive.getQualifiedSourceName();
    } else if (asArray != null) {
      JType componentType = asArray.getComponentType();
      return getBinaryOrPrimitiveName(componentType) + "[]";
    } else {
      throw new InternalCompilerException("Cannot create binary name for "
          + type.getQualifiedSourceName());
    }
  }

  /**
   * Returns the compilationUnit corresponding to the className. For nested
   * classes, the unit corresponding to the top level type is returned.
   * 
   * Since a file might have several top-level types, search using classFileMap.
   */
  private CompilationUnit getUnitForClassName(String className) {
    String mainTypeName = className;
    int index = mainTypeName.length();
    CompiledClass cc = null;
    while (cc == null && index != -1) {
      mainTypeName = mainTypeName.substring(0, index);
      cc = compilationState.getClassFileMap().get(mainTypeName);
      index = mainTypeName.lastIndexOf('$');
    }
    return cc == null ? null : cc.getUnit();
  }

  private void injectJsniMethods(CompilationUnit unit) {
    if (unit == null || unit.getJsniMethods() == null) {
      return;
    }
    Event event = SpeedTracerLogger.start(DevModeEventType.LOAD_JSNI, "unit",
        unit.getTypeName());
    try {
      shellJavaScriptHost.createNativeMethods(logger, unit.getJsniMethods(),
          this);
    } finally {
      event.end();
    }
  }

  private void maybeInitializeScriptOnlyClassLoader() {
    if (scriptOnlyClassLoader == null) {
      scriptOnlyClassLoader = new MultiParentClassLoader(this,
          Thread.currentThread().getContextClassLoader());
    }
  }

  private boolean typeHasCompilationUnit(String className) {
    return getUnitForClassName(className) != null;
  }

  /**
   * Tricky one, this. Reaches over into this modules's JavaScriptHost class and
   * sets its static 'host' field to our module space.
   * 
   * @see JavaScriptHost
   */
  private void updateGwtClass() {
    if (gwtClass == null) {
      return;
    }
    Throwable caught;
    try {
      GWTBridgeImpl bridge;
      if (shellJavaScriptHost == null) {
        bridge = null;
      } else {
        bridge = new GWTBridgeImpl(shellJavaScriptHost);
      }
      final Class<?>[] paramTypes = new Class[]{GWTBridge.class};
      Method setBridgeMethod = gwtClass.getDeclaredMethod("setBridge",
          paramTypes);
      setBridgeMethod.setAccessible(true);
      setBridgeMethod.invoke(gwtClass, new Object[]{bridge});
      return;
    } catch (SecurityException e) {
      caught = e;
    } catch (NoSuchMethodException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e.getTargetException();
    }
    throw new RuntimeException("Error initializing GWT bridge", caught);
  }

  /**
   * Tricky one, this. Reaches over into this modules's JavaScriptHost class and
   * sets its static 'host' field to our module space.
   * 
   * @see JavaScriptHost
   */
  private void updateJavaScriptHost() {
    if (javaScriptHostClass == null) {
      return;
    }
    Throwable caught;
    try {
      final Class<?>[] paramTypes = new Class[]{ShellJavaScriptHost.class};
      Method setHostMethod = javaScriptHostClass.getMethod("setHost",
          paramTypes);
      setHostMethod.invoke(javaScriptHostClass,
          new Object[]{shellJavaScriptHost});
      return;
    } catch (SecurityException e) {
      caught = e;
    } catch (NoSuchMethodException e) {
      caught = e;
    } catch (IllegalArgumentException e) {
      caught = e;
    } catch (IllegalAccessException e) {
      caught = e;
    } catch (InvocationTargetException e) {
      caught = e.getTargetException();
    }
    throw new RuntimeException("Error initializing JavaScriptHost", caught);
  }
}
