1 19 20 package edu.umd.cs.findbugs.classfile.impl; 21 22 import java.util.HashMap ; 23 import java.util.Map ; 24 import java.util.Map.Entry; 25 26 import edu.umd.cs.findbugs.classfile.CheckedAnalysisException; 27 import edu.umd.cs.findbugs.classfile.ClassDescriptor; 28 import edu.umd.cs.findbugs.classfile.IAnalysisCache; 29 import edu.umd.cs.findbugs.classfile.IAnalysisEngine; 30 import edu.umd.cs.findbugs.classfile.IClassAnalysisEngine; 31 import edu.umd.cs.findbugs.classfile.IClassPath; 32 import edu.umd.cs.findbugs.classfile.IDatabaseFactory; 33 import edu.umd.cs.findbugs.classfile.IErrorLogger; 34 import edu.umd.cs.findbugs.classfile.IMethodAnalysisEngine; 35 import edu.umd.cs.findbugs.classfile.MethodDescriptor; 36 import edu.umd.cs.findbugs.util.MapCache; 37 38 45 public class AnalysisCache implements IAnalysisCache { 46 50 private static final int CACHE_SIZE = 5; 51 52 private IClassPath classPath; 54 private IErrorLogger errorLogger; 55 private Map <Class <?>, IClassAnalysisEngine> classAnalysisEngineMap; 56 private Map <Class <?>, IMethodAnalysisEngine> methodAnalysisEngineMap; 57 private Map <Class <?>, IDatabaseFactory<?>> databaseFactoryMap; 58 private Map <Class <?>, Map <ClassDescriptor, Object >> classAnalysisMap; 59 private Map <Class <?>, Map <MethodDescriptor, Object >> methodAnalysisMap; 60 private Map <Class <?>, Object > databaseMap; 61 62 66 static class AnalysisError { 67 CheckedAnalysisException exception; 68 69 public AnalysisError(CheckedAnalysisException exception) { 70 this.exception = exception; 71 } 72 } 73 74 80 AnalysisCache(IClassPath classPath, IErrorLogger errorLogger) { 81 this.classPath = classPath; 82 this.errorLogger = errorLogger; 83 this.classAnalysisEngineMap = new HashMap <Class <?>, IClassAnalysisEngine>(); 84 this.methodAnalysisEngineMap = new HashMap <Class <?>, IMethodAnalysisEngine>(); 85 this.databaseFactoryMap = new HashMap <Class <?>, IDatabaseFactory<?>>(); 86 87 this.classAnalysisMap = new HashMap <Class <?>, Map <ClassDescriptor,Object >>(); 88 this.methodAnalysisMap = new HashMap <Class <?>, Map <MethodDescriptor,Object >>(); 89 90 this.databaseMap = new HashMap <Class <?>, Object >(); 91 } 92 93 96 public IClassPath getClassPath() { 97 return classPath; 98 } 99 100 103 public <E> E getClassAnalysis(Class <E> analysisClass, 104 ClassDescriptor classDescriptor) throws CheckedAnalysisException { 105 return analyzeClassOrMethod( 106 this, 107 classAnalysisMap, 108 classAnalysisEngineMap, 109 classDescriptor, 110 analysisClass); 111 } 112 113 116 public <E> E probeClassAnalysis(Class <E> analysisClass, ClassDescriptor classDescriptor) { 117 Map <ClassDescriptor, Object > descriptorMap = classAnalysisMap.get(analysisClass); 118 if (descriptorMap == null) { 119 return null; 120 } 121 return (E) descriptorMap.get(classDescriptor); 122 } 123 124 127 public <E> E getMethodAnalysis(Class <E> analysisClass, 128 MethodDescriptor methodDescriptor) throws CheckedAnalysisException { 129 return analyzeClassOrMethod( 130 this, 131 methodAnalysisMap, 132 methodAnalysisEngineMap, 133 methodDescriptor, 134 analysisClass); 135 } 136 137 151 static<DescriptorType, E> E analyzeClassOrMethod( 152 final AnalysisCache analysisCache, 153 final Map <Class <?>, Map <DescriptorType, Object >> analysisClassToDescriptorMapMap, 154 final Map <Class <?>, ? extends IAnalysisEngine<DescriptorType>> engineMap, 155 final DescriptorType descriptor, 156 final Class <E> analysisClass 157 ) throws CheckedAnalysisException { 158 159 Map <DescriptorType, Object > descriptorMap = analysisClassToDescriptorMapMap.get(analysisClass); 162 if (descriptorMap == null) { 163 descriptorMap = new MapCache<DescriptorType, Object >(CACHE_SIZE) { 166 IAnalysisEngine<DescriptorType> engine = engineMap.get(analysisClass); 167 168 171 @Override 172 protected boolean removeEldestEntry(Entry<DescriptorType, Object > eldest) { 173 if (engine.retainAnalysisResults()) { 174 return false; 175 } else { 176 return super.removeEldestEntry(eldest); 177 } 178 } 179 }; 180 analysisClassToDescriptorMapMap.put(analysisClass, descriptorMap); 181 } 182 183 Object analysisResult = descriptorMap.get(descriptor); 185 if (analysisResult == null) { 186 IAnalysisEngine<DescriptorType> engine = engineMap.get(analysisClass); 188 if (engine == null) { 189 throw new IllegalArgumentException ( 190 "No analysis engine registered to produce " + analysisClass.getName()); 191 } 192 193 try { 195 analysisResult = engine.analyze(analysisCache, descriptor); 196 } catch (CheckedAnalysisException e) { 197 analysisResult = new AnalysisError(e); 200 } 201 202 descriptorMap.put(descriptor, analysisResult); 204 } 205 206 if (analysisResult instanceof AnalysisError) { 208 throw ((AnalysisError) analysisResult).exception; 209 } 210 211 return (E) analysisResult; 214 } 215 216 219 public <E> void registerClassAnalysisEngine(Class <E> analysisResultType, 220 IClassAnalysisEngine classAnalysisEngine) { 221 classAnalysisEngineMap.put(analysisResultType, classAnalysisEngine); 222 } 223 224 227 public <E> void registerMethodAnalysisEngine(Class <E> analysisResultType, 228 IMethodAnalysisEngine methodAnalysisEngine) { 229 methodAnalysisEngineMap.put(analysisResultType, methodAnalysisEngine); 230 } 231 232 235 public <E> void registerDatabaseFactory(Class <E> databaseClass, IDatabaseFactory<E> databaseFactory) { 236 databaseFactoryMap.put(databaseClass, databaseFactory); 237 } 238 239 242 public <E> E getDatabase(Class <E> databaseClass) throws CheckedAnalysisException { 243 Object database = databaseMap.get(databaseClass); 244 245 if (database == null) { 246 try { 247 IDatabaseFactory<?> databaseFactory = databaseFactoryMap.get(databaseClass); 249 if (databaseFactory == null) { 250 throw new IllegalArgumentException ( 251 "No database factory registered for " + databaseClass.getName()); 252 } 253 254 database = databaseFactory.createDatabase(); 256 } catch (CheckedAnalysisException e) { 257 database = new AnalysisError(e); 259 } 260 261 databaseMap.put(databaseClass, database); 262 } 263 264 if (database instanceof AnalysisError) { 265 throw ((AnalysisError)database).exception; 266 } 267 268 return (E) database; 270 } 271 272 275 public IErrorLogger getErrorLogger() { 276 return errorLogger; 277 } 278 } 279 | Popular Tags |