/*
 * 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.io.InputStream;
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.apache.aries.proxy.impl.SystemModuleClassLoader;
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;
        }
        InputStream is = loader.getResourceAsStream(currentlyAnalysedClass
                                                    .getName().replaceAll("\\.", "/")
                                                    + ".class");
        if (is == null) {
              //use SystemModuleClassLoader as fallback
              ClassLoader classLoader = new SystemModuleClassLoader();
              is = classLoader.getResourceAsStream(currentlyAnalysedClass
                                              .getName().replaceAll("\\.", "/")
                                              + ".class");
        }
        ClassReader cr = new ClassReader(is);
        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
  }
}
