001: package csdl.jblanket.modifier;
002:
003: import csdl.jblanket.JBlanketException;
004: import csdl.jblanket.methodset.MethodInfo;
005: import csdl.jblanket.methodset.MethodSet;
006: import csdl.jblanket.methodset.MethodSetManager;
007: import csdl.jblanket.util.MethodCategories;
008:
009: import java.io.FileOutputStream;
010: import java.io.IOException;
011: import java.util.ArrayList;
012: import java.util.Date;
013:
014: import org.apache.bcel.classfile.JavaClass;
015: import org.apache.bcel.classfile.Method;
016: import org.apache.bcel.generic.ConstantPoolGen;
017: import org.apache.bcel.generic.LineNumberGen;
018: import org.apache.bcel.generic.MethodGen;
019: import org.apache.bcel.generic.Type;
020:
021: /**
022: * Provides a counter for all of the methods in the system. All methods are found and stored in an
023: * XML file specified by 'totalFile' in csdl.jblanket.util.MethodCategories.
024: * <p>
025: * <i>Debug must be turned "on" when compiling to add line numbers.</i> If no line numbers are
026: * detected, then no methods are recorded.
027: *
028: * @author Joy M. Agustin
029: * @version $Id: MethodCounter.java,v 1.3 2005/03/08 08:02:01 timshadel Exp $
030: */
031: public class MethodCounter {
032:
033: /** Container for all of the methods found */
034: private MethodSet methodSet;
035:
036: /** Output file for total methods, including abstract and native */
037: private String totalFile;
038: /** Container for byte code methods */
039: private MethodSet totalSet;
040:
041: /**
042: * Constructs a new MethodCounter object for 'totalFile'.
043: */
044: public MethodCounter() {
045:
046: this .totalFile = MethodCategories.getInstance().getFileName(
047: "totalFile");
048: this .totalSet = MethodSetManager.getInstance().getMethodSet(
049: totalFile);
050: }
051:
052: /**
053: * Finds the type signatures of all methods in a Java class. If no line numbers are detected in
054: * a method, then it must be an abstract method.
055: * <p>
056: * NOTE: Unable to distinguish between the user implemented and compiler created constructors.
057: * Therefore, use the excludeConstructors to either exclude or include all constructors.
058: *
059: * @param clazz the class to be recorded.
060: * @param excludeConstructors describes if constructors should be excluded from coverage.
061: */
062: public void findAllMethods(JavaClass clazz,
063: boolean excludeConstructors) {
064:
065: // get all methods
066: ConstantPoolGen pool = new ConstantPoolGen(clazz
067: .getConstantPool());
068: Method[] methods = clazz.getMethods();
069: String clazzName = clazz.getClassName();
070:
071: // check each method in the class
072: for (int i = 0; i < methods.length; i++) {
073: MethodGen method = new MethodGen(methods[i], clazzName,
074: pool);
075: String methodName = method.getName();
076:
077: // get debug line numbers of source code
078: LineNumberGen[] lineNumbers = method.getLineNumbers();
079: // check if line numbers are present
080: /* if (lineNumbers.length == 0) {
081: // found abstract method, do nothing
082: continue;
083: }
084:
085: // check for void method containing only a
086: // return statement, perhaps inserted just by javac
087: // treat like abstract methods, since there's nothing to test
088: if (method.getType() == Type.VOID && lineNumbers.length == 1) {
089: continue;
090: }
091: */
092: // these methods are not implemented by the programmer
093: // <clinit> - class or interface initialization method
094: // class$ - constructor for super class
095: if ("<clinit>".equals(methodName)
096: || "class$".equals(methodName)) {
097: continue;
098: }
099: /*
100: // init - user implemented and default compiler created constructors;
101: else if (methodName.equals(constructor) && excludeConstructors) {
102: continue;
103: }
104: */
105:
106: // found method
107: Type[] paramType = method.getArgumentTypes();
108: ArrayList paramList = new ArrayList();
109: for (int j = 0; j < paramType.length; j++) {
110: paramList.add(MethodCollector
111: .reconstructType(paramType[j].getSignature()));
112: }
113:
114: // reconstruct names of constructors from default names, removing package prefix
115: if ("<init>".equals(methodName)) {
116: methodName = MethodCollector
117: .removePackagePrefix(clazzName);
118: }
119: if ("<clinit>".equals(methodName)) {
120: methodName = MethodCollector
121: .removePackagePrefix(clazzName)
122: + "[static initializer]";
123: }
124: methodName = methodName.replaceAll("<", "_").replaceAll(
125: ">", "_");
126: MethodInfo methodInfo = new MethodInfo(clazzName,
127: methodName, paramList);
128: this .totalSet.add(methodInfo);
129: }
130: }
131:
132: /**
133: * Stores all methods found to XML file 'totalFile'.
134: *
135: * @throws JBlanketException if cannot store methods.
136: */
137: public void storeAllMethods() throws JBlanketException {
138:
139: // store total methods to totalFile
140: try {
141: // throws FileNotFoundException
142: FileOutputStream fostream = new FileOutputStream(
143: this .totalFile);
144: // throws IOException
145: this .totalSet.store(fostream, null, new Date());
146: // throws FileNotFoundException
147: fostream.close();
148: } catch (IOException e) {
149: throw new JBlanketException("Unable to store methods to "
150: + this.totalFile, e);
151: }
152: }
153: }
|