/*******************************************************************************
* Copyright (c) 2010 Fraunhofer IWU and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Fraunhofer IWU - initial API and implementation
*******************************************************************************/
package net.enilink.composition.asm.meta;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.Method;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
/**
* Reflective meta data for classes that also contains the visible and invisible
* annotations of their methods.
*/
public class ClassInfo extends ClassVisitor {
/**
* The class version.
*/
public int version;
/**
* The class's access flags (see {@link org.objectweb.asm.Opcodes}). This
* field also indicates if the class is deprecated.
*/
public int access;
/**
* The internal name of the class (see
* {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
*/
public String name;
/**
* The signature of the class. Mayt be <tt>null</tt>.
*/
public String signature;
/**
* The internal of name of the super class (see
* {@link org.objectweb.asm.Type#getInternalName() getInternalName}). For
* interfaces, the super class is {@link Object}. May be <tt>null</tt>, but
* only for the {@link Object} class.
*/
public String superName;
/**
* The internal names of the class's interfaces (see
* {@link org.objectweb.asm.Type#getInternalName() getInternalName}). This
* list is a list of {@link String} objects.
*/
public List<String> interfaces;
/**
* The methods of this class.
*/
public Map<Method, MethodNode> methods;
/**
* The runtime visible annotations of this class. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label visible
*/
public List<AnnotationNode> visibleAnnotations;
/**
* The runtime invisible annotations of this class. This list is a list of
* {@link AnnotationNode} objects. May be <tt>null</tt>.
*
* @associates org.objectweb.asm.tree.AnnotationNode
* @label invisible
*/
public List<AnnotationNode> invisibleAnnotations;
/**
* Constructs a new {@link ClassNode}.
*/
public ClassInfo() {
super(Opcodes.ASM5);
this.interfaces = new ArrayList<String>();
this.methods = new HashMap<Method, MethodNode>();
}
// ------------------------------------------------------------------------
// Implementation of the ClassVisitor interface
// ------------------------------------------------------------------------
public void visit(final int version, final int access, final String name,
final String signature, final String superName,
final String[] interfaces) {
this.version = version;
this.access = access;
this.name = name;
this.signature = signature;
this.superName = superName;
if (interfaces != null) {
this.interfaces.addAll(Arrays.asList(interfaces));
}
}
@Override
public AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) {
AnnotationNode an = new AnnotationNode(desc);
if (visible) {
if (visibleAnnotations == null) {
visibleAnnotations = new ArrayList<AnnotationNode>(1);
}
visibleAnnotations.add(an);
} else {
if (invisibleAnnotations == null) {
invisibleAnnotations = new ArrayList<AnnotationNode>(1);
}
invisibleAnnotations.add(an);
}
return an;
}
public MethodVisitor visitMethod(final int access, final String name,
final String desc, final String signature, final String[] exceptions) {
MethodNode mn = new MethodNode(Opcodes.ASM5, access, name, desc,
signature, exceptions) {
public void visitEnd() {
instructions.clear();
}
};
methods.put(new Method(name, desc), mn);
return mn;
}
public MethodNode getMethod(Method method) {
return methods.get(method);
}
@Override
public void visitSource(String source, String debug) {
}
@Override
public void visitOuterClass(String owner, String name, String desc) {
}
@Override
public void visitInnerClass(String name, String outerName,
String innerName, int access) {
}
@Override
public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
return null;
}
/**
* Copies annotations of this class.
*
* @param cv
* a class visitor.
*/
public void copyAnnotations(final ClassVisitor cv) {
// visits annotations
int i, n;
n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
for (i = 0; i < n; ++i) {
AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);
an.accept(cv.visitAnnotation(an.desc, true));
}
n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
for (i = 0; i < n; ++i) {
AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);
an.accept(cv.visitAnnotation(an.desc, false));
}
}
}