001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2005, 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.visitclass;
021:
022: import org.apache.bcel.Repository;
023: import org.apache.bcel.classfile.Attribute;
024: import org.apache.bcel.classfile.Code;
025: import org.apache.bcel.classfile.CodeException;
026: import org.apache.bcel.classfile.Constant;
027: import org.apache.bcel.classfile.ConstantClass;
028: import org.apache.bcel.classfile.ConstantPool;
029: import org.apache.bcel.classfile.InnerClass;
030: import org.apache.bcel.classfile.InnerClasses;
031: import org.apache.bcel.classfile.JavaClass;
032: import org.apache.bcel.classfile.LineNumber;
033: import org.apache.bcel.classfile.LineNumberTable;
034: import org.apache.bcel.classfile.Method;
035:
036: import edu.umd.cs.findbugs.annotations.CheckForNull;
037:
038: /**
039: * @author pugh
040: */
041: public class Util {
042: /**
043: * Determine the outer class of obj.
044: * @param obj
045: * @return JavaClass for outer class, or null if obj is not an outer class
046: * @throws ClassNotFoundException
047: */
048:
049: @CheckForNull
050: public static JavaClass getOuterClass(JavaClass obj)
051: throws ClassNotFoundException {
052: for (Attribute a : obj.getAttributes())
053: if (a instanceof InnerClasses) {
054: for (InnerClass ic : ((InnerClasses) a)
055: .getInnerClasses()) {
056: if (obj.getClassNameIndex() == ic
057: .getInnerClassIndex()) {
058: // System.out.println("Outer class is " + ic.getOuterClassIndex());
059: ConstantClass oc = (ConstantClass) obj
060: .getConstantPool().getConstant(
061: ic.getOuterClassIndex());
062: String ocName = oc.getBytes(obj
063: .getConstantPool());
064: return Repository.lookupClass(ocName);
065: }
066: }
067: }
068: return null;
069: }
070:
071: public static int getSizeOfSurroundingTryBlock(Method method,
072: String vmNameOfExceptionClass, int pc) {
073: return getSizeOfSurroundingTryBlock(method.getConstantPool(),
074: method.getCode(), vmNameOfExceptionClass, pc);
075: }
076:
077: public static int getSizeOfSurroundingTryBlock(
078: ConstantPool constantPool, Code code,
079: String vmNameOfExceptionClass, int pc) {
080: int size = Integer.MAX_VALUE;
081: int tightStartPC = 0;
082: int tightEndPC = Integer.MAX_VALUE;
083: if (code.getExceptionTable() == null)
084: return size;
085: for (CodeException catchBlock : code.getExceptionTable()) {
086: if (vmNameOfExceptionClass != null) {
087: Constant catchType = constantPool
088: .getConstant(catchBlock.getCatchType());
089: if (catchType == null
090: || catchType instanceof ConstantClass
091: && !((ConstantClass) catchType).getBytes(
092: constantPool).equals(
093: vmNameOfExceptionClass))
094: continue;
095: }
096: int startPC = catchBlock.getStartPC();
097: int endPC = catchBlock.getEndPC();
098: if (pc >= startPC && pc <= endPC) {
099: int this Size = endPC - startPC;
100: if (size > this Size) {
101: size = this Size;
102: tightStartPC = startPC;
103: tightEndPC = endPC;
104: }
105: }
106: }
107: if (size == Integer.MAX_VALUE)
108: return size;
109:
110: // try to guestimate number of lines that correspond
111: size = (size + 7) / 8;
112: LineNumberTable lineNumberTable = code.getLineNumberTable();
113: if (lineNumberTable == null)
114: return size;
115:
116: int count = 0;
117: for (LineNumber line : lineNumberTable.getLineNumberTable()) {
118: if (line.getStartPC() > tightEndPC)
119: break;
120: if (line.getStartPC() >= tightStartPC)
121: count++;
122: }
123: return count;
124:
125: }
126:
127: }
|