/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.aries.proxy.impl.gen;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Modifier;

import org.apache.aries.proxy.impl.NLS;
import org.apache.aries.proxy.impl.ProxyUtils;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ProxySubclassAdapter extends ClassVisitor implements Opcodes
{

  private static final Type STRING_TYPE = Type.getType(String.class);
  private static final Type CLASS_TYPE = Type.getType(Class.class);
  private static final Type CLASSLOADER_TYPE = Type.getType(ClassLoader.class);
  private static final Type OBJECT_TYPE = Type.getType(Object.class);
  private static final Type METHOD_TYPE = Type.getType(java.lang.reflect.Method.class);
  private static final Type IH_TYPE = Type.getType(InvocationHandler.class);
  private static final Type[] NO_ARGS = new Type[] {};

  private static final String IH_FIELD = "ih";

  private static Logger LOGGER = LoggerFactory.getLogger(ProxySubclassAdapter.class);

  private String newClassName = null;
  private String superclassBinaryName = null;
  private Class<?> superclassClass = null;
  private ClassLoader loader = null;
  private Type newClassType = null;
  private GeneratorAdapter staticAdapter = null;
  private String currentlyAnalysedClassName = null;
  private Class<?> currentlyAnalysedClass = null;
  private String currentClassFieldName = null;

  public ProxySubclassAdapter(ClassVisitor writer, String newClassName, ClassLoader loader)
  {
    // call the superclass constructor
    super(Opcodes.ASM5, writer);
    // the writer is now the cv in the superclass of ClassAdapter

    LOGGER.debug(Constants.LOG_ENTRY, "ProxySubclassAdapter", new Object[] { this, writer,
        newClassName });

    // set the newClassName field
    this.newClassName = newClassName;
    // set the newClassType descriptor
    newClassType = Type.getType("L" + newClassName + ";");

    // set the classloader
    this.loader = loader;

    LOGGER.debug(Constants.LOG_EXIT, "ProxySubclassAdapter", this);
  }

  /*
   * This method visits the class to generate the new subclass.
   * 
   * The following things happen here: 1. The class is renamed to a dynamic
   * name 2. The existing class name is changed to be the superclass name so
   * that the generated class extends the original class. 3. A private field
   * is added to store an invocation handler 4. A constructor is added that
   * takes an invocation handler as an argument 5. The constructor method
   * instantiates an instance of the superclass 6. The constructor method sets
   * the invocation handler so the invoke method can be called from all the
   * subsequently rewritten methods 7. Add a getInvocationHandler() method 8.
   * store a static Class object of the superclass so we can reflectively find
   * methods later
   */
  public void visit(int version, int access, String name, String signature, String superName,
      String[] interfaces)
  {
    LOGGER.debug(Constants.LOG_ENTRY, "visit", new Object[] { version, access, name,
        signature, superName, interfaces });

    // store the superclass binary name
    this.superclassBinaryName = name.replaceAll("/", "\\.");

    try {
      this.superclassClass = Class.forName(superclassBinaryName, false, loader);
    } catch (ClassNotFoundException cnfe) {
      throw new TypeNotPresentException(superclassBinaryName, cnfe);
    }


    // keep the same access and signature as the superclass (unless it's abstract)
    // remove all the superclass interfaces because they will be inherited
    // from the superclass anyway
    if((access & ACC_ABSTRACT) != 0) {
      //If the super was abstract the subclass should not be!
      access &= ~ACC_ABSTRACT;
    }
    cv.visit(ProxyUtils.getWeavingJavaVersion(), access, newClassName, signature, name, null);

    // add a private field for the invocation handler
    // this isn't static in case we have multiple instances of the same
    // proxy
    cv.visitField(ACC_PRIVATE, IH_FIELD, Type.getDescriptor(InvocationHandler.class), null, null);

    // create a static adapter for generating a static initialiser method in
    // the generated subclass
    staticAdapter = new GeneratorAdapter(ACC_STATIC,
        new Method("<clinit>", Type.VOID_TYPE, NO_ARGS), null, null, cv);

    // add a zero args constructor method
    Method m = new Method("<init>", Type.VOID_TYPE, NO_ARGS);
    GeneratorAdapter methodAdapter = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cv);
    // loadthis
    methodAdapter.loadThis();
    // List the constructors in the superclass.
    Constructor<?>[] constructors = superclassClass.getDeclaredConstructors();
    // Check that we've got at least one constructor, and get the 1st one in the list.
    if (constructors.length > 0) {
      // We now need to construct the proxy class as though it is going to invoke the superclasses constructor.
      // We do this because we can no longer call the java.lang.Object() zero arg constructor as the JVM now throws a VerifyError.
      // So what we do is build up the calling of the superclasses constructor using nulls and default values. This means that the 
      // class bytes can be verified by the JVM, and then in the ProxySubclassGenerator, we load the class without invoking the 
      // constructor. 
      Method constructor = Method.getMethod(constructors[0]);      
      Type[] argTypes = constructor.getArgumentTypes();
      if (argTypes.length == 0) {
        methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>", Type.VOID_TYPE, NO_ARGS));
      } else {
        for (Type type : argTypes) {
          switch (type.getSort())
          {
            case Type.ARRAY:
              // We need to process any array or multidimentional arrays.
              String elementDesc = type.getElementType().getDescriptor();
              String typeDesc = type.getDescriptor();
              
              // Iterate over the number of arrays and load 0 for each one. Keep a count of the number of 
              // arrays as we will need to run different code fo multi dimentional arrays.
              int index = 0;
              while (! elementDesc.equals(typeDesc)) {
                typeDesc = typeDesc.substring(1);
                methodAdapter.visitInsn(Opcodes.ICONST_0);
                index++;
              }
              // If we're just a single array, then call the newArray method, otherwise use the MultiANewArray instruction.
              if (index == 1) {
                methodAdapter.newArray(type.getElementType());
              } else {
                methodAdapter.visitMultiANewArrayInsn(type.getDescriptor(), index);
              }
              break;
            case Type.BOOLEAN:
              methodAdapter.push(true);
              break;
            case Type.BYTE:
              methodAdapter.push(Type.VOID_TYPE);
              break;
            case Type.CHAR:
              methodAdapter.push(Type.VOID_TYPE);
              break;
            case Type.DOUBLE:
              methodAdapter.push(0.0);
              break;
            case Type.FLOAT:
              methodAdapter.push(0.0f);
              break;
            case Type.INT:
              methodAdapter.push(0);
              break;
            case Type.LONG:
              methodAdapter.push(0l);
              break;
            case Type.SHORT:
              methodAdapter.push(0);
              break;
            default:
            case Type.OBJECT:
              methodAdapter.visitInsn(Opcodes.ACONST_NULL);
              break;
          }
        }
        
        methodAdapter.invokeConstructor(Type.getType(superclassClass), new Method("<init>", Type.VOID_TYPE, argTypes));
      }
    }
    methodAdapter.returnValue();
    methodAdapter.endMethod();

    // add a method for getting the invocation handler
    Method setter = new Method("setInvocationHandler", Type.VOID_TYPE, new Type[] { IH_TYPE });
    m = new Method("getInvocationHandler", IH_TYPE, NO_ARGS);
    methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, m, null, null, cv);
    // load this to get the field
    methodAdapter.loadThis();
    // get the ih field and return
    methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
    methodAdapter.returnValue();
    methodAdapter.endMethod();

    // add a method for setting the invocation handler
    methodAdapter = new GeneratorAdapter(ACC_PUBLIC | ACC_FINAL, setter, null, null, cv);
    // load this to put the field
    methodAdapter.loadThis();
    // load the method arguments (i.e. the invocation handler) to the stack
    methodAdapter.loadArgs();
    // set the ih field using the method argument
    methodAdapter.putField(newClassType, IH_FIELD, IH_TYPE);
    methodAdapter.returnValue();
    methodAdapter.endMethod();

    // loop through the class hierarchy to get any needed methods off the
    // supertypes
    // start by finding the methods declared on the class of interest (the
    // superclass of our dynamic subclass)
    java.lang.reflect.Method[] observedMethods = superclassClass.getDeclaredMethods();
    // add the methods to a set of observedMethods
    ProxySubclassMethodHashSet<String> setOfObservedMethods = new ProxySubclassMethodHashSet<String>(
        observedMethods.length);
    setOfObservedMethods.addMethodArray(observedMethods);
    // get the next superclass in the hierarchy
    Class<?> nextSuperClass = superclassClass.getSuperclass();
    while (nextSuperClass != null) {
      // set the fields for the current class
      setCurrentAnalysisClassFields(nextSuperClass);

      // add a static field and static initializer code to the generated
      // subclass
      // for each of the superclasses in the hierarchy
      addClassStaticField(currentlyAnalysedClassName);

      LOGGER.debug("Class currently being analysed: {} {}", currentlyAnalysedClassName,
          currentlyAnalysedClass);

      // now find the methods declared on the current class and add them
      // to a set of foundMethods
      java.lang.reflect.Method[] foundMethods = currentlyAnalysedClass.getDeclaredMethods();
      ProxySubclassMethodHashSet<String> setOfFoundMethods = new ProxySubclassMethodHashSet<String>(
          foundMethods.length);
      setOfFoundMethods.addMethodArray(foundMethods);
      // remove from the set of foundMethods any methods we saw on a
      // subclass
      // because we want to use the lowest level declaration of a method
      setOfFoundMethods.removeAll(setOfObservedMethods);
      try {
        // read the current class and use a
        // ProxySubclassHierarchyAdapter
        // to process only methods on that class that are in the list
        ClassLoader loader = currentlyAnalysedClass.getClassLoader();
        if (loader == null) {
          loader = this.loader;
        }
        ClassReader cr = new ClassReader(loader.getResourceAsStream(currentlyAnalysedClass
            .getName().replaceAll("\\.", "/")
            + ".class"));
        ClassVisitor hierarchyAdapter = new ProxySubclassHierarchyAdapter(this, setOfFoundMethods);
        cr.accept(hierarchyAdapter, ClassReader.SKIP_DEBUG);
      } catch (IOException e) {
        throw new TypeNotPresentException(currentlyAnalysedClassName, e);
      }
      // now add the foundMethods to the overall list of observed methods
      setOfObservedMethods.addAll(setOfFoundMethods);
      // get the next class up in the hierarchy and go again
      nextSuperClass = currentlyAnalysedClass.getSuperclass();
    }

    // we've finished looking at the superclass hierarchy
    // set the fields for the immediate superclass of our dynamic subclass
    setCurrentAnalysisClassFields(superclassClass);

    // add the class static field
    addClassStaticField(currentlyAnalysedClassName);
    // we do the lowest class last because we are already visiting the class
    // when in this adapter code
    // now we are ready to visit all the methods on the lowest class
    // which will happen by the ASM ClassVisitor implemented in this adapter

    LOGGER.debug(Constants.LOG_EXIT, "visit");
  }

  public void visitSource(String source, String debug)
  {
    LOGGER.debug(Constants.LOG_ENTRY, "visitSource", new Object[] { source, debug });

    // set the source to null since the class is generated on the fly and
    // not compiled
    cv.visitSource(null, null);

    LOGGER.debug(Constants.LOG_EXIT, "visitSource");
  }

  public void visitEnd()
  {
    LOGGER.debug(Constants.LOG_ENTRY, "visitEnd");

    // this method is called when we reach the end of the class
    // so it is time to make sure the static initialiser method is closed
    staticAdapter.returnValue();
    staticAdapter.endMethod();
    // now delegate to the cv
    cv.visitEnd();

    LOGGER.debug(Constants.LOG_EXIT, "visitEnd");
  }

  /*
   * This method is called on each method of the superclass (and all parent
   * classes up to Object) Each of these methods is visited in turn and the
   * code here generates the byte code for the InvocationHandler to call the
   * methods on the superclass.
   */
  public MethodVisitor visitMethod(int access, String name, String desc, String signature,
      String[] exceptions)
  {
    LOGGER.debug(Constants.LOG_ENTRY, "visitMethod", new Object[] { access, name, desc,
        signature, exceptions });

    /*
     * Check the method access and handle the method types we don't want to
     * copy: final methods (issue warnings if these are not methods from
     * java.* classes) static methods (initialiser and others) private
     * methods, constructors (for now we don't copy any constructors)
     * everything else we process to proxy. Abstract methods should be made
     * non-abstract so that they can be proxied.
     */
    
    if((access & ACC_ABSTRACT) != 0) {
      //If the method is abstract then it should not be in the concrete subclass!
      access &= ~ACC_ABSTRACT;
    }
    
    LOGGER.debug("Method name: {} with descriptor: {}", name, desc);

    MethodVisitor methodVisitorToReturn = null;

    if (name.equals("<init>")) {
      // we may need to do something extra with constructors later
      // e.g. include bytecode for calling super with the same args
      // since we currently rely on the super having a zero args
      // constructor
      // we need to issue an error if we don't find one

      // for now we return null to ignore them
      methodVisitorToReturn = null;
    } else if (name.equals("<clinit>")) {
      // don't copy static initialisers from the superclass into the new
      // subclass
      methodVisitorToReturn = null;
    } else if ((access & ACC_FINAL) != 0) {
      // since we check for final methods in the ProxySubclassGenerator we
      // should never get here
      methodVisitorToReturn = null;
    } else if ((access & ACC_SYNTHETIC) != 0) {
      // synthetic methods are generated by the compiler for covariance
      // etc
      // we shouldn't copy them or we will have duplicate methods
      methodVisitorToReturn = null;
    } else if ((access & ACC_PRIVATE) != 0) {
      // don't copy private methods from the superclass
      methodVisitorToReturn = null;
    } else if ((access & ACC_STATIC) != 0) {
      // don't copy static methods
      methodVisitorToReturn = null;
    } else if (!(((access & ACC_PUBLIC) != 0) || ((access & ACC_PROTECTED) != 0) || ((access & ACC_PRIVATE) != 0))) {
      // the default (package) modifier value is 0, so by using & with any
      // of the other
      // modifier values and getting a result of zero means that we have
      // default accessibility

      // check the package in which the method is declared against the
      // package
      // where the generated subclass will be
      // if they are the same process the method otherwise ignore it
      if (currentlyAnalysedClass.getPackage().equals(superclassClass.getPackage())) {
        processMethod(access, name, desc, signature, exceptions);
        methodVisitorToReturn = null;
      } else {
        methodVisitorToReturn = null;
      }
    } else {
      processMethod(access, name, desc, signature, exceptions);
      // return null because we don't want the original method code from
      // the superclass
      methodVisitorToReturn = null;
    }

    LOGGER.debug(Constants.LOG_EXIT, "visitMethod", methodVisitorToReturn);

    return methodVisitorToReturn;

  }

  private void processMethod(int access, String name, String desc, String signature,
      String[] exceptions)
  {
    LOGGER.debug(Constants.LOG_ENTRY, "processMethod", new Object[] { access, name, desc,
        signature, exceptions });

    LOGGER.debug("Processing method: {} with descriptor {}", name, desc);

    // identify the target method parameters and return type
    Method currentTransformMethod = new Method(name, desc);
    Type[] targetMethodParameters = currentTransformMethod.getArgumentTypes();
    Type returnType = currentTransformMethod.getReturnType();

    // we create a static field for each method we encounter with a name
    // like method_parm1_parm2...
    StringBuilder methodStaticFieldNameBuilder = new StringBuilder(name);
    // for each a parameter get the name and add it to the field removing
    // the dots first
    for (Type t : targetMethodParameters) {
      methodStaticFieldNameBuilder.append("_");
      methodStaticFieldNameBuilder.append(t.getClassName().replaceAll("\\[\\]", "Array")
          .replaceAll("\\.", ""));
    }
    String methodStaticFieldName = methodStaticFieldNameBuilder.toString();

    // add a private static field for the method
    cv.visitField(ACC_PRIVATE | ACC_STATIC, methodStaticFieldName, METHOD_TYPE.getDescriptor(),
        null, null);

    // visit the method using the class writer, delegated through the method
    // visitor and generator
    // modify the method access so that any native methods aren't
    // described as native
    // since they won't be native in proxy form
    // also stop methods being marked synchronized on the proxy as they will
    // be sync
    // on the real object
    int newAccess = access & (~ACC_NATIVE) & (~ACC_SYNCHRONIZED);
    MethodVisitor mv = cv.visitMethod(newAccess, name, desc, signature, exceptions);
    // use a GeneratorAdapter to build the invoke call directly in byte code
    GeneratorAdapter methodAdapter = new GeneratorAdapter(mv, newAccess, name, desc);

    /*
     * Stage 1 creates the bytecode for adding the reflected method of the
     * superclass to a static field in the subclass: private static Method
     * methodName_parm1_parm2... = null; static{ methodName_parm1_parm2... =
     * superClass.getDeclaredMethod(methodName,new Class[]{method args}; }
     * 
     * Stage 2 is to call the ih.invoke(this,methodName_parm1_parm2,args) in
     * the new subclass methods Stage 3 is to cast the return value to the
     * correct type
     */

    /*
     * Stage 1 use superClass.getMethod(methodName,new Class[]{method args}
     * from the Class object on the stack
     */

    // load the static superclass Class onto the stack
    staticAdapter.getStatic(newClassType, currentClassFieldName, CLASS_TYPE);

    // push the method name string arg onto the stack
    staticAdapter.push(name);

    // create an array of the method parm class[] arg
    staticAdapter.push(targetMethodParameters.length);
    staticAdapter.newArray(CLASS_TYPE);
    int index = 0;
    for (Type t : targetMethodParameters) {
      staticAdapter.dup();
      staticAdapter.push(index);
      switch (t.getSort())
      {
        case Type.BOOLEAN:
          staticAdapter.getStatic(Type.getType(java.lang.Boolean.class), "TYPE", CLASS_TYPE);
          break;
        case Type.BYTE:
          staticAdapter.getStatic(Type.getType(java.lang.Byte.class), "TYPE", CLASS_TYPE);
          break;
        case Type.CHAR:
          staticAdapter.getStatic(Type.getType(java.lang.Character.class), "TYPE", CLASS_TYPE);
          break;
        case Type.DOUBLE:
          staticAdapter.getStatic(Type.getType(java.lang.Double.class), "TYPE", CLASS_TYPE);
          break;
        case Type.FLOAT:
          staticAdapter.getStatic(Type.getType(java.lang.Float.class), "TYPE", CLASS_TYPE);
          break;
        case Type.INT:
          staticAdapter.getStatic(Type.getType(java.lang.Integer.class), "TYPE", CLASS_TYPE);
          break;
        case Type.LONG:
          staticAdapter.getStatic(Type.getType(java.lang.Long.class), "TYPE", CLASS_TYPE);
          break;
        case Type.SHORT:
          staticAdapter.getStatic(Type.getType(java.lang.Short.class), "TYPE", CLASS_TYPE);
          break;
        default:
        case Type.OBJECT:
          staticAdapter.push(t);
          break;
      }
      staticAdapter.arrayStore(CLASS_TYPE);
      index++;
    }

    // invoke the getMethod
    staticAdapter.invokeVirtual(CLASS_TYPE, new Method("getDeclaredMethod", METHOD_TYPE,
        new Type[] { STRING_TYPE, Type.getType(java.lang.Class[].class) }));

    // store the reflected method in the static field
    staticAdapter.putStatic(newClassType, methodStaticFieldName, METHOD_TYPE);

    /*
     * Stage 2 call the ih.invoke(this,supermethod,parms)
     */

    // load this to get the ih field
    methodAdapter.loadThis();
    // load the invocation handler from the field (the location of the
    // InvocationHandler.invoke)
    methodAdapter.getField(newClassType, IH_FIELD, IH_TYPE);
    // loadThis (the first arg of the InvocationHandler.invoke)
    methodAdapter.loadThis();
    // load the method to invoke (the second arg of the
    // InvocationHandler.invoke)
    methodAdapter.getStatic(newClassType, methodStaticFieldName, METHOD_TYPE);
    // load all the method arguments onto the stack as an object array (the
    // third arg of the InvocationHandler.invoke)
    methodAdapter.loadArgArray();
    // generate the invoke method
    Method invocationHandlerInvokeMethod = new Method("invoke", OBJECT_TYPE, new Type[] {
        OBJECT_TYPE, METHOD_TYPE, Type.getType(java.lang.Object[].class) });
    // call the invoke method of the invocation handler
    methodAdapter.invokeInterface(IH_TYPE, invocationHandlerInvokeMethod);

    /*
     * Stage 3 the returned object is now on the top of the stack We need to
     * check the type and cast as necessary
     */
    switch (returnType.getSort())
    {
      case Type.BOOLEAN:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Boolean.class));
        methodAdapter.unbox(Type.BOOLEAN_TYPE);
        break;
      case Type.BYTE:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Byte.class));
        methodAdapter.unbox(Type.BYTE_TYPE);
        break;
      case Type.CHAR:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Character.class));
        methodAdapter.unbox(Type.CHAR_TYPE);
        break;
      case Type.DOUBLE:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Double.class));
        methodAdapter.unbox(Type.DOUBLE_TYPE);
        break;
      case Type.FLOAT:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Float.class));
        methodAdapter.unbox(Type.FLOAT_TYPE);
        break;
      case Type.INT:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Integer.class));
        methodAdapter.unbox(Type.INT_TYPE);
        break;
      case Type.LONG:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Long.class));
        methodAdapter.unbox(Type.LONG_TYPE);
        break;
      case Type.SHORT:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Short.class));
        methodAdapter.unbox(Type.SHORT_TYPE);
        break;
      case Type.VOID:
        methodAdapter.cast(OBJECT_TYPE, Type.getType(Void.class));
        methodAdapter.unbox(Type.VOID_TYPE);
        break;
      default:
      case Type.OBJECT:
        // in this case check the cast and cast the object to the return
        // type
        methodAdapter.checkCast(returnType);
        methodAdapter.cast(OBJECT_TYPE, returnType);
        break;
    }
    // return the (appropriately cast) result of the invocation from the
    // stack
    methodAdapter.returnValue();
    // end the method
    methodAdapter.endMethod();

    LOGGER.debug(Constants.LOG_EXIT, "processMethod");
  }

  private void addClassStaticField(String classBinaryName)
  {
    LOGGER.debug(Constants.LOG_ENTRY, "addClassStaticField",
        new Object[] { classBinaryName });

    currentClassFieldName = classBinaryName.replaceAll("\\.", "_");

    /*
     * use Class.forName on the superclass so we can reflectively find
     * methods later
     * 
     * produces bytecode for retrieving the superclass and storing in a
     * private static field: private static Class superClass = null; static{
     * superClass = Class.forName(superclass, true, TYPE_BEING_PROXIED.class.getClassLoader()); }
     */

    // add a private static field for the superclass Class
    cv.visitField(ACC_PRIVATE | ACC_STATIC, currentClassFieldName, CLASS_TYPE.getDescriptor(),
        null, null);

    // push the String arg for the Class.forName onto the stack
    staticAdapter.push(classBinaryName);
    //push the boolean arg for the Class.forName onto the stack
    staticAdapter.push(true);
    //get the classloader
    staticAdapter.push(newClassType);
    staticAdapter.invokeVirtual(CLASS_TYPE, new Method("getClassLoader", CLASSLOADER_TYPE, NO_ARGS));

    // invoke the Class forName putting the Class on the stack
    staticAdapter.invokeStatic(CLASS_TYPE, new Method("forName", CLASS_TYPE,
        new Type[] { STRING_TYPE, Type.BOOLEAN_TYPE, CLASSLOADER_TYPE }));

    // put the Class in the static field
    staticAdapter.putStatic(newClassType, currentClassFieldName, CLASS_TYPE);

    LOGGER.debug(Constants.LOG_ENTRY, "addClassStaticField");
  }

  private void setCurrentAnalysisClassFields(Class<?> aClass)
  {
    LOGGER.debug(Constants.LOG_ENTRY, "setCurrentAnalysisClassFields",
        new Object[] { aClass });

    currentlyAnalysedClassName = aClass.getName();
    currentlyAnalysedClass = aClass;

    LOGGER.debug(Constants.LOG_EXIT, "setCurrentAnalysisClassFields");
  }

  // we don't want to copy fields from the class into the proxy
  public FieldVisitor visitField(int access, String name, String desc, String signature,
      Object value)
  {
    return null;
  }

  // for now we don't do any processing in these methods
  public AnnotationVisitor visitAnnotation(String desc, boolean visible)
  {
    return null;
  }

  public void visitAttribute(Attribute attr)
  {
    // no-op
  }

  public void visitInnerClass(String name, String outerName, String innerName, int access)
  {
    // no-op
  }

  public void visitOuterClass(String owner, String name, String desc)
  {
    // no-op
  }
}
