Example usage for org.objectweb.asm ClassVisitor visitEnd

List of usage examples for org.objectweb.asm ClassVisitor visitEnd

Introduction

In this page you can find the example usage for org.objectweb.asm ClassVisitor visitEnd.

Prototype

public void visitEnd() 

Source Link

Document

Visits the end of the class.

Usage

From source file:org.adjective.stout.writer.ByteCodeWriter.java

License:Apache License

public byte[] write(ClassDescriptor cls) {
    begin(cls);//from  w  w  w .j a  v a  2s.  c o  m
    ClassWriter writer = createClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = writer;
    if (_trace) {
        cv = new TraceClassVisitor(cv, new PrintWriter(System.err));
    }
    if (_check) {
        cv = new CheckClassAdapter(cv);
    }

    String signature = null; // @TODO
    cv.visit(Opcodes.V1_5, getModifierCode(cls.getModifiers(), cls.getSort()), cls.getInternalName(), signature,
            getInternalName(cls.getSuperClass()), getInterfaceNames(cls));

    if (cls.getSourceFile() != null) {
        cv.visitSource(cls.getSourceFile(), "");
    }

    UnresolvedType outer = cls.getOuterClass();
    if (outer != null) {
        cv.visitOuterClass(outer.getInternalName(), null, null);
    }

    for (AnnotationDescriptor annotation : cls.getAnnotations()) {
        writeAnnotation(cv, annotation);
    }

    for (ClassDescriptor inner : cls.getInnerClasses()) {
        String name = inner.getInternalName();
        String simpleName = name.substring(name.lastIndexOf('/') + 1);
        cv.visitInnerClass(name, cls.getInternalName(), simpleName,
                getModifierCode(inner.getModifiers(), inner.getSort()));
    }

    for (FieldDescriptor field : cls.getFields()) {
        writeField(cv, field);
    }

    for (MethodDescriptor method : cls.getMethods()) {
        writeMethod(cv, cls, method);
    }

    cv.visitEnd();

    end(cls);
    return writer.toByteArray();
}

From source file:org.apache.commons.weaver.normalizer.Normalizer.java

License:Apache License

/**
 * Create the normalized version of a given class in the configured target package. The {@link Normalizer} will
 * gladly do so in a package from which the normalized class will not actually be able to reference any types upon
 * which it relies; in such a situation you must specify the target package as the package of the supertype.
 * @param key used to generate the normalized classname.
 * @param classWrapper/*www . jav  a2  s  . co m*/
 * @return the generated classname.
 * @throws IOException
 */
private String copy(final Pair<String, String> key, final ClassWrapper classWrapper) throws IOException {
    env.debug("Copying %s to %s", key, targetPackage);
    final MessageDigest md5;
    try {
        md5 = MessageDigest.getInstance("MD5");
    } catch (final NoSuchAlgorithmException e) {
        throw new IllegalStateException(e);
    }
    md5.update(key.getLeft().getBytes(StandardCharsets.UTF_8));
    md5.update(key.getRight().getBytes(StandardCharsets.UTF_8));

    final long digest = Conversion.byteArrayToLong(md5.digest(), 0, 0L, 0, Long.SIZE / Byte.SIZE);

    final String result = MessageFormat.format("{0}/$normalized{1,number,0;_0}", targetPackage, digest);

    env.debug("Copying class %s to %s", classWrapper.wrapped.getName(), result);

    try (InputStream bytecode = env.getClassfile(classWrapper.wrapped).getInputStream()) {
        final ClassReader reader = new ClassReader(bytecode);
        final ClassVisitor writeClass = new WriteClass();

        // we're doing most of this by hand; we only read the original class to hijack signature, ctor exceptions,
        // etc.:

        reader.accept(new ClassVisitor(ASM_VERSION) {
            Type supertype;

            @Override
            @SuppressWarnings("PMD.UseVarargs") //overridden method
            public void visit(final int version, final int access, final String name, final String signature,
                    final String superName, final String[] interfaces) {
                supertype = Type.getObjectType(superName);
                writeClass.visit(version, Opcodes.ACC_PUBLIC, result, signature, superName, interfaces);
                visitAnnotation(Type.getType(Marker.class).getDescriptor(), false);
            }

            @Override
            @SuppressWarnings("PMD.UseVarargs") //overridden method
            public MethodVisitor visitMethod(final int access, final String name, final String desc,
                    final String signature, final String[] exceptions) {
                if (INIT.equals(name)) {
                    final Method staticCtor = new Method(INIT, key.getRight());
                    final Type[] argumentTypes = staticCtor.getArgumentTypes();
                    final Type[] exceptionTypes = toObjectTypes(exceptions);

                    {
                        final GeneratorAdapter mgen = new GeneratorAdapter(Opcodes.ACC_PUBLIC, staticCtor,
                                signature, exceptionTypes, writeClass);
                        mgen.visitCode();
                        mgen.loadThis();
                        for (int i = 0; i < argumentTypes.length; i++) {
                            mgen.loadArg(i);
                        }
                        mgen.invokeConstructor(supertype, staticCtor);
                        mgen.returnValue();
                        mgen.endMethod();
                    }
                    /*
                     * now declare a dummy constructor that will match, and discard,
                     * any originally inner-class bound constructor i.e. that set up a this$0 field.
                     * By doing this we can avoid playing with the stack that originally
                     * invoked such a constructor and simply rewrite the method
                     */
                    {
                        final Method instanceCtor = new Method(INIT, Type.VOID_TYPE,
                                ArrayUtils.insert(0, argumentTypes, OBJECT_TYPE));
                        final GeneratorAdapter mgen = new GeneratorAdapter(Opcodes.ACC_PUBLIC, instanceCtor,
                                signature, exceptionTypes, writeClass);
                        mgen.visitCode();
                        mgen.loadThis();
                        for (int i = 0; i < argumentTypes.length; i++) {
                            mgen.loadArg(i + 1);
                        }
                        mgen.invokeConstructor(supertype, staticCtor);
                        mgen.returnValue();
                        mgen.endMethod();
                    }
                    return null;
                }
                return null;
            }

            @Override
            public void visitEnd() {
                writeClass.visitEnd();
            }
        }, 0);
    }
    return result;
}

From source file:org.eclipse.objectteams.otredyn.bytecode.asm.MultiClassAdapter.java

License:Open Source License

@Override
public void visitEnd() {
    for (ClassVisitor visitor : visitors) {
        visitor.visitEnd();
    }
}

From source file:org.eclipse.sisu.scanners.QualifiedScanningTest.java

License:Open Source License

public void testEmptyMethods() {
    final AnnotationVisitor emptyAnnotationVisitor = new EmptyAnnotationVisitor();

    emptyAnnotationVisitor.visit(null, null);
    emptyAnnotationVisitor.visitEnum(null, null, null);
    emptyAnnotationVisitor.visitAnnotation(null, null);
    emptyAnnotationVisitor.visitArray(null);
    emptyAnnotationVisitor.visitEnd();//from   w  w  w  .  j  ava  2s . c o m

    final ClassVisitor emptyClassVisitor = new EmptyClassVisitor();

    emptyClassVisitor.visit(0, 0, null, null, null, null);
    emptyClassVisitor.visitAnnotation(null, false);
    emptyClassVisitor.visitAttribute(null);
    emptyClassVisitor.visitSource(null, null);
    emptyClassVisitor.visitEnd();
}

From source file:org.elasticsearch.painless.node.SSource.java

License:Apache License

public void write() {
    // Create the ClassWriter.

    int classFrames = ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS;
    int classAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL;
    String classBase = BASE_CLASS_TYPE.getInternalName();
    String className = CLASS_TYPE.getInternalName();
    String classInterfaces[] = reserved.usesScore()
            ? new String[] { WriterConstants.NEEDS_SCORE_TYPE.getInternalName() }
            : null;/*from w  w  w . j a  va 2s  .co  m*/

    ClassWriter writer = new ClassWriter(classFrames);
    ClassVisitor visitor = writer;

    // if picky is enabled, turn on some checks. instead of VerifyError at the end, you get a helpful stacktrace.
    if (settings.isPicky()) {
        visitor = new SimpleChecksAdapter(visitor);
    }

    if (debugStream != null) {
        visitor = new TraceClassVisitor(visitor, debugStream, null);
    }
    visitor.visit(WriterConstants.CLASS_VERSION, classAccess, className, null, classBase, classInterfaces);
    visitor.visitSource(Location.computeSourceName(name, source), null);

    // Write the constructor:
    MethodWriter constructor = new MethodWriter(Opcodes.ACC_PUBLIC, CONSTRUCTOR, visitor,
            globals.getStatements(), settings);
    constructor.visitCode();
    constructor.loadThis();
    constructor.loadArgs();
    constructor.invokeConstructor(org.objectweb.asm.Type.getType(Executable.class), CONSTRUCTOR);
    constructor.returnValue();
    constructor.endMethod();

    // Write the execute method:
    MethodWriter execute = new MethodWriter(Opcodes.ACC_PUBLIC, EXECUTE, visitor, globals.getStatements(),
            settings);
    execute.visitCode();
    write(execute, globals);
    execute.endMethod();

    // Write all functions:
    for (SFunction function : functions) {
        function.write(visitor, settings, globals);
    }

    // Write all synthetic functions. Note that this process may add more :)
    while (!globals.getSyntheticMethods().isEmpty()) {
        List<SFunction> current = new ArrayList<>(globals.getSyntheticMethods().values());
        globals.getSyntheticMethods().clear();
        for (SFunction function : current) {
            function.write(visitor, settings, globals);
        }
    }

    // Write the constants
    if (false == globals.getConstantInitializers().isEmpty()) {
        Collection<Constant> inits = globals.getConstantInitializers().values();

        // Fields
        for (Constant constant : inits) {
            visitor.visitField(Opcodes.ACC_FINAL | Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, constant.name,
                    constant.type.getDescriptor(), null, null).visitEnd();
        }

        // Initialize the constants in a static initializer
        final MethodWriter clinit = new MethodWriter(Opcodes.ACC_STATIC, WriterConstants.CLINIT, visitor,
                globals.getStatements(), settings);
        clinit.visitCode();
        for (Constant constant : inits) {
            constant.initializer.accept(clinit);
            clinit.putStatic(CLASS_TYPE, constant.name, constant.type);
        }
        clinit.returnValue();
        clinit.endMethod();
    }

    // End writing the class and store the generated bytes.

    visitor.visitEnd();
    bytes = writer.toByteArray();
}

From source file:org.jephyr.common.agent.DelegationClassAdapter.java

License:Open Source License

@Override
public void visitEnd() {
    ClassVisitor cv1 = delegate();
    if (cv1 != null) {
        cv1.visitEnd();
    }
}

From source file:org.jruby.compiler.util.HandleFactory.java

License:LGPL

public static byte[] createHandleBytes(Method method, String name) {
    Class returnType = method.getReturnType();
    Class[] paramTypes = method.getParameterTypes();
    ClassVisitor cv = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cv.visit(ACC_PUBLIC | ACC_FINAL | ACC_SUPER, V1_5, name, null, p(Handle.class), null);

    SkinnyMethodAdapter m;/*from   ww  w  .jav a  2 s .  c  o  m*/
    String signature;
    boolean needsArgsVersion = true;
    switch (paramTypes.length) {
    case 0:
        signature = sig(Object.class, Object.class);
        break;
    case 1:
        signature = sig(Object.class, Object.class, Object.class);
        break;
    case 2:
        signature = sig(Object.class, Object.class, Object.class, Object.class);
        break;
    case 3:
        signature = sig(Object.class, Object.class, Object.class, Object.class, Object.class);
        break;
    //        case 4:
    //            signature = sig(Object.class, Object.class, Object.class, Object.class, Object.class);
    //            break;
    //        case 5:
    //            signature = sig(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class);
    //            break;
    default:
        needsArgsVersion = false;
        signature = sig(Object.class, Object.class, Object[].class);
        break;
    }
    m = new SkinnyMethodAdapter(cv, ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC, "invoke", signature, null, null);

    m.start();

    // load receiver
    if (!Modifier.isStatic(method.getModifiers())) {
        m.aload(1); // receiver
        if (method.getDeclaringClass() != Object.class) {
            m.checkcast(p(method.getDeclaringClass()));
        }
    }

    // load arguments
    switch (paramTypes.length) {
    case 0:
    case 1:
    case 2:
    case 3:
        //        case 4:
        //        case 5:
        for (int i = 0; i < paramTypes.length; i++) {
            loadUnboxedArgument(m, i + 2, paramTypes[i]);
        }
        break;
    default:
        for (int i = 0; i < paramTypes.length; i++) {
            m.aload(2); // Object[] args
            m.pushInt(i);
            m.aaload();
            Class paramClass = paramTypes[i];
            if (paramClass.isPrimitive()) {
                Class boxType = getBoxType(paramClass);
                m.checkcast(p(boxType));
                m.invokevirtual(p(boxType), paramClass.toString() + "Value", sig(paramClass));
            } else if (paramClass != Object.class) {
                m.checkcast(p(paramClass));
            }
        }
        break;
    }

    if (Modifier.isStatic(method.getModifiers())) {
        m.invokestatic(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes));
    } else if (Modifier.isInterface(method.getDeclaringClass().getModifiers())) {
        m.invokeinterface(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes));
    } else {
        m.invokevirtual(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes));
    }

    if (returnType == void.class) {
        m.aconst_null();
    } else if (returnType.isPrimitive()) {
        Class boxType = getBoxType(returnType);
        m.invokestatic(p(boxType), "valueOf", sig(boxType, returnType));
    }
    m.areturn();
    m.end();

    if (needsArgsVersion) {
        m = new SkinnyMethodAdapter(cv, ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC, "invoke",
                sig(Object.class, Object.class, Object[].class), null, null);

        m.start();

        // load handle
        m.aload(0);

        // load receiver
        m.aload(1);

        // load arguments
        for (int i = 0; i < paramTypes.length; i++) {
            m.aload(2); // args array
            m.ldc(i);
            m.aaload(); // i'th argument
        }

        // invoke specific arity version
        m.invokevirtual(name, "invoke",
                sig(Object.class, params(Object.class, Object.class, paramTypes.length)));

        // return result
        m.areturn();
        m.end();
    }

    // constructor
    m = new SkinnyMethodAdapter(cv, ACC_PUBLIC, "<init>", sig(void.class), null, null);
    m.start();
    m.aload(0);
    m.invokespecial(p(Handle.class), "<init>", sig(void.class));
    m.voidreturn();
    m.end();

    cv.visitEnd();

    byte[] bytes = ((ClassWriter) cv).toByteArray();

    return bytes;
}

From source file:org.kjots.json.object.JsonObjectGeneratorBase.java

License:Apache License

/**
 * Generate the class.//from   ww w.  j  a  va2 s  .  c o m
 *
 * @param classVisitor The class visitor.
 * @param jsonObjectClass The class of the JSON object.
 * @param jsonObjectType The type of the JSON object.
 * @param superJsonObjectImplType The type of the super JSON object implementation.
 */
private void generateClass(ClassVisitor classVisitor, Class<? extends JsonObject> jsonObjectClass,
        Type jsonObjectType, Type superJsonObjectImplType) {
    Type jsonObjectImplType = Type
            .getObjectType(jsonObjectType.getInternalName() + "$" + this.jsonObjectImplClass.getSimpleName());

    classVisitor.visit(V1_6, ACC_PUBLIC + ACC_SUPER, jsonObjectImplType, null, superJsonObjectImplType,
            jsonObjectType);

    this.generateConstructor(classVisitor, jsonObjectImplType, superJsonObjectImplType);

    for (java.lang.reflect.Method method : jsonObjectClass.getDeclaredMethods()) {
        if (method.getAnnotation(JsonFunction.class) != null) {
            this.generateFunctionMethod(classVisitor, jsonObjectImplType, jsonObjectClass,
                    Method.getMethod(method), method.getAnnotation(JsonFunction.class), method.isVarArgs());
        } else if (method.getAnnotation(JsonException.class) != null) {
            this.generateExceptionMethod(classVisitor, jsonObjectImplType, jsonObjectClass,
                    Method.getMethod(method), method.getAnnotation(JsonException.class), method.isVarArgs());
        } else if (method.getAnnotation(JsonProperty.class) != null) {
            this.generatePropertyMethod(classVisitor, jsonObjectImplType, method, Method.getMethod(method),
                    method.getAnnotation(JsonProperty.class));
        } else {
            throw new IllegalArgumentException(
                    method.getName() + "() is not annotated with suitable annotation");
        }
    }

    Set<Method> implementedMethods = new HashSet<Method>(classVisitor.getImplementedMethods());

    for (GenericMethod declaredMethod : this.getExtraInterfaceMethods(jsonObjectClass)) {
        Method implementedMethod = null;

        if (declaredMethod.getGenericReturnType() || !declaredMethod.getGenericTypeIndices().isEmpty()) {
            implementedMethod = declaredMethod.getCompatibleMethod(implementedMethods);
        } else if (!declaredMethod.getGenericReturnType() && !implementedMethods.contains(declaredMethod)) {
            int returnTypeSort = declaredMethod.getReturnType().getSort();
            if (returnTypeSort == Type.ARRAY) {
                returnTypeSort = declaredMethod.getReturnType().getElementType().getSort();
            }

            if (returnTypeSort == Type.OBJECT) {
                GenericMethod newDeclaredMethod = new GenericMethod(declaredMethod.getName(),
                        declaredMethod.getDescriptor(), true, declaredMethod.getGenericTypeIndices());

                implementedMethod = newDeclaredMethod.getCompatibleMethod(implementedMethods);
            }
        }

        if (implementedMethod != null && !implementedMethod.equals(declaredMethod)) {
            this.generateBridgeMethod(classVisitor, jsonObjectImplType, declaredMethod, implementedMethod);
        }
    }

    classVisitor.visitEnd();
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Accepts a visitor and fills it with information for a given class.
 * @param classRep the representation for the top-level class.
 * @param cv the class visitor to accept.
 * @throws JavaGenerationException/*from w  ww.  j  a  va 2s  .  c  om*/
 */
private static void encodeClassAcceptingVisitor(JavaClassRep classRep, ClassVisitor cv)
        throws JavaGenerationException {

    // Get the fully-qualified internal class and superclass names.    
    final JavaTypeName classRepTypeName = classRep.getClassName();
    final String className = classRepTypeName.getJVMInternalName();
    final String superclassName = classRep.getSuperclassName().getJVMInternalName();

    // Determine if the class or any inner class contains assert statements.
    int assertPresence = classRep.getAssertionContainment();
    if ((assertPresence & JavaClassRep.ASSERTS_UNKNOWN) > 0) {
        assertPresence = AsmJavaBytecodeGenerator.containsAsserts(classRep);
    }

    // Create the interfaces[] array.
    final int nInterfaces = classRep.getNInterfaces();
    final String[] interfaces = new String[nInterfaces];
    for (int i = 0; i < nInterfaces; i++) {
        interfaces[i] = classRep.getInterface(i).getJVMInternalName();
    }

    //ACC_SUPER flag should always be set for the flags defining a class file.
    //(see the Java language specification under ACC_SUPER in the index. The flag is not set only
    //by older Java compilers and exists for backwards compatibility reasons).
    int classModifiers = classRep.getModifiers() | Opcodes.ACC_SUPER;
    //static inner classes are marked with the static modifier, but this is not a valid access flag for a class.
    classModifiers &= ~Modifier.STATIC;

    // We aren't generating or using generics, so the signature can be null
    String classSignature = null;
    cv.visit(Opcodes.V1_5, classModifiers, className, classSignature, superclassName, interfaces);

    //sourcefileName = null, since this class was not compiled from a Java source file.
    //However, if we are debugging byte codes, use a "fake" source file name as if this class were generated from a Java source file.
    //This eliminates a trivial difference between the byte code generated by ASM and that of javac and makes inspecting the
    //differences in a differencing tool easier.
    String sourceFileName = null;
    //        if (AsmJavaBytecodeGenerator.DEBUG_GENERATED_BYTECODE) {               
    String unqualifiedName = classRepTypeName.getUnqualifiedJavaSourceName();
    int dotPosition = unqualifiedName.indexOf('.');
    if (dotPosition != -1) {
        //get the top level class name.
        unqualifiedName = unqualifiedName.substring(0, dotPosition);
    }
    sourceFileName = unqualifiedName + ".java";
    //        }

    cv.visitSource(sourceFileName, null);

    //add the fields        
    for (int i = 0, nFields = classRep.getNFieldDeclarations(); i < nFields; ++i) {

        JavaFieldDeclaration fieldDeclaration = classRep.getFieldDeclaration(i);

        //todoBI it may be more efficient to handle initializers for static-fields here in the cases where it is possible
        //(int, long, float, double, String).
        cv.visitField(fieldDeclaration.getModifiers(), fieldDeclaration.getFieldName(),
                fieldDeclaration.getFieldType().getJVMDescriptor(), null, null);
    }

    /*
     * When dealing with assert statements there is possibly an additional field that needs to be
     * added.
     * If a class contains an assert statement a static final synthetic boolean field called '$assertionsDisabled' is
     * added.  This field is initialized in the class static initializer and is used to determine whether to
     * check or skip assertions.
     */
    if (assertPresence != JavaClassRep.ASSERTS_NONE) {

        if ((assertPresence & JavaClassRep.ASSERTS_IN_CLASS) > 0) {
            // We need to add a static final synthetic boolean field to indicate the enabled/disabled state of assertions.
            cv.visitField(Opcodes.ACC_FINAL + Opcodes.ACC_STATIC + Opcodes.ACC_SYNTHETIC, "$assertionsDisabled",
                    "Z", null, null);
        }
    }

    //add the constructors
    final int nConstructors = classRep.getNConstructors();
    if (nConstructors == 0) {
        //if empty, add the default constructor.             

        JavaConstructor defaultConstructor = new JavaConstructor(Modifier.PUBLIC,
                ((JavaTypeName.Reference.Object) classRepTypeName).getBaseName());
        defaultConstructor.addStatement(new JavaStatement.ReturnStatement());
        encodeConstructor(classRep, defaultConstructor, cv);

    } else {

        for (int i = 0; i < nConstructors; ++i) {
            encodeConstructor(classRep, classRep.getConstructor(i), cv);
        }
    }

    //add the methods
    for (int i = 0, nMethods = classRep.getNMethods(); i < nMethods; ++i) {

        encodeMethod(classRep, classRep.getMethod(i), cv);
    }

    //add the initializers for the static fields
    encodeClassInitializer(classRep, cv, (assertPresence & JavaClassRep.ASSERTS_IN_CLASS) > 0);

    //add the inner classes (these are basically just references to the inner classes)

    //if classRep itself is an inner class, call visitInnerClass on itself. This is what the eclipse java compiler does.
    //javac annotates for every inner class reference occurring within the class file e.g. a field declared of inner class type,
    //an instance of expression of inner class type, a throws declaration on a method where an inner class is thrown.
    if (classRepTypeName.isInnerClass()) {

        JavaTypeName.Reference.Object classTypeName = (JavaTypeName.Reference.Object) classRepTypeName;
        String internalImportName = classTypeName.getImportName().replace('.', '/');

        cv.visitInnerClass(classTypeName.getJVMInternalName(), internalImportName, classTypeName.getBaseName(),
                classRep.getModifiers());
    }

    /*
     * Previously we would call visitInnerClass for any inner classes associated with this class.  However,
     * we are no longer doing this.  
     * Bytecode is generated in different scenarios (i.e. static generation, dynamic generation, etc).  In some
     * scenarios inner classes are generated separately from the containing class.  In order to keep the generated
     * bytecode consistent between the dynamic and static scenarios wer are not adding the attributes for contained 
     * inner classes to the bytecode.
     * 
     for (int i = 0, nInnerClasses = classRep.getNInnerClasses(); i < nInnerClasses; ++i) {
            
    JavaClassRep innerClass = classRep.getInnerClass(i);
    JavaTypeName.Reference.Object innerClassTypeName = (JavaTypeName.Reference.Object)innerClass.getClassName();            
            
    cw.visitInnerClass(innerClassTypeName.getJVMInternalName(), className, innerClassTypeName.getBaseName(), innerClass.getModifiers());
    }               
            
    */

    cv.visitEnd();
}

From source file:org.simantics.databoard.binding.reflection.AsmBindingClassLoader.java

License:Open Source License

public byte[] createBindingClass(ClassInfo ci, String bindingClassName) {
    //System.out.println("BindingFactory: "+bindingClassName+" (for "+ci.clazz.getClassLoader()+")");
    int count = ci.fields.length;
    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    ClassVisitor cv = cw;//new CheckClassAdapter(cw);

    FieldVisitor fv;//from w  w w  .j  a va 2s .c om
    MethodVisitor mv;
    AnnotationVisitor av0;

    String className = ci.clazz.getName().replaceAll("\\.", "/");
    bindingClassName = bindingClassName.replaceAll("\\.", "/");
    Object[] classNameX = new Object[] { className };
    String signature = "L" + bindingClassName + ";";

    // Constructor
    String superClass = "org/simantics/databoard/binding/reflection/ClassBinding";
    cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, bindingClassName, null, superClass, null);

    // Constructor
    {
        mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/simantics/databoard/type/RecordType;)V", null,
                new String[] { "org/simantics/databoard/binding/error/BindingConstructionException" });

        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitLdcInsn(Type.getType("L" + className + ";"));
        mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "(Ljava/lang/Class;)V");

        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(PUTFIELD, bindingClassName, "type", "Lorg/simantics/databoard/type/Datatype;");

        Label l2 = new Label();
        mv.visitLabel(l2);
        mv.visitInsn(RETURN);

        Label l3 = new Label();
        mv.visitLabel(l3);
        mv.visitLocalVariable("this", signature, null, l0, l3, 0);
        mv.visitLocalVariable("type", "Lorg/simantics/databoard/type/RecordType;", null, l0, l3, 1);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
    }

    // getComponent
    {
        mv = cv.visitMethod(ACC_PUBLIC, "getComponent", "(Ljava/lang/Object;I)Ljava/lang/Object;", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, className);
        mv.visitVarInsn(ASTORE, 3);
        Label l1 = new Label();
        mv.visitLabel(l1);

        Label caseLabels[] = createFieldLabels(ci);
        Label elseLabel = new Label();

        if (count > 0) {
            // Switch
            mv.visitVarInsn(ILOAD, 2);
            mv.visitTableSwitchInsn(0, count - 1, elseLabel, caseLabels);

            // case i: x.field = value[i]
            for (int i = 0; i < count; i++) {
                Label label = caseLabels[i];
                Field field = ci.fields[i];
                String fieldName = field.getName();
                Class<?> fieldClass = ci.fields[i].getType();
                String typeDescriptor = toTypeDescriptor(fieldClass);

                Method getter = ci.getters[i];
                boolean useGetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && getter != null;

                mv.visitLabel(label);
                if (i == 0) {
                    mv.visitFrame(Opcodes.F_APPEND, 1, classNameX, 0, null);
                } else {
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                }

                // Read instance argument
                mv.visitVarInsn(ALOAD, 3);

                if (useGetter) {
                    // call getField
                    mv.visitMethodInsn(INVOKEVIRTUAL, className, getter.getName(), "()" + typeDescriptor);
                } else {
                    // Read field
                    mv.visitFieldInsn(GETFIELD, className, fieldName, typeDescriptor);
                }

                // Box 
                box(mv, fieldClass);

                mv.visitInsn(ARETURN);
            }

        }

        mv.visitLabel(elseLabel);
        if (count > 0) {
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        }
        mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Illegal field index");
        mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>",
                "(Ljava/lang/String;)V");
        mv.visitInsn(ATHROW);

        // End 
        Label l19 = new Label();
        mv.visitLabel(l19);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l19, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l19, 1);
        mv.visitLocalVariable("index", "I", null, l0, l19, 2);
        //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, l1, l19, 3);
        mv.visitMaxs(3, 4);
        mv.visitEnd();
    }

    // Create
    {
        mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)Ljava/lang/Object;", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        if (ci.beanConstructor != null) {
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, className);
            mv.visitInsn(DUP);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitMethodInsn(INVOKESPECIAL, className, "<init>",
                    "(Lorg/simantics/databoard/binding/Binding;)V");
            mv.visitVarInsn(ASTORE, 2);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents",
                    "(Ljava/lang/Object;[Ljava/lang/Object;)V");
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitInsn(ARETURN);
            Label l3 = new Label();
            mv.visitLabel(l3);
            mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l3, 0);
            mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);
            //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        } else if (ci.argsConstructor != null) {
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, className);
            mv.visitInsn(DUP);

            String constArgsDescriptor = "(";
            Class<?>[] args = ci.argsConstructor.getParameterTypes();
            for (int i = 0; i < count; i++) {
                Label label = new Label();
                Class<?> field = args[i];
                String fieldName = field.getName();
                Method getter = ci.getters[i];
                Class<?> fieldClass = ci.fields[i].getType();
                Class<?> boxClass = getBoxClass(fieldClass);
                String typeDescriptor = toTypeDescriptor(fieldClass);
                String boxTypeDescriptor = toTypeDescriptor(boxClass);
                constArgsDescriptor += typeDescriptor;

                mv.visitLabel(label);
                mv.visitVarInsn(ALOAD, 1);
                if (i < 6) {
                    mv.visitInsn(ICONST_0 + i);
                } else {
                    mv.visitIntInsn(BIPUSH, i);
                }

                mv.visitInsn(AALOAD);
                mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));
                unbox(mv, fieldClass);
            }

            Label l17 = new Label();
            mv.visitLabel(l17);
            constArgsDescriptor += ")V";
            mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", constArgsDescriptor);
            mv.visitInsn(ARETURN);
            Label l18 = new Label();
            mv.visitLabel(l18);
            mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l18, 0);
            mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l18, 1);
            mv.visitMaxs(21, 2);
            mv.visitEnd();

        } else {
            mv.visitCode();
            Label l0 = new Label();
            mv.visitLabel(l0);
            mv.visitTypeInsn(NEW, className);
            mv.visitInsn(DUP);
            mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
            mv.visitVarInsn(ASTORE, 2);
            Label l1 = new Label();
            mv.visitLabel(l1);
            mv.visitVarInsn(ALOAD, 0);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitVarInsn(ALOAD, 1);
            mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "setComponents",
                    "(Ljava/lang/Object;[Ljava/lang/Object;)V");
            Label l2 = new Label();
            mv.visitLabel(l2);
            mv.visitVarInsn(ALOAD, 2);
            mv.visitInsn(ARETURN);
            Label l3 = new Label();
            mv.visitLabel(l3);
            mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l3, 0);
            mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l0, l3, 1);
            //mv.visitLocalVariable("x", "L"+className+";", null, l1, l3, 2);
            mv.visitMaxs(3, 3);
            mv.visitEnd();
        }
    }

    // CreatePartial
    mv = cv.visitMethod(ACC_PUBLIC, "createPartial", "()Ljava/lang/Object;", null,
            new String[] { "org/simantics/databoard/binding/error/BindingException" });
    if (ci.beanConstructor != null) {
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitTypeInsn(NEW, className);
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Lorg/simantics/databoard/binding/Binding;)V");
        mv.visitInsn(ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l1, 0);
        mv.visitMaxs(3, 1);
        mv.visitEnd();
    } else if (ci.noArgsConstructor != null) {
        // return new MyClass();
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitTypeInsn(NEW, className);
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "()V");
        mv.visitInsn(ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l1, 0);
        mv.visitMaxs(2, 1);
        mv.visitEnd();
    } else {
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitIntInsn(BIPUSH, count);
        mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
        mv.visitVarInsn(ASTORE, 1);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitInsn(ICONST_0);
        mv.visitVarInsn(ISTORE, 2);
        Label l2 = new Label();
        mv.visitLabel(l2);
        Label l3 = new Label();
        mv.visitJumpInsn(GOTO, l3);
        Label l4 = new Label();
        mv.visitLabel(l4);
        mv.visitFrame(Opcodes.F_APPEND, 2, new Object[] { "[Ljava/lang/Object;", Opcodes.INTEGER }, 0, null);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, bindingClassName, "componentBindings",
                "[Lorg/simantics/databoard/binding/Binding;");
        mv.visitVarInsn(ILOAD, 2);
        mv.visitInsn(AALOAD);
        mv.visitVarInsn(ASTORE, 3);
        Label l5 = new Label();
        mv.visitLabel(l5);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitMethodInsn(INVOKEVIRTUAL, "org/simantics/databoard/binding/Binding", "createDefault",
                "()Ljava/lang/Object;");
        mv.visitInsn(AASTORE);
        Label l6 = new Label();
        mv.visitLabel(l6);
        mv.visitIincInsn(2, 1);
        mv.visitLabel(l3);
        mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        mv.visitVarInsn(ILOAD, 2);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitInsn(ARRAYLENGTH);
        mv.visitJumpInsn(IF_ICMPLT, l4);
        Label l7 = new Label();
        mv.visitLabel(l7);
        mv.visitLineNumber(109, l7);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(INVOKEVIRTUAL, bindingClassName, "create",
                "([Ljava/lang/Object;)Ljava/lang/Object;");
        mv.visitInsn(ARETURN);
        Label l8 = new Label();
        mv.visitLabel(l8);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, l8, 0);
        mv.visitLocalVariable("values", "[Ljava/lang/Object;", null, l1, l8, 1);
        mv.visitLocalVariable("i", "I", null, l2, l7, 2);
        mv.visitLocalVariable("fb", "Lorg/simantics/databoard/binding/Binding;", null, l5, l6, 3);
        mv.visitMaxs(3, 4);
        mv.visitEnd();
    }

    // setComponent
    {
        mv = cv.visitMethod(ACC_PUBLIC, "setComponent", "(Ljava/lang/Object;ILjava/lang/Object;)V", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, className);
        mv.visitVarInsn(ASTORE, 4);
        Label endLabel = new Label();
        Label l1 = new Label();
        mv.visitLabel(l1);

        Label elseLabel = new Label();
        Label labels[] = new Label[count];
        for (int i = 0; i < count; i++)
            labels[i] = new Label();

        if (count > 0) {
            mv.visitVarInsn(ILOAD, 2);
            mv.visitTableSwitchInsn(0, count - 1, elseLabel, labels);

            for (int i = 0; i < count; i++) {
                Label label = labels[i];
                mv.visitLabel(label);
                Field field = ci.fields[i];
                String fieldName = field.getName();
                Class<?> fieldClass = ci.fields[i].getType();
                Class<?> boxClass = getBoxClass(fieldClass);
                String typeDescriptor = toTypeDescriptor(fieldClass);
                String boxTypeDescriptor = toTypeDescriptor(boxClass);

                Method setter = ci.setters[i];
                Class<?> setterClass = setter != null ? setter.getParameterTypes()[0] : null;
                boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter != null;

                if (i == 0) {
                    mv.visitFrame(Opcodes.F_APPEND, 1, classNameX, 0, null);
                } else {
                    mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                }
                mv.visitVarInsn(ALOAD, 4);
                mv.visitVarInsn(ALOAD, 3);
                mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));

                if (useSetter) {
                    unbox(mv, setterClass);
                    mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "(" + typeDescriptor + ")V");
                } else {
                    unbox(mv, fieldClass);
                    mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);
                }
                mv.visitInsn(RETURN);
            }
        }

        mv.visitLabel(elseLabel);
        mv.visitLineNumber(178, elseLabel);
        if (count > 0) {
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
        }
        mv.visitTypeInsn(NEW, "org/simantics/databoard/binding/error/BindingException");
        mv.visitInsn(DUP);
        mv.visitLdcInsn("Illegal field index");
        mv.visitMethodInsn(INVOKESPECIAL, "org/simantics/databoard/binding/error/BindingException", "<init>",
                "(Ljava/lang/String;)V");
        mv.visitInsn(ATHROW);

        mv.visitLabel(endLabel);
        mv.visitLocalVariable("this", "L" + bindingClassName + ";", null, l0, endLabel, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);
        mv.visitLocalVariable("index", "I", null, l0, endLabel, 2);
        mv.visitLocalVariable("value", "Ljava/lang/Object;", null, l0, endLabel, 3);
        //mv.visitLocalVariable("x", "L"+className+";", null, l1, endLabel, 4);
        mv.visitMaxs(3, 5);
        mv.visitEnd();
    }

    // IsImmutable
    {
        mv = cv.visitMethod(ACC_PUBLIC, "isImmutable", "()Z", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitInsn(ICONST_0);
        mv.visitInsn(IRETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    // IsInstance
    {
        mv = cv.visitMethod(ACC_PUBLIC, "isInstance", "(Ljava/lang/Object;)Z", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(INSTANCEOF, className);
        mv.visitInsn(IRETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, l1, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, l1, 1);
        mv.visitMaxs(1, 2);
        mv.visitEnd();
    }

    // SetComponents
    {
        mv = cv.visitMethod(ACC_PUBLIC + ACC_VARARGS, "setComponents",
                "(Ljava/lang/Object;[Ljava/lang/Object;)V", null,
                new String[] { "org/simantics/databoard/binding/error/BindingException" });
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitTypeInsn(CHECKCAST, className);
        mv.visitVarInsn(ASTORE, 3);
        Label firstLabel = l0;

        for (int i = 0; i < count; i++) {
            Label label = new Label();
            if (firstLabel == l0)
                firstLabel = label;
            Field field = ci.fields[i];
            String fieldName = field.getName();
            Class<?> fieldClass = ci.fields[i].getType();
            Class<?> boxClass = getBoxClass(fieldClass);
            String typeDescriptor = toTypeDescriptor(fieldClass);
            String boxTypeDescriptor = toTypeDescriptor(boxClass);

            Method setter = ci.setters[i];
            Class<?> setterClass = setter != null ? setter.getParameterTypes()[0] : null;
            boolean useSetter = ((field.getModifiers() & Modifier.PUBLIC) == 0) && setter != null;

            mv.visitLabel(label);
            mv.visitVarInsn(ALOAD, 3);
            mv.visitVarInsn(ALOAD, 2);
            if (i < 6) {
                mv.visitInsn(ICONST_0 + i);
            } else {
                mv.visitIntInsn(BIPUSH, i);
            }
            mv.visitInsn(AALOAD);
            mv.visitTypeInsn(CHECKCAST, toClassCanonicalName(boxClass));

            if (useSetter) {
                unbox(mv, setterClass);
                mv.visitMethodInsn(INVOKEVIRTUAL, className, setter.getName(), "(" + typeDescriptor + ")V");
            } else {
                unbox(mv, fieldClass);
                mv.visitFieldInsn(PUTFIELD, className, field.getName(), typeDescriptor);
            }

        }
        Label l17 = new Label();
        mv.visitLabel(l17);
        mv.visitInsn(RETURN);
        Label endLabel = new Label();
        mv.visitLabel(endLabel);
        mv.visitLocalVariable("this", "L" + className + ";", null, l0, endLabel, 0);
        mv.visitLocalVariable("obj", "Ljava/lang/Object;", null, l0, endLabel, 1);
        mv.visitLocalVariable("value", "[Ljava/lang/Object;", null, l0, endLabel, 2);
        //mv.visitLocalVariable("x", "Lorg/simantics/databoard/binding/reflection/MyClass;", null, firstLabel, endLabel, 3);
        mv.visitMaxs(3, 4);
        mv.visitEnd();
    }

    // Add primitive setters
    {
        addGetSetPrimitive(ci, cv, "Boolean", "Z", bindingClassName);
        addGetSetPrimitive(ci, cv, "Byte", "B", bindingClassName);
        addGetSetPrimitive(ci, cv, "Int", "I", bindingClassName);
        addGetSetPrimitive(ci, cv, "Long", "J", bindingClassName);
        addGetSetPrimitive(ci, cv, "Float", "F", bindingClassName);
        addGetSetPrimitive(ci, cv, "Double", "D", bindingClassName);
    }

    cv.visitEnd();
    return cw.toByteArray();
}