//Tested with BCEL-5.1
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
package com.puppycrawl.tools.checkstyle.bcel;
import java.util.HashSet;
import java.util.Set;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.GETFIELD;
import org.apache.bcel.generic.GETSTATIC;
import org.apache.bcel.generic.INVOKESPECIAL;
import org.apache.bcel.generic.INVOKESTATIC;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.PUTFIELD;
import org.apache.bcel.generic.PUTSTATIC;
import com.puppycrawl.tools.checkstyle.api.Scope;
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
import com.puppycrawl.tools.checkstyle.bcel.classfile.ReferenceDAO;
import com.puppycrawl.tools.checkstyle.bcel.generic.FieldReference;
import com.puppycrawl.tools.checkstyle.bcel.generic.GETFIELDReference;
import com.puppycrawl.tools.checkstyle.bcel.generic.GETSTATICReference;
import com.puppycrawl.tools.checkstyle.bcel.generic.InvokeReference;
import com.puppycrawl.tools.checkstyle.bcel.generic.PUTFIELDReference;
import com.puppycrawl.tools.checkstyle.bcel.generic.PUTSTATICReference;
/**
* Records references during a deep parse tree traversal.
* @author Rick Giles
*/
public final class ReferenceVisitor extends EmptyDeepVisitor
{
/** singleton */
private static ReferenceVisitor sInstance = new ReferenceVisitor();
/** scope for checking field references */
private Set mFieldScopes = new HashSet();
/** scope for checking method references */
private Set mMethodScopes = new HashSet();
/** maps a JavaClass to a JavaClassDefinition */
private ReferenceDAO mReferenceDAO;
/** access to current constant pool */
private ConstantPoolGen mCurrentPoolGen;
/**
* Adds a reference when it visits an instruction that invokes
* a method or references a field.
* @author Rick Giles
* @version 18-Jun-2003
*/
private class GenericVisitor extends org.apache.bcel.generic.EmptyVisitor
{
/** @see org.apache.bcel.generic.Visitor */
public void visitINVOKESPECIAL(INVOKESPECIAL aINVOKESPECIAL)
{
addInvokeReference(
new InvokeReference(aINVOKESPECIAL, mCurrentPoolGen));
}
/** @see org.apache.bcel.generic.Visitor */
public void visitINVOKESTATIC(INVOKESTATIC aINVOKESTATIC)
{
addInvokeReference(
new InvokeReference(aINVOKESTATIC, mCurrentPoolGen));
}
/** @see org.apache.bcel.generic.Visitor */
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL aINVOKEVIRTUAL)
{
addInvokeReference(
new InvokeReference(aINVOKEVIRTUAL, mCurrentPoolGen));
}
/** @see org.apache.bcel.generic.Visitor */
public void visitGETSTATIC(GETSTATIC aGETSTATIC)
{
addFieldReference(
new GETSTATICReference(aGETSTATIC, mCurrentPoolGen));
}
/** @see org.apache.bcel.generic.Visitor */
public void visitGETFIELD(GETFIELD aGETFIELD)
{
addFieldReference(
new GETFIELDReference(aGETFIELD, mCurrentPoolGen));
}
/** @see org.apache.bcel.generic.Visitor */
public void visitPUTSTATIC(PUTSTATIC aPUTSTATIC)
{
addFieldReference(
new PUTSTATICReference(aPUTSTATIC, mCurrentPoolGen));
}
/** @see org.apache.bcel.generic.Visitor */
public void visitPUTFIELD(PUTFIELD aPUTFIELD)
{
addFieldReference(
new PUTFIELDReference(aPUTFIELD, mCurrentPoolGen));
}
}
/** prevent client construction */
private ReferenceVisitor()
{
setGenericVisitor(new GenericVisitor());
addFieldScope(Scope.PRIVATE);
}
/**
* Returns the singleton ReferencesVisitor
* @return the singleton
*/
public static ReferenceVisitor getInstance()
{
return sInstance;
}
/**
* Adds an invoke reference to the reference DAO.
* @param aReference the reference.
*/
private void addInvokeReference(InvokeReference aReference)
{
getReferenceDAO().addInvokeReference(aReference);
}
/**
* Adds an field reference to the reference DAO.
* @param aReference the reference.
*/
private void addFieldReference(FieldReference aReference)
{
getReferenceDAO().addFieldReference(aReference);
}
/** @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor */
public void visitSet(Set aJavaClasses)
{
mReferenceDAO =
new ReferenceDAO(aJavaClasses, mFieldScopes, mMethodScopes);
}
/**
* Gets the reference DAO.
* @return the reference DAO.
*/
public ReferenceDAO getReferenceDAO()
{
return mReferenceDAO;
}
/** @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor */
public void visitObject(Object aObject)
{
final JavaClass javaClass = (JavaClass) aObject;
final ConstantPool pool = javaClass.getConstantPool();
mCurrentPoolGen = new ConstantPoolGen(pool);
}
/**
* Finds the JavaClassDefinition for a given JavaClass.
* @param aJavaClass the JavaClass.
* @return the JavaClassDefinition for aJavaClass.
*/
public JavaClassDefinition findJavaClassDef(JavaClass aJavaClass)
{
return getReferenceDAO().findJavaClassDef(aJavaClass);
}
/**
* Includes a scope in the scope for checking field references.
* @param aScope the scope to include.
*/
public void addFieldScope(Scope aScope)
{
mFieldScopes.add(aScope);
}
/**
* Includes a scope in the scope for checking method references.
* @param aScope the scope to include.
*/
public void addMethodScope(Scope aScope)
{
mMethodScopes.add(aScope);
}
}