//Tested with BCEL-5.1 //http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/ package com.puppycrawl.tools.checkstyle.bcel.classfile; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.bcel.Repository; import org.apache.bcel.classfile.JavaClass; import org.apache.bcel.generic.Type; import com.puppycrawl.tools.checkstyle.bcel.generic.FieldReference; import com.puppycrawl.tools.checkstyle.bcel.generic.InvokeReference; /** * Accesses Method and Field references for a set of JavaClasses. * @author Rick Giles */ public class ReferenceDAO { /** * Creates a <code>ReferenceDAO</code> from a set of JavaClasses. * @param aJavaClasses the set of JavaClasses for this DAO. * @param aFieldScopes the scopes for field references. * @param aMethodScopes the scopes for method references. */ public ReferenceDAO(Set aJavaClasses, Set aFieldScopes, Set aMethodScopes) { mJavaClasses = new HashMap(aJavaClasses.size()); final Iterator it = aJavaClasses.iterator(); while (it.hasNext()) { final JavaClass javaClass = (JavaClass) it.next(); final JavaClassDefinition javaClassDef = new JavaClassDefinition(javaClass, aFieldScopes, aMethodScopes); mJavaClasses.put(javaClass, javaClassDef); } } /** maps a JavaClass to a JavaClassDefinition */ private Map mJavaClasses = null; /** * Finds the JavaClassDefinition for a given JavaClass. * @param aJavaClass the JavaClass. * @return the JavaClassDefinition keyed on aJavaClass. */ public JavaClassDefinition findJavaClassDef(JavaClass aJavaClass) { return (JavaClassDefinition) mJavaClasses.get(aJavaClass); } /** * Adds a reference for an invocation in the invoked method definition. * The invocation is of the form class.method(args). * @param aInvokeRef the invocation reference. */ public void addInvokeReference(InvokeReference aInvokeRef) { // find the class for the instruction final String className = aInvokeRef.getClassName(); JavaClass javaClass = Repository.lookupClass(className); final String methodName = aInvokeRef.getName(); final Type[] argTypes = aInvokeRef.getArgTypes(); // search up the class hierarchy for the class containing the // method definition. MethodDefinition narrowest = null; while ((javaClass != null) && (narrowest == null)) { final JavaClassDefinition javaClassDef = (JavaClassDefinition) mJavaClasses.get(javaClass); if (javaClassDef != null) { // find narrowest compatible in the current class narrowest = javaClassDef.findNarrowestMethod( className, methodName, argTypes); if (narrowest != null) { narrowest.addReference(aInvokeRef); } } // search the parent javaClass = javaClass.getSuperClass(); } } /** * Adds a reference to a field. * @param aFieldRef the field reference. */ public void addFieldReference(FieldReference aFieldRef) { final String className = aFieldRef.getClassName(); JavaClass javaClass = Repository.lookupClass(className); final String fieldName = aFieldRef.getName(); // search up the class hierarchy for the class containing the // method definition. FieldDefinition fieldDef = null; while ((javaClass != null) && (fieldDef == null)) { final JavaClassDefinition javaClassDef = (JavaClassDefinition) mJavaClasses.get(javaClass); if (javaClassDef != null) { fieldDef = javaClassDef.findFieldDef(fieldName); if (fieldDef != null) { fieldDef.addReference(aFieldRef); } } //search the parent javaClass = javaClass.getSuperClass(); } } /** * Finds the definition of the field of a field reference. * @param aFieldRef the reference to a field. * @return the definition of the field for aFieldRef. */ public FieldDefinition findFieldDef(FieldReference aFieldRef) { final String className = aFieldRef.getClassName(); JavaClass javaClass = Repository.lookupClass(className); final String fieldName = aFieldRef.getName(); // search up the class hierarchy for the class containing the // method definition. FieldDefinition result = null; while ((javaClass != null) && (result == null)) { final JavaClassDefinition javaClassDef = (JavaClassDefinition) mJavaClasses.get(javaClass); if (javaClassDef != null) { result = javaClassDef.findFieldDef(fieldName); } //search the parent javaClass = javaClass.getSuperClass(); } return result; } }