/*
* FindBugs - Find Bugs in Java programs
* Copyright (C) 2003-2007 University of Maryland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs.ba.jsr305;
import java.util.HashMap;
import org.apache.bcel.generic.ConstantPoolGen;
import edu.umd.cs.findbugs.ba.CFG;
import edu.umd.cs.findbugs.ba.DataflowAnalysisException;
import edu.umd.cs.findbugs.ba.DepthFirstSearch;
import edu.umd.cs.findbugs.ba.XFactory;
import edu.umd.cs.findbugs.ba.XMethod;
import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow;
import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
import edu.umd.cs.findbugs.classfile.Global;
import edu.umd.cs.findbugs.classfile.IAnalysisCache;
import edu.umd.cs.findbugs.classfile.MethodDescriptor;
/**
* Factory to create and cache TypeQualifierDataflow objects for a particular
* method.
*
* @author David Hovemeyer
*/
public abstract class TypeQualifierDataflowFactory<AnalysisType extends TypeQualifierDataflowAnalysis, DataflowType extends TypeQualifierDataflow<AnalysisType>> {
private static class DataflowResult<DataflowType> {
DataflowType dataflow;
CheckedAnalysisException checkedException;
RuntimeException runtimeException;
DataflowType get() throws CheckedAnalysisException {
if (dataflow != null) {
return dataflow;
}
if (checkedException != null) {
throw checkedException;
}
throw runtimeException;
}
}
private final HashMap<TypeQualifierValue<?>, DataflowResult<DataflowType>> dataflowMap;
private final MethodDescriptor methodDescriptor;
public TypeQualifierDataflowFactory(MethodDescriptor methodDescriptor) {
this.methodDescriptor = methodDescriptor;
this.dataflowMap = new HashMap<TypeQualifierValue<?>, DataflowResult<DataflowType>>();
}
public DataflowType getDataflow(TypeQualifierValue<?> typeQualifierValue) throws CheckedAnalysisException {
DataflowResult<DataflowType> result = dataflowMap.get(typeQualifierValue);
if (result == null) {
result = compute(typeQualifierValue);
dataflowMap.put(typeQualifierValue, result);
}
return result.get();
}
private DataflowResult<DataflowType> compute(TypeQualifierValue<?> typeQualifierValue) {
DataflowResult<DataflowType> result = new DataflowResult<DataflowType>();
try {
IAnalysisCache analysisCache = Global.getAnalysisCache();
DepthFirstSearch dfs = analysisCache.getMethodAnalysis(DepthFirstSearch.class, methodDescriptor);
XMethod xmethod = XFactory.createXMethod(methodDescriptor);
CFG cfg = analysisCache.getMethodAnalysis(CFG.class, methodDescriptor);
ValueNumberDataflow vnaDataflow = analysisCache.getMethodAnalysis(ValueNumberDataflow.class, methodDescriptor);
ConstantPoolGen cpg = analysisCache.getClassAnalysis(ConstantPoolGen.class, methodDescriptor.getClassDescriptor());
DataflowType dataflow = getDataflow(dfs, xmethod, cfg, vnaDataflow, cpg, analysisCache, methodDescriptor,
typeQualifierValue);
result.dataflow = dataflow;
if (TypeQualifierDatabase.USE_DATABASE) {
try {
populateDatabase(dataflow, vnaDataflow, xmethod, typeQualifierValue);
} catch (DataflowAnalysisException e) {
analysisCache.getErrorLogger().logError("Error populating type qualifier database", e);
}
}
} catch (CheckedAnalysisException e) {
result.checkedException = e;
} catch (RuntimeException e) {
result.runtimeException = e;
}
return result;
}
protected abstract DataflowType getDataflow(DepthFirstSearch dfs, XMethod xmethod, CFG cfg, ValueNumberDataflow vnaDataflow,
ConstantPoolGen cpg, IAnalysisCache analysisCache, MethodDescriptor methodDescriptor1,
TypeQualifierValue<?> typeQualifierValue) throws CheckedAnalysisException;
protected abstract void populateDatabase(DataflowType dataflow, ValueNumberDataflow vnaDataflow, XMethod xmethod,
TypeQualifierValue<?> tqv) throws CheckedAnalysisException;
}