001: /*
002: * Bytecode Analysis Framework
003: * Copyright (C) 2003,2004 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.ba;
021:
022: import java.io.IOException;
023:
024: import org.apache.bcel.classfile.JavaClass;
025: import org.apache.bcel.classfile.Method;
026: import org.apache.bcel.generic.MethodGen;
027:
028: import edu.umd.cs.findbugs.SystemProperties;
029:
030: /**
031: * A test driver for dataflow analysis classes.
032: * It runs the dataflow analysis on the methods of a single class,
033: * and has options (properties) to restrict the analysis to a single
034: * method, and to print out a CFG annotated with dataflow values.
035: *
036: * @author David Hovemeyer
037: * @see Dataflow
038: * @see DataflowAnalysis
039: */
040: public abstract class DataflowTestDriver<Fact, AnalysisType extends BasicAbstractDataflowAnalysis<Fact>>
041: extends AbstractDataflowTestDriver {
042: /**
043: * Execute the analysis on a single class.
044: *
045: * @param filename the name of the class file
046: */
047: public void execute(String filename)
048: throws DataflowAnalysisException, CFGBuilderException,
049: IOException {
050: JavaClass jclass = new RepositoryClassParser(filename).parse();
051:
052: final RepositoryLookupFailureCallback lookupFailureCallback = new DebugRepositoryLookupFailureCallback();
053:
054: AnalysisContext analysisContext = AnalysisContext
055: .create(lookupFailureCallback);
056: analysisContext.setBoolProperty(
057: AnalysisFeatures.ACCURATE_EXCEPTIONS, true);
058:
059: configureAnalysisContext(analysisContext);
060:
061: ClassContext classContext = analysisContext
062: .getClassContext(jclass);
063: String methodName = SystemProperties
064: .getProperty("dataflow.method");
065:
066: Method[] methods = jclass.getMethods();
067: for (Method method : methods) {
068: if (methodName != null
069: && !method.getName().equals(methodName))
070: continue;
071:
072: MethodGen methodGen = classContext.getMethodGen(method);
073: if (methodGen == null)
074: continue;
075:
076: System.out
077: .println("-----------------------------------------------------------------");
078: System.out.println("Method: "
079: + SignatureConverter
080: .convertMethodSignature(methodGen));
081: System.out
082: .println("-----------------------------------------------------------------");
083:
084: execute(classContext, method);
085: }
086: }
087:
088: /**
089: * Execute the analysis on a single method of a class.
090: */
091: public void execute(ClassContext classContext, Method method)
092: throws DataflowAnalysisException, CFGBuilderException {
093:
094: Dataflow<Fact, AnalysisType> dataflow = createDataflow(
095: classContext, method);
096: System.out.println("Finished in " + dataflow.getNumIterations()
097: + " iterations");
098:
099: CFG cfg = classContext.getCFG(method);
100: examineResults(cfg, dataflow);
101:
102: if (SystemProperties.getBoolean("dataflow.printcfg")) {
103: CFGPrinter p = new DataflowCFGPrinter<Fact, AnalysisType>(
104: dataflow);
105: if (overrideIsForwards) {
106: p.setIsForwards(!p.isForwards());
107: }
108: p.print(System.out);
109: }
110: }
111:
112: /**
113: * Downcall method to create the dataflow driver object
114: * and execute the analysis.
115: *
116: * @param classContext ClassContext for the class
117: * @param method the Method
118: * @return the Dataflow driver
119: */
120: public abstract Dataflow<Fact, AnalysisType> createDataflow(
121: ClassContext classContext, Method method)
122: throws CFGBuilderException, DataflowAnalysisException;
123:
124: /**
125: * Downcall method to inspect the analysis results.
126: * Need not be implemented by subclasses.
127: *
128: * @param cfg the control flow graph
129: * @param dataflow the analysis results
130: */
131: public void examineResults(CFG cfg,
132: Dataflow<Fact, AnalysisType> dataflow) {
133: }
134: }
135:
136: // vim:ts=4
|