001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2003-2007 University of Maryland
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: */
019:
020: package edu.umd.cs.findbugs.bcel;
021:
022: import org.apache.bcel.Constants;
023: import org.apache.bcel.classfile.JavaClass;
024: import org.apache.bcel.classfile.Method;
025: import org.apache.bcel.generic.ConstantPoolGen;
026: import org.apache.bcel.generic.FieldInstruction;
027: import org.apache.bcel.generic.InvokeInstruction;
028: import org.apache.bcel.generic.ObjectType;
029:
030: import edu.umd.cs.findbugs.ba.ClassNotFoundExceptionParser;
031: import edu.umd.cs.findbugs.classfile.ClassDescriptor;
032: import edu.umd.cs.findbugs.classfile.DescriptorFactory;
033: import edu.umd.cs.findbugs.classfile.FieldDescriptor;
034: import edu.umd.cs.findbugs.classfile.MethodDescriptor;
035: import edu.umd.cs.findbugs.util.ClassName;
036:
037: /**
038: * Utility methods for detectors and analyses using BCEL.
039: *
040: * @author David Hovemeyer
041: */
042: public abstract class BCELUtil {
043: /**
044: * Construct a MethodDescriptor from JavaClass and method.
045: *
046: * @param jclass a JavaClass
047: * @param method a Method belonging to the JavaClass
048: * @return a MethodDescriptor identifying the method
049: */
050: public static MethodDescriptor getMethodDescriptor(
051: JavaClass jclass, Method method) {
052: return DescriptorFactory.instance().getMethodDescriptor(
053: jclass.getClassName().replace('.', '/'),
054: method.getName(), method.getSignature(),
055: method.isStatic());
056: }
057:
058: /**
059: * Get a MethodDescriptor describing the method called by
060: * given InvokeInstruction.
061: *
062: * @param inv the InvokeInstruction
063: * @param cpg ConstantPoolGen of class containing instruction
064: * @return MethodDescriptor describing the called method
065: */
066: public static MethodDescriptor getCalledMethodDescriptor(
067: InvokeInstruction inv, ConstantPoolGen cpg) {
068: String calledClassName = inv.getClassName(cpg)
069: .replace('.', '/');
070: String calledMethodName = inv.getMethodName(cpg);
071: String calledMethodSig = inv.getSignature(cpg);
072: boolean isStatic = inv.getOpcode() == Constants.INVOKESTATIC;
073:
074: return DescriptorFactory.instance().getMethodDescriptor(
075: calledClassName, calledMethodName, calledMethodSig,
076: isStatic);
077: }
078:
079: /**
080: * Get FieldDescriptor describing the field accessed by given FieldInstruction.
081: *
082: * @param fins a FieldInstruction
083: * @param cpg ConstantPoolGen for the method containing the FieldInstruction
084: * @return FieldDescriptor describing the field accessed by given FieldInstruction
085: */
086: public static FieldDescriptor getAccessedFieldDescriptor(
087: FieldInstruction fins, ConstantPoolGen cpg) {
088: String className = fins.getClassName(cpg);
089: String fieldName = fins.getName(cpg);
090: String fieldSig = fins.getSignature(cpg);
091: boolean isStatic = (fins.getOpcode() == Constants.GETSTATIC || fins
092: .getOpcode() == Constants.PUTSTATIC);
093: return DescriptorFactory.instance().getFieldDescriptor(
094: className, fieldName, fieldSig, isStatic);
095: }
096:
097: /**
098: * Construct a ClassDescriptor from a JavaClass.
099: *
100: * @param jclass a JavaClass
101: * @return a ClassDescriptor identifying that JavaClass
102: */
103: public static ClassDescriptor getClassDescriptor(JavaClass jclass) {
104: return DescriptorFactory.instance().getClassDescriptor(
105: ClassName.toSlashedClassName(jclass.getClassName()));
106: }
107:
108: private static final int JDK15_MAJOR = 48;
109: private static final int JDK15_MINOR = 0;
110:
111: /**
112: * Checks if classfile was compiled for pre 1.5 target
113: */
114: public static boolean preTiger(JavaClass jclass) {
115: return jclass.getMajor() < JDK15_MAJOR
116: || (jclass.getMajor() == JDK15_MAJOR && jclass
117: .getMinor() < JDK15_MINOR);
118:
119: }
120:
121: /**
122: * Get a ClassDescriptor for the class described by given ObjectType object.
123: *
124: * @param type an ObjectType
125: * @return a ClassDescriptor for the class described by the ObjectType
126: */
127: public static ClassDescriptor getClassDescriptor(ObjectType type) {
128: return DescriptorFactory.instance()
129: .getClassDescriptorForDottedClassName(
130: type.getClassName());
131: }
132:
133: /**
134: * Throw a ClassNotFoundException to indicate that class named
135: * by given ClassDescriptor cannot be found.
136: * The exception message is formatted in a way that can
137: * be decoded by ClassNotFoundExceptionParser.
138: *
139: * @param classDescriptor ClassDescriptor naming a class that cannot be found
140: * @throws ClassNotFoundException
141: * @see ClassNotFoundExceptionParser
142: */
143: public static void throwClassNotFoundException(
144: ClassDescriptor classDescriptor)
145: throws ClassNotFoundException {
146: throw new ClassNotFoundException("Class "
147: + classDescriptor.toDottedClassName()
148: + " cannot be resolved");
149: }
150: }
|