001: /*
002: * FindBugs - Find Bugs in Java programs
003: * Copyright (C) 2006, 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: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.HashSet;
026: import java.util.List;
027:
028: import org.apache.bcel.Repository;
029: import org.apache.bcel.classfile.JavaClass;
030:
031: import edu.umd.cs.findbugs.AnalysisCacheToRepositoryAdapter;
032: import edu.umd.cs.findbugs.ba.ch.Subtypes;
033: import edu.umd.cs.findbugs.ba.ch.Subtypes2;
034: import edu.umd.cs.findbugs.ba.npe.IsNullValueAnalysisFeatures;
035: import edu.umd.cs.findbugs.ba.npe.ParameterNullnessPropertyDatabase;
036: import edu.umd.cs.findbugs.ba.npe.ReturnValueNullnessPropertyDatabase;
037: import edu.umd.cs.findbugs.ba.npe.TypeQualifierNullnessAnnotationDatabase;
038: import edu.umd.cs.findbugs.ba.type.FieldStoreTypeDatabase;
039: import edu.umd.cs.findbugs.classfile.CheckedAnalysisException;
040: import edu.umd.cs.findbugs.classfile.ClassDescriptor;
041: import edu.umd.cs.findbugs.classfile.DescriptorFactory;
042: import edu.umd.cs.findbugs.classfile.Global;
043: import edu.umd.cs.findbugs.classfile.MethodDescriptor;
044: import edu.umd.cs.findbugs.classfile.analysis.ClassInfo;
045: import edu.umd.cs.findbugs.internalAnnotations.DottedClassName;
046: import edu.umd.cs.findbugs.util.ClassName;
047:
048: /**
049: * An AnalysisContext implementation that uses the
050: * IAnalysisCache. This class must only be used by
051: * FindBugs2, not the original FindBugs driver.
052: *
053: * @author David Hovemeyer
054: */
055: public class AnalysisCacheToAnalysisContextAdapter extends
056: AnalysisContext {
057:
058: static class DelegatingRepositoryLookupFailureCallback implements
059: RepositoryLookupFailureCallback {
060:
061: /* (non-Javadoc)
062: * @see edu.umd.cs.findbugs.classfile.IErrorLogger#logError(java.lang.String)
063: */
064: public void logError(String message) {
065: Global.getAnalysisCache().getErrorLogger()
066: .logError(message);
067: }
068:
069: /* (non-Javadoc)
070: * @see edu.umd.cs.findbugs.classfile.IErrorLogger#logError(java.lang.String, java.lang.Throwable)
071: */
072: public void logError(String message, Throwable e) {
073: Global.getAnalysisCache().getErrorLogger().logError(
074: message, e);
075: }
076:
077: /* (non-Javadoc)
078: * @see edu.umd.cs.findbugs.classfile.IErrorLogger#reportMissingClass(java.lang.ClassNotFoundException)
079: */
080: public void reportMissingClass(ClassNotFoundException ex) {
081: Global.getAnalysisCache().getErrorLogger()
082: .reportMissingClass(ex);
083: }
084:
085: /* (non-Javadoc)
086: * @see edu.umd.cs.findbugs.classfile.IErrorLogger#reportMissingClass(edu.umd.cs.findbugs.classfile.ClassDescriptor)
087: */
088: public void reportMissingClass(ClassDescriptor classDescriptor) {
089: Global.getAnalysisCache().getErrorLogger()
090: .reportMissingClass(classDescriptor);
091: }
092:
093: /* (non-Javadoc)
094: * @see edu.umd.cs.findbugs.classfile.IErrorLogger#reportSkippedAnalysis(edu.umd.cs.findbugs.classfile.MethodDescriptor)
095: */
096: public void reportSkippedAnalysis(MethodDescriptor method) {
097: Global.getAnalysisCache().getErrorLogger()
098: .reportSkippedAnalysis(method);
099: }
100:
101: }
102:
103: private RepositoryLookupFailureCallback lookupFailureCallback;
104:
105: /**
106: * Constructor.
107: */
108: public AnalysisCacheToAnalysisContextAdapter() {
109: this .lookupFailureCallback = new DelegatingRepositoryLookupFailureCallback();
110: }
111:
112: /* (non-Javadoc)
113: * @see edu.umd.cs.findbugs.ba.AnalysisContext#addApplicationClassToRepository(org.apache.bcel.classfile.JavaClass)
114: */
115: @Override
116: public void addApplicationClassToRepository(JavaClass appClass) {
117: throw new UnsupportedOperationException();
118: }
119:
120: /* (non-Javadoc)
121: * @see edu.umd.cs.findbugs.ba.AnalysisContext#addClasspathEntry(java.lang.String)
122: */
123: @Override
124: public void addClasspathEntry(String url) throws IOException {
125: throw new UnsupportedOperationException();
126: }
127:
128: /* (non-Javadoc)
129: * @see edu.umd.cs.findbugs.ba.AnalysisContext#clearClassContextCache()
130: */
131: @Override
132: public void clearClassContextCache() {
133: throw new UnsupportedOperationException();
134: }
135:
136: /* (non-Javadoc)
137: * @see edu.umd.cs.findbugs.ba.AnalysisContext#clearRepository()
138: */
139: @Override
140: public void clearRepository() {
141: // Set the backing store for the BCEL Repository to
142: // be the AnalysisCache.
143: Repository
144: .setRepository(new AnalysisCacheToRepositoryAdapter());
145: }
146:
147: /* (non-Javadoc)
148: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getAnnotationRetentionDatabase()
149: */
150: @Override
151: public AnnotationRetentionDatabase getAnnotationRetentionDatabase() {
152: return getDatabase(AnnotationRetentionDatabase.class);
153: }
154:
155: /* (non-Javadoc)
156: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getCheckReturnAnnotationDatabase()
157: */
158: @Override
159: public CheckReturnAnnotationDatabase getCheckReturnAnnotationDatabase() {
160: return getDatabase(CheckReturnAnnotationDatabase.class);
161: }
162:
163: /* (non-Javadoc)
164: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getClassContext(org.apache.bcel.classfile.JavaClass)
165: */
166: @Override
167: public ClassContext getClassContext(JavaClass javaClass) {
168: // This is a bit silly since we're doing an unnecessary ClassDescriptor->JavaClass lookup.
169: // However, we can be assured that it will succeed.
170:
171: ClassDescriptor classDescriptor = DescriptorFactory.instance()
172: .getClassDescriptor(
173: ClassName.toSlashedClassName(javaClass
174: .getClassName()));
175:
176: try {
177: return Global.getAnalysisCache().getClassAnalysis(
178: ClassContext.class, classDescriptor);
179: } catch (CheckedAnalysisException e) {
180: IllegalStateException ise = new IllegalStateException(
181: "Could not get ClassContext for JavaClass");
182: ise.initCause(e);
183: throw ise;
184: }
185: }
186:
187: /* (non-Javadoc)
188: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getClassContextStats()
189: */
190: @Override
191: public String getClassContextStats() {
192: return "<unknown ClassContext stats>";
193: }
194:
195: /* (non-Javadoc)
196: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getFieldStoreTypeDatabase()
197: */
198: @Override
199: public FieldStoreTypeDatabase getFieldStoreTypeDatabase() {
200: return getDatabase(FieldStoreTypeDatabase.class);
201: }
202:
203: /* (non-Javadoc)
204: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getJCIPAnnotationDatabase()
205: */
206: @Override
207: public JCIPAnnotationDatabase getJCIPAnnotationDatabase() {
208: return getDatabase(JCIPAnnotationDatabase.class);
209: }
210:
211: /* (non-Javadoc)
212: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getLookupFailureCallback()
213: */
214: @Override
215: public RepositoryLookupFailureCallback getLookupFailureCallback() {
216: return lookupFailureCallback;
217: }
218:
219: private TypeQualifierNullnessAnnotationDatabase tqNullnessDatabase;
220:
221: /* (non-Javadoc)
222: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getNullnessAnnotationDatabase()
223: */
224: @Override
225: public INullnessAnnotationDatabase getNullnessAnnotationDatabase() {
226: if (IsNullValueAnalysisFeatures.USE_TYPE_QUALIFIERS) {
227: if (tqNullnessDatabase == null) {
228: tqNullnessDatabase = new TypeQualifierNullnessAnnotationDatabase();
229: }
230: return tqNullnessDatabase;
231: } else {
232: return getDatabase(NullnessAnnotationDatabase.class);
233: }
234: }
235:
236: /* (non-Javadoc)
237: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getSourceFinder()
238: */
239: @Override
240: public SourceFinder getSourceFinder() {
241: return getDatabase(SourceFinder.class);
242: }
243:
244: /* (non-Javadoc)
245: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getSourceInfoMap()
246: */
247: @Override
248: public SourceInfoMap getSourceInfoMap() {
249: return getDatabase(SourceInfoMap.class);
250: }
251:
252: /* (non-Javadoc)
253: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getSubtypes()
254: */
255: @Override
256: public Subtypes getSubtypes() {
257: return getDatabase(Subtypes.class);
258: }
259:
260: /* (non-Javadoc)
261: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getUnconditionalDerefParamDatabase()
262: */
263: @Override
264: public ParameterNullnessPropertyDatabase getUnconditionalDerefParamDatabase() {
265: return getDatabase(ParameterNullnessPropertyDatabase.class);
266: }
267:
268: /* (non-Javadoc)
269: * @see edu.umd.cs.findbugs.ba.AnalysisContext#initDatabases()
270: */
271: @Override
272: public void initDatabases() {
273: // Databases are created on-demand - don't need to explicitly create them
274: }
275:
276: /* (non-Javadoc)
277: * @see edu.umd.cs.findbugs.ba.AnalysisContext#lookupClass(java.lang.String)
278: */
279: @Override
280: public JavaClass lookupClass(@DottedClassName
281: String className) throws ClassNotFoundException {
282: try {
283: if (className.length() == 0)
284: throw new IllegalArgumentException(
285: "Class name is empty");
286: if (!ClassName.isValidClassName(className)) {
287: throw new ClassNotFoundException("Invalid class name: "
288: + className);
289: }
290: return Global.getAnalysisCache().getClassAnalysis(
291: JavaClass.class,
292: DescriptorFactory.instance().getClassDescriptor(
293: ClassName.toSlashedClassName(className)));
294: } catch (CheckedAnalysisException e) {
295: throw new ClassNotFoundException("Class not found: "
296: + className, e);
297: }
298: }
299:
300: /* (non-Javadoc)
301: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getInnerClassAccessMap()
302: */
303: @Override
304: public InnerClassAccessMap getInnerClassAccessMap() {
305: return getDatabase(InnerClassAccessMap.class);
306: }
307:
308: /**
309: * Helper method to get a database
310: * without having to worry about a
311: * CheckedAnalysisException.
312: *
313: * @param cls Class of the database to get
314: * @return the database
315: */
316: private <E> E getDatabase(Class<E> cls) {
317: try {
318: return Global.getAnalysisCache().getDatabase(cls);
319: } catch (CheckedAnalysisException e) {
320: throw new IllegalStateException("Could not get database "
321: + cls.getName(), e);
322: }
323: }
324:
325: /**
326: * Set the collection of class descriptors identifying all
327: * application classes.
328: *
329: * @param appClassCollection List of ClassDescriptors identifying application classes
330: */
331: public void setAppClassList(List<ClassDescriptor> appClassCollection)
332: throws CheckedAnalysisException {
333:
334: // FIXME: we really should drive the progress callback here
335: HashSet<ClassDescriptor> appSet = new HashSet<ClassDescriptor>(
336: appClassCollection);
337:
338: Collection<ClassDescriptor> allClassDescriptors = new ArrayList<ClassDescriptor>(
339: DescriptorFactory.instance().getAllClassDescriptors());
340: for (ClassDescriptor appClass : allClassDescriptors) {
341: XClass xclass = currentXFactory().getXClass(appClass);
342:
343: if (xclass == null)
344: continue;
345:
346: // Add the application class to the database
347: if (appSet.contains(appClass))
348: getSubtypes2().addApplicationClass(xclass);
349: else if (xclass instanceof ClassInfo)
350: getSubtypes2().addClass(xclass);
351:
352: }
353:
354: if (Subtypes2.ENABLE_SUBTYPES2 && Subtypes2.DEBUG) {
355: System.out.println(subtypes2.getGraph().getNumVertices()
356: + " vertices in inheritance graph");
357: }
358: }
359:
360: /* (non-Javadoc)
361: * @see edu.umd.cs.findbugs.ba.AnalysisContext#updateDatabases(int)
362: */
363: @Override
364: public void updateDatabases(int pass) {
365: if (pass == 0) {
366: getCheckReturnAnnotationDatabase()
367: .loadAuxiliaryAnnotations();
368: getNullnessAnnotationDatabase().loadAuxiliaryAnnotations();
369: }
370:
371: }
372:
373: /* (non-Javadoc)
374: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getReturnValueNullnessPropertyDatabase()
375: */
376: @Override
377: public ReturnValueNullnessPropertyDatabase getReturnValueNullnessPropertyDatabase() {
378: return getDatabase(ReturnValueNullnessPropertyDatabase.class);
379:
380: }
381:
382: private Subtypes2 subtypes2;
383:
384: /* (non-Javadoc)
385: * @see edu.umd.cs.findbugs.ba.AnalysisContext#getSubtypes2()
386: */
387: @Override
388: public Subtypes2 getSubtypes2() {
389: if (subtypes2 == null) {
390: try {
391: subtypes2 = Global.getAnalysisCache().getDatabase(
392: Subtypes2.class);
393: } catch (CheckedAnalysisException e) {
394: IllegalStateException ise = new IllegalStateException(
395: "Should not happen");
396: ise.initCause(e);
397: throw ise;
398: }
399: }
400: return subtypes2;
401: }
402:
403: }
|