1 19 20 package edu.umd.cs.findbugs; 21 22 import java.util.Arrays ; 23 import java.util.Comparator ; 24 import java.util.HashSet ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 import java.util.Set ; 28 29 import edu.umd.cs.findbugs.ba.AnalysisContext; 30 import edu.umd.cs.findbugs.ba.ClassNotFoundExceptionParser; 31 import edu.umd.cs.findbugs.ba.JavaClassAndMethod; 32 import edu.umd.cs.findbugs.ba.MethodUnprofitableException; 33 import edu.umd.cs.findbugs.ba.MissingClassException; 34 import edu.umd.cs.findbugs.classfile.ClassDescriptor; 35 import edu.umd.cs.findbugs.classfile.MethodDescriptor; 36 37 41 public abstract class AbstractBugReporter implements BugReporter { 42 private static final boolean DEBUG_MISSING_CLASSES = SystemProperties.getBoolean("findbugs.debug.missingclasses"); 43 44 private static class Error { 45 private int sequence; 46 private String message; 47 private Throwable cause; 48 49 public Error(int sequence, String message) { 50 this(sequence, message, null); 51 } 52 53 public Error(int sequence, String message, Throwable cause) { 54 this.sequence = sequence; 55 this.message = message; 56 this.cause = cause; 57 } 58 59 public int getSequence() { 60 return sequence; 61 } 62 63 public String getMessage() { 64 return message; 65 } 66 67 public Throwable getCause() { 68 return cause; 69 } 70 71 @Override 72 public int hashCode() { 73 int hashCode = message.hashCode(); 74 if (cause != null) { 75 hashCode += 1009 * cause.hashCode(); 76 } 77 return hashCode; 78 } 79 80 @Override 82 public boolean equals(Object obj) { 83 if (obj == null || obj.getClass() != this.getClass()) 84 return false; 85 Error other = (Error ) obj; 86 if (!message.equals(other.message)) 87 return false; 88 if (this.cause == other.cause) 89 return true; 90 if (this.cause == null || other.cause == null) 91 return false; 92 return this.cause.equals(other.cause); 93 } 94 } 95 96 private int verbosityLevel = NORMAL; 97 private int priorityThreshold; 98 private boolean analysisUnderway, relaxed; 99 private HashSet <String > missingClassMessageSet = new HashSet <String >(); 100 private LinkedList <String > missingClassMessageList = new LinkedList <String >(); 101 private Set <Error > errorSet = new HashSet <Error >(); 102 private List <BugReporterObserver> observerList = new LinkedList <BugReporterObserver>(); 103 private ProjectStats projectStats = new ProjectStats(); 104 private int errorCount; 105 106 public void setErrorVerbosity(int level) { 107 this.verbosityLevel = level; 108 } 109 110 public void setPriorityThreshold(int threshold) { 111 this.priorityThreshold = threshold; 112 } 113 114 public final void reportBug(BugInstance bugInstance) { 116 if (!analysisUnderway) { 117 if (FindBugsAnalysisFeatures.isRelaxedMode()) { 118 relaxed = true; 119 } 120 121 analysisUnderway = true; 122 } 123 ClassAnnotation primaryClass = bugInstance.getPrimaryClass(); 124 if (primaryClass != null && !AnalysisContext.currentAnalysisContext().isApplicationClass(primaryClass.getClassName())) 125 return; 126 if (bugInstance.getPriority() <= priorityThreshold || relaxed) 127 doReportBug(bugInstance); 128 } 129 130 public static String getMissingClassName(ClassNotFoundException ex) { 131 String message = ex.getMessage(); 132 133 String className = ClassNotFoundExceptionParser.getMissingClassName(ex); 135 if (className != null) { 136 if (className.indexOf('/') >= 0) { 137 className = className.replace('/','.'); 138 } 139 return className; 140 141 } 142 143 return message; 146 } 147 148 public void reportMissingClass(ClassNotFoundException ex) { 149 if (DEBUG_MISSING_CLASSES) { 150 System.out.println("Missing class: " + ex.toString()); 151 ex.printStackTrace(System.out); 152 } 153 154 if (verbosityLevel == SILENT) 155 return; 156 157 String message = getMissingClassName(ex); 158 159 if (message.startsWith("[")) { 160 return; 167 } 168 169 logMissingClass(message); 170 } 171 172 175 public void reportMissingClass(ClassDescriptor classDescriptor) { 176 if (DEBUG_MISSING_CLASSES) { 177 System.out.println("Missing class: " + classDescriptor); 178 } 179 180 if (verbosityLevel == SILENT) 181 return; 182 183 logMissingClass(classDescriptor.toDottedClassName()); 184 } 185 186 189 private void logMissingClass(String message) { 190 if (!missingClassMessageSet.contains(message)) { 191 missingClassMessageSet.add(message); 192 missingClassMessageList.add(message); 193 } 194 } 195 196 200 public void reportSkippedAnalysis(MethodDescriptor method) { 201 } 203 public void logError(String message) { 204 if (verbosityLevel == SILENT) 205 return; 206 207 Error error = new Error (errorCount++, message); 208 if (!errorSet.contains(error)) 209 errorSet.add(error); 210 } 211 212 public void logError(String message, Throwable e) { 213 214 if (e instanceof MethodUnprofitableException) { 215 return; 217 } 218 if (e instanceof MissingClassException) { 219 MissingClassException missingClassEx = (MissingClassException) e; 221 ClassNotFoundException cnfe = missingClassEx.getClassNotFoundException(); 222 223 reportMissingClass(cnfe); 224 return; 227 } 228 229 if (verbosityLevel == SILENT) 230 return; 231 232 Error error = new Error (errorCount++, message, e); 233 if (!errorSet.contains(error)) 234 errorSet.add(error); 235 } 236 237 public void reportQueuedErrors() { 238 Error [] errorList = errorSet.toArray(new Error [errorSet.size()]); 240 Arrays.sort(errorList, new Comparator <Error >() { 241 public int compare(Error o1, Error o2) { 242 return o1.getSequence() - o2.getSequence(); 243 } 244 }); 245 for (Error error : errorList) { 246 reportAnalysisError(new AnalysisError(error.getMessage(), error.getCause())); 247 } 248 249 for (String aMissingClassMessageList : missingClassMessageList) { 250 reportMissingClass(aMissingClassMessageList); 251 } 252 } 253 254 public void addObserver(BugReporterObserver observer) { 255 observerList.add(observer); 256 } 257 258 public ProjectStats getProjectStats() { 259 return projectStats; 260 } 261 262 267 protected void notifyObservers(BugInstance bugInstance) { 268 for (BugReporterObserver aObserverList : observerList) 269 aObserverList.reportBug(bugInstance); 270 } 271 272 278 protected abstract void doReportBug(BugInstance bugInstance); 279 280 285 public abstract void reportAnalysisError(AnalysisError error); 286 287 292 public abstract void reportMissingClass(String string); 293 } 294 295 | Popular Tags |