/**
 * Copyright (C) 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.inject.internal;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.logging.Logger;

/**
 * Utility methods for runtime code generation and class loading. We use this stuff for {@link
 * net.sf.cglib.reflect.FastClass faster reflection}, {@link net.sf.cglib.proxy.Enhancer method
 * interceptors} and to proxy circular dependencies.
 *
 * <p>When loading classes, we need to be careful of:
 * <ul>
 *   <li><strong>Memory leaks.</strong> Generated classes need to be garbage collected in long-lived
 *       applications. Once an injector and any instances it created can be garbage collected, the
 *       corresponding generated classes should be collectable.
 *   <li><strong>Visibility.</strong> Containers like <code>OSGi</code> use class loader boundaries
 *       to enforce modularity at runtime.
 * </ul>
 *
 * <p>For each generated class, there's multiple class loaders involved:
 * <ul>
 *    <li><strong>The related class's class loader.</strong> Every generated class services exactly
 *        one user-supplied class. This class loader must be used to access members with private and
 *        package visibility.
 *    <li><strong>Guice's class loader.</strong>
 *    <li><strong>Our bridge class loader.</strong> This is a child of the user's class loader. It
 *        selectively delegates to either the user's class loader (for user classes) or the Guice
 *        class loader (for internal classes that are used by the generated classes). This class
 *        loader that owns the classes generated by Guice.
 * </ul>
 *
 * @author mcculls@gmail.com (Stuart McCulloch)
 * @author jessewilson@google.com (Jesse Wilson)
 */
public final class BytecodeGen {

  static final Logger logger = Logger.getLogger(BytecodeGen.class.getName());

  static final ClassLoader GUICE_CLASS_LOADER = canonicalize(BytecodeGen.class.getClassLoader());

  // initialization-on-demand...
  private static class SystemBridgeHolder {
    static final BridgeClassLoader SYSTEM_BRIDGE = new BridgeClassLoader();
  }

  /** ie. "com.google.inject.internal" */
  static final String GUICE_INTERNAL_PACKAGE
      = BytecodeGen.class.getName().replaceFirst("\\.internal\\..*$", ".internal");

  /*if[AOP]*/
  /** either "net.sf.cglib", or "com.google.inject.internal.cglib" */
  static final String CGLIB_PACKAGE
      = net.sf.cglib.proxy.Enhancer.class.getName().replaceFirst("\\.cglib\\..*$", ".cglib");

  static final net.sf.cglib.core.NamingPolicy FASTCLASS_NAMING_POLICY
      = new net.sf.cglib.core.DefaultNamingPolicy() {
    @Override protected String getTag() {
      return "ByGuice";
    }

    @Override
    public String getClassName(String prefix, String source, Object key,
        net.sf.cglib.core.Predicate names) {
      // we explicitly set the source here to "FastClass" so that our jarjar renaming
      // to $FastClass doesn't leak into the class names.  if we did not do this,
      // classes would end up looking like $$$FastClassByGuice$$, with the extra $
      // at the front.
      return super.getClassName(prefix, "FastClass", key, names);
    }
  };

  static final net.sf.cglib.core.NamingPolicy ENHANCER_NAMING_POLICY
      = new net.sf.cglib.core.DefaultNamingPolicy() {
    @Override
    protected String getTag() {
      return "ByGuice";
    }

    @Override
    public String getClassName(String prefix, String source, Object key,
        net.sf.cglib.core.Predicate names) {
      // we explicitly set the source here to "Enhancer" so that our jarjar renaming
      // to $Enhancer doesn't leak into the class names.  if we did not do this,
      // classes would end up looking like $$$EnhancerByGuice$$, with the extra $
      // at the front.
      return super.getClassName(prefix, "Enhancer", key, names);
    }
  };
  /*end[AOP]*/
  /*if[NO_AOP]
  private static final String CGLIB_PACKAGE = " "; // any string that's illegal in a package name
  end[NO_AOP]*/

  /** Use "-Dguice.custom.loader=false" to disable custom classloading. */
  private static final boolean CUSTOM_LOADER_ENABLED
      = Boolean.parseBoolean(System.getProperty("guice.custom.loader", "true"));

  /**
   * Weak cache of bridge class loaders that make the Guice implementation
   * classes visible to various code-generated proxies of client classes.
   */
  private static final LoadingCache<ClassLoader, ClassLoader> CLASS_LOADER_CACHE;

  static {
    CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder().weakKeys().weakValues();
    if (!CUSTOM_LOADER_ENABLED) {
      builder.maximumSize(0);
    }
    CLASS_LOADER_CACHE = builder.build(
        new CacheLoader<ClassLoader, ClassLoader>() {
          public ClassLoader load(final ClassLoader typeClassLoader) {
            logger.fine("Creating a bridge ClassLoader for " + typeClassLoader);
            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
              public ClassLoader run() {
                return new BridgeClassLoader(typeClassLoader);
              }
            });
          }
        });
  }

  /**
   * Attempts to canonicalize null references to the system class loader.
   * May return null if for some reason the system loader is unavailable.
   */
  private static ClassLoader canonicalize(ClassLoader classLoader) {
    return classLoader != null ? classLoader : SystemBridgeHolder.SYSTEM_BRIDGE.getParent();
  }

  /**
   * Returns the class loader to host generated classes for {@code type}.
   */
  public static ClassLoader getClassLoader(Class<?> type) {
    return getClassLoader(type, type.getClassLoader());
  }

  private static ClassLoader getClassLoader(Class<?> type, ClassLoader delegate) {

    // simple case: do nothing!
    if (!CUSTOM_LOADER_ENABLED) {
      return delegate;
    }

    // java.* types can be seen everywhere
    if (type.getName().startsWith("java.")) {
      return GUICE_CLASS_LOADER;
    }

    delegate = canonicalize(delegate);

    // no need for a bridge if using same class loader, or it's already a bridge
    if (delegate == GUICE_CLASS_LOADER || delegate instanceof BridgeClassLoader) {
      return delegate;
    }

    // don't try bridging private types as it won't work
    if (Visibility.forType(type) == Visibility.PUBLIC) {
      if (delegate != SystemBridgeHolder.SYSTEM_BRIDGE.getParent()) {
        // delegate guaranteed to be non-null here
        return CLASS_LOADER_CACHE.getUnchecked(delegate);
      }
      // delegate may or may not be null here
      return SystemBridgeHolder.SYSTEM_BRIDGE;
    }

    return delegate; // last-resort: do nothing!
  }

  /*if[AOP]*/
  // use fully-qualified names so imports don't need preprocessor statements 
  public static net.sf.cglib.reflect.FastClass newFastClass(Class<?> type, Visibility visibility) {
    net.sf.cglib.reflect.FastClass.Generator generator
        = new net.sf.cglib.reflect.FastClass.Generator();
    generator.setType(type);
    if (visibility == Visibility.PUBLIC) {
      generator.setClassLoader(getClassLoader(type));
    }
    generator.setNamingPolicy(FASTCLASS_NAMING_POLICY);
    logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader());
    return generator.create();
  }

  public static net.sf.cglib.proxy.Enhancer newEnhancer(Class<?> type, Visibility visibility) {
    net.sf.cglib.proxy.Enhancer enhancer = new net.sf.cglib.proxy.Enhancer();
    enhancer.setSuperclass(type);
    enhancer.setUseFactory(false);
    if (visibility == Visibility.PUBLIC) {
      enhancer.setClassLoader(getClassLoader(type));
    }
    enhancer.setNamingPolicy(ENHANCER_NAMING_POLICY);
    logger.fine("Loading " + type + " Enhancer with " + enhancer.getClassLoader());
    return enhancer;
  }
  /*end[AOP]*/

  /**
   * The required visibility of a user's class from a Guice-generated class. Visibility of
   * package-private members depends on the loading classloader: only if two classes were loaded by
   * the same classloader can they see each other's package-private members. We need to be careful
   * when choosing which classloader to use for generated classes. We prefer our bridge classloader,
   * since it's OSGi-safe and doesn't leak permgen space. But often we cannot due to visibility.
   */
  public enum Visibility {

    /**
     * Indicates that Guice-generated classes only need to call and override public members of the
     * target class. These generated classes may be loaded by our bridge classloader.
     */
    PUBLIC {
      @Override
      public Visibility and(Visibility that) {
        return that;
      }
    },

    /**
     * Indicates that Guice-generated classes need to call or override package-private members.
     * These generated classes must be loaded in the same classloader as the target class. They
     * won't work with OSGi, and won't get garbage collected until the target class' classloader is
     * garbage collected.
     */
    SAME_PACKAGE {
      @Override
      public Visibility and(Visibility that) {
        return this;
      }
    };

    public static Visibility forMember(Member member) {
      if ((member.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
        return SAME_PACKAGE;
      }

      Class[] parameterTypes;
      if (member instanceof Constructor) {
        parameterTypes = ((Constructor) member).getParameterTypes();
      } else {
        Method method = (Method) member;
        if (forType(method.getReturnType()) == SAME_PACKAGE) {
          return SAME_PACKAGE;
        }
        parameterTypes = method.getParameterTypes();
      }

      for (Class<?> type : parameterTypes) {
        if (forType(type) == SAME_PACKAGE) {
          return SAME_PACKAGE;
        }
      }

      return PUBLIC;
    }

    public static Visibility forType(Class<?> type) {
      return (type.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) != 0
          ? PUBLIC
          : SAME_PACKAGE;
    }

    public abstract Visibility and(Visibility that);
  }

  /**
   * Loader for Guice-generated classes. For referenced classes, this delegates to either either the
   * user's classloader (which is the parent of this classloader) or Guice's class loader.
   */
  private static class BridgeClassLoader extends ClassLoader {

    BridgeClassLoader() {
      // use system loader as parent
    }

    BridgeClassLoader(ClassLoader usersClassLoader) {
      super(usersClassLoader);
    }

    @Override protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException {

      if (name.startsWith("sun.reflect")) {
        // these reflection classes must be loaded from bootstrap class loader
        return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
      }

      if (name.startsWith(GUICE_INTERNAL_PACKAGE) || name.startsWith(CGLIB_PACKAGE)) {
        if (null == GUICE_CLASS_LOADER) {
          // use special system bridge to load classes from bootstrap class loader
          return SystemBridgeHolder.SYSTEM_BRIDGE.classicLoadClass(name, resolve);
        }
        try {
          Class<?> clazz = GUICE_CLASS_LOADER.loadClass(name);
          if (resolve) {
            resolveClass(clazz);
          }
          return clazz;
        } catch (Throwable e) {
          // fall-back to classic delegation
        }
      }

      return classicLoadClass(name, resolve);
    }

    // make the classic delegating loadClass method visible
    Class<?> classicLoadClass(String name, boolean resolve)
      throws ClassNotFoundException {
      return super.loadClass(name, resolve);
    }
  }
}
