/*
 * 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.util.tools.Utility;

import org.apache.commons.collections.map.AbstractReferenceMap;
import org.apache.commons.collections.map.ReferenceIdentityMap;
import org.apache.commons.collections.map.ReferenceMap;

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;

  @SuppressWarnings("unchecked")
  private final Map<Object, Object> weakJavaWrapperCache = new ReferenceIdentityMap(
      AbstractReferenceMap.WEAK, AbstractReferenceMap.WEAK);

  @SuppressWarnings("unchecked")
  private final Map<Integer, Object> weakJsoCache = new ReferenceMap(
      AbstractReferenceMap.HARD, AbstractReferenceMap.WEAK);

  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);
  }
}
