Search in sources :

Example 1 with AnnotationDescriptor

use of org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor in project felix by apache.

the class ClassManipulator method generateMethodHeader.

/**
 * Generate the method header of a POJO method.
 * This method header encapsulate the POJO method call to
 * signal entry exit and error to the container.
 * @param access : access flag.
 * @param name : method name.
 * @param desc : method descriptor.
 * @param signature : method signature.
 * @param exceptions : declared exceptions.
 * @param localVariables : the local variable nodes.
 * @param annotations : the annotations to move to this method.
 * @param paramAnnotations : the parameter annotations to move to this method.
 */
private void generateMethodHeader(int access, String name, String desc, String signature, String[] exceptions, List<LocalVariableNode> localVariables, List<AnnotationDescriptor> annotations, Map<Integer, List<AnnotationDescriptor>> paramAnnotations) {
    GeneratorAdapter mv = new GeneratorAdapter(cv.visitMethod(access, name, desc, signature, exceptions), access, name, desc);
    mv.visitCode();
    // If we have variables, we wraps the code within labels. The `lifetime` of the variables are bound to those
    // two variables.
    boolean hasArgumentLabels = localVariables != null && !localVariables.isEmpty();
    Label start = null;
    if (hasArgumentLabels) {
        start = new Label();
        mv.visitLabel(start);
    }
    mv.visitCode();
    Type returnType = Type.getReturnType(desc);
    // Compute result and exception stack location
    int result = -1;
    int exception;
    if (returnType.getSort() != Type.VOID) {
        // The method returns something
        result = mv.newLocal(returnType);
        exception = mv.newLocal(Type.getType(Throwable.class));
    } else {
        exception = mv.newLocal(Type.getType(Throwable.class));
    }
    Label l0 = new Label();
    Label l1 = new Label();
    Label l2 = new Label();
    mv.visitTryCatchBlock(l0, l1, l2, "java/lang/Throwable");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, generateMethodFlag(name, desc), "Z");
    mv.visitJumpInsn(IFNE, l0);
    mv.visitVarInsn(ALOAD, 0);
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc, false);
    mv.visitInsn(returnType.getOpcode(IRETURN));
    // end of the non intercepted method invocation.
    mv.visitLabel(l0);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    mv.loadArgArray();
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ENTRY, "(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)V", false);
    mv.visitVarInsn(ALOAD, 0);
    // Do not allow argument modification : just reload arguments.
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, PREFIX + name, desc, false);
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ISTORE), result);
    }
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
        mv.box(returnType);
    } else {
        mv.visitInsn(ACONST_NULL);
    }
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", EXIT, "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V", false);
    mv.visitLabel(l1);
    Label l7 = new Label();
    mv.visitJumpInsn(GOTO, l7);
    mv.visitLabel(l2);
    mv.visitVarInsn(ASTORE, exception);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, m_owner, IM_FIELD, "Lorg/apache/felix/ipojo/InstanceManager;");
    mv.visitVarInsn(ALOAD, 0);
    mv.visitLdcInsn(generateMethodId(name, desc));
    mv.visitVarInsn(ALOAD, exception);
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/apache/felix/ipojo/InstanceManager", ERROR, "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Throwable;)V", false);
    mv.visitVarInsn(ALOAD, exception);
    mv.visitInsn(ATHROW);
    mv.visitLabel(l7);
    if (returnType.getSort() != Type.VOID) {
        mv.visitVarInsn(returnType.getOpcode(ILOAD), result);
    }
    mv.visitInsn(returnType.getOpcode(IRETURN));
    // If we had arguments, we mark the end of the lifetime.
    Label end = null;
    if (hasArgumentLabels) {
        end = new Label();
        mv.visitLabel(end);
    }
    // Move annotations
    if (annotations != null) {
        for (AnnotationDescriptor ad : annotations) {
            ad.visitAnnotation(mv);
        }
    }
    // Move parameter annotations
    if (paramAnnotations != null && !paramAnnotations.isEmpty()) {
        for (Integer id : paramAnnotations.keySet()) {
            List<AnnotationDescriptor> ads = paramAnnotations.get(id);
            for (AnnotationDescriptor ad : ads) {
                ad.visitParameterAnnotation(id, mv);
            }
        }
    }
    // Write the arguments name.
    if (hasArgumentLabels) {
        for (LocalVariableNode var : localVariables) {
            mv.visitLocalVariable(var.name, var.desc, var.signature, start, end, var.index);
        }
    }
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : AnnotationDescriptor(org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor) Type(org.objectweb.asm.Type) Label(org.objectweb.asm.Label) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) LocalVariableNode(org.objectweb.asm.tree.LocalVariableNode)

Example 2 with AnnotationDescriptor

use of org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor in project felix by apache.

the class ClassManipulator method generateConstructor.

/**
 * Modify the given constructor to be something like:
 * <code>
 * this(null, params...);
 * return;
 * </code>
 * The actual constructor is modified to support the instance manager argument.
 * @param access : access flag
 * @param descriptor : the original constructor descriptor
 * @param signature : method signature
 * @param exceptions : declared exception
 * @param annotations : the annotations to move to this constructor.
 * @param locals : the local variables from the original constructors.
 */
private void generateConstructor(int access, String descriptor, String signature, String[] exceptions, List<AnnotationDescriptor> annotations, Map<Integer, List<AnnotationDescriptor>> paramAnnotations, LinkedHashMap<Integer, LocalVariableNode> locals) {
    GeneratorAdapter mv = new GeneratorAdapter(cv.visitMethod(access, "<init>", descriptor, signature, exceptions), access, "<init>", descriptor);
    // Compute the new signature
    // Remove the first (
    String newDesc = descriptor.substring(1);
    newDesc = "(Lorg/apache/felix/ipojo/InstanceManager;" + newDesc;
    mv.visitCode();
    Label start = new Label();
    mv.visitLabel(start);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitInsn(ACONST_NULL);
    mv.loadArgs();
    mv.visitMethodInsn(INVOKESPECIAL, m_owner, "<init>", newDesc, false);
    mv.visitInsn(RETURN);
    Label stop = new Label();
    mv.visitLabel(stop);
    // Move annotations
    if (annotations != null) {
        for (AnnotationDescriptor ad : annotations) {
            ad.visitAnnotation(mv);
        }
    }
    // Move parameter annotations if any
    if (paramAnnotations != null && !paramAnnotations.isEmpty()) {
        for (Integer id : paramAnnotations.keySet()) {
            List<AnnotationDescriptor> ads = paramAnnotations.get(id);
            for (AnnotationDescriptor ad : ads) {
                ad.visitParameterAnnotation(id, mv);
            }
        }
    }
    // Add local variables for the arguments.
    for (Map.Entry<Integer, LocalVariableNode> local : locals.entrySet()) {
        // initial descriptor.
        if (local.getValue().index <= Type.getArgumentTypes(descriptor).length) {
            mv.visitLocalVariable(local.getValue().name, local.getValue().desc, local.getValue().signature, start, stop, local.getValue().index);
        }
    }
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : AnnotationDescriptor(org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor) Label(org.objectweb.asm.Label) GeneratorAdapter(org.objectweb.asm.commons.GeneratorAdapter) LocalVariableNode(org.objectweb.asm.tree.LocalVariableNode)

Aggregations

AnnotationDescriptor (org.apache.felix.ipojo.manipulation.ClassChecker.AnnotationDescriptor)2 Label (org.objectweb.asm.Label)2 GeneratorAdapter (org.objectweb.asm.commons.GeneratorAdapter)2 LocalVariableNode (org.objectweb.asm.tree.LocalVariableNode)2 Type (org.objectweb.asm.Type)1