org.ow2.spec.testengine.AnalyzerClassVisitor Maven / Gradle / Ivy
The newest version!
/**
* EasyBeans
* Copyright (C) 2006 Bull S.A.S.
* Contact: [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: AnalyzerClassVisitor.java 5276 2010-01-08 16:22:04Z benoitf $
* --------------------------------------------------------------------------
*/
package org.ow2.spec.testengine;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
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.EmptyVisitor;
import org.ow2.spec.testengine.metadata.AnnotationMetadata;
import org.ow2.spec.testengine.metadata.ClassMetadata;
import org.ow2.spec.testengine.metadata.FieldMetadata;
import org.ow2.spec.testengine.metadata.InnerClassMetadata;
import org.ow2.spec.testengine.metadata.MethodMetadata;
public class AnalyzerClassVisitor implements ClassVisitor {
/**
* Map between package name and Map of .
*/
private Map> packageClassesMetadataMap = null;
private ClassMetadata classMetaData = null;
public AnalyzerClassVisitor(Map> packageClassesMetadataMap) {
this.packageClassesMetadataMap = packageClassesMetadataMap;
}
/**
* Visits the header of the class.
*
* @param version the class version.
* @param access the class's access flags (see {@link Opcodes}). This
* parameter also indicates if the class is deprecated.
* @param name the internal name of the class (see
* {@link Type#getInternalName() getInternalName}).
* @param signature the signature of this class. May be null if
* the class is not a generic one, and does not extend or implement
* generic classes or interfaces.
* @param superName the internal of name of the super class (see
* {@link Type#getInternalName() getInternalName}). For interfaces,
* the super class is {@link Object}. May be null, but
* only for the {@link Object} class.
* @param interfaces the internal names of the class's interfaces (see
* {@link Type#getInternalName() getInternalName}). May be
* null.
*/
public void visit(
int version,
int access,
String name,
String signature,
String superName,
String[] interfaces) {
// Build class representation
classMetaData = new ClassMetadata(access, name, signature, superName, interfaces);
}
/**
* Visits the source of the class.
*
* @param source the name of the source file from which the class was
* compiled. May be null.
* @param debug additional debug information to compute the correspondance
* between source and compiled elements of the class. May be
* null.
*/
public void visitSource(String source, String debug) {
}
/**
* Visits the enclosing class of the class. This method must be called only
* if the class has an enclosing class.
*
* @param owner internal name of the enclosing class of the class.
* @param name the name of the method that contains the class, or
* null if the class is not enclosed in a method of its
* enclosing class.
* @param desc the descriptor of the method that contains the class, or
* null if the class is not enclosed in a method of its
* enclosing class.
*/
public void visitOuterClass(String owner, String name, String desc) {
}
/**
* Visits an annotation of the class.
*
* @param desc the class descriptor of the annotation class.
* @param visible true if the annotation is visible at runtime.
* @return a non null visitor to visit the annotation values.
*/
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
AnnotationMetadata annotationMetadata = new AnnotationMetadata(desc, visible);
classMetaData.addAnnotationMetadata(annotationMetadata);
return new AnalyzerAnnotationVisitor(annotationMetadata);
}
/**
* Visits a non standard attribute of the class.
*
* @param attr an attribute.
*/
public void visitAttribute(Attribute attr) {
}
/**
* Visits information about an inner class. This inner class is not
* necessarily a member of the class being visited.
*
* @param name the internal name of an inner class (see
* {@link Type#getInternalName() getInternalName}).
* @param outerName the internal name of the class to which the inner class
* belongs (see {@link Type#getInternalName() getInternalName}). May
* be null.
* @param innerName the (simple) name of the inner class inside its
* enclosing class. May be null for anonymous inner
* classes.
* @param access the access flags of the inner class as originally declared
* in the enclosing class.
*/
public void visitInnerClass(
String name,
String outerName,
String innerName,
int access) {
// Not private, log it
if ((access & Opcodes.ACC_PRIVATE) == 0) {
InnerClassMetadata innerClassMetadata = new InnerClassMetadata(name, outerName, innerName, access);
classMetaData.addInnerClassMetadata(innerClassMetadata);
}
}
/**
* Visits a field of the class.
*
* @param access the field's access flags (see {@link Opcodes}). This
* parameter also indicates if the field is synthetic and/or
* deprecated.
* @param name the field's name.
* @param desc the field's descriptor (see {@link Type Type}).
* @param signature the field's signature. May be null if the
* field's type does not use generic types.
* @param value the field's initial value. This parameter, which may be
* null if the field does not have an initial value, must
* be an {@link Integer}, a {@link Float}, a {@link Long}, a
* {@link Double} or a {@link String} (for int,
* float, long or String fields
* respectively). This parameter is only used for static fields.
* Its value is ignored for non static fields, which must be
* initialized through bytecode instructions in constructors or
* methods.
* @return a visitor to visit field annotations and attributes, or
* null if this class visitor is not interested in
* visiting these annotations and attributes.
*/
public FieldVisitor visitField(
int access,
String name,
String desc,
String signature,
Object value) {
// Not private, log it
if ((access & Opcodes.ACC_PRIVATE) == 0) {
FieldMetadata fieldMetadata = new FieldMetadata(access, name, desc, signature, value);
classMetaData.addFieldMetadata(fieldMetadata);
}
return new EmptyVisitor();
}
/**
* Visits a method of the class. This method must return a new
* {@link MethodVisitor} instance (or null) each time it is
* called, i.e., it should not return a previously returned visitor.
*
* @param access the method's access flags (see {@link Opcodes}). This
* parameter also indicates if the method is synthetic and/or
* deprecated.
* @param name the method's name.
* @param desc the method's descriptor (see {@link Type Type}).
* @param signature the method's signature. May be null if the
* method parameters, return type and exceptions do not use generic
* types.
* @param exceptions the internal names of the method's exception classes
* (see {@link Type#getInternalName() getInternalName}). May be
* null.
* @return an object to visit the byte code of the method, or null
* if this class visitor is not interested in visiting the code of
* this method.
*/
public MethodVisitor visitMethod(
int access,
String name,
String desc,
String signature,
String[] exceptions) {
// If enum type and JDK 5.0, change access to
if ("java/lang/Enum".equals(classMetaData.getSuperName())) {
if ("values".equals(name)) {
access = 25;
}
}
// Not private, log it
if ((access & Opcodes.ACC_PRIVATE) == 0) {
MethodMetadata methodMetadata = new MethodMetadata(access, name, desc, signature, exceptions);
classMetaData.addMethodMetadata(methodMetadata);
}
return new EmptyVisitor();
}
/**
* Visits the end of the class. This method, which is the last one to be
* called, is used to inform the visitor that all the fields and methods of
* the class have been visited.
*/
public void visitEnd() {
String packageName = "";
String[] split = classMetaData.getName().split("/");
packageName += split[0];
packageName += ".";
packageName += split[1];
Map classMetadataMap = packageClassesMetadataMap.get(packageName);
if (classMetadataMap == null) {
classMetadataMap = new HashMap();
packageClassesMetadataMap.put(packageName, classMetadataMap);
}
classMetadataMap.put(classMetaData.getName(), classMetaData);
}
public void setUID(long uid) {
classMetaData.setUID(uid);
}
}