/* * 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; }