Droid Post

10:39 PM 0 Comments

At Google I/O this year, they gave away Droids as free gifts to attendees. SO, I am now using AndraBlogger, an app that I downloaded from the Droid App Store, to make stpst from a mobile device.

So, you would have seen here an extra four paragraphs, but the app crashed. :) Fortunately, it salvaged the first paragraph. I'm tired now, though. I'll recreate the rest later.

0 comments:

Testing Custom FindBugs Detectors in Eclipse

12:15 PM 3 Comments

We are starting to use Sonar where I work, and I've been tasked with finding out how to write custom FindBugs rules.


First of all, that was pretty fun getting down into the byte code, it made me feel like a Java super-villain. Daniel Schneller has a very helpful post on creating your own FindBugs rule. With his help, you too can feel like a Java super-villain.


Anyway, the first thing that I noticed is that there wasn't really an easy way to debug through my detector. =[ Or, at least, I wasn't able to find one.


For my first stab, I decided to try creating a method that would take my detector class and a test class file to run the detector against.



public ProjectStats analyze(Class clazz, Detector detector)

Of course, I failed to remember that FindBugs analyzes class files, and so I would need to provide the location of the target directory. You need to do this with the maven plugin, so I'm not too worried about it:



public ProjectStats analyze(String filePath, Detector detector)

Finally, the bug reporting strategy is passed around as a parameter in most places, so I had to include the BugPattern and BugReporter in my signature:



public ProjectStats analyze(String filePath, Detector detector,
BugPattern bugPattern, BugReporter bugReporter)

Inside, it's a total mess of configuration. Hopefully, there is a way to clean it up:



public ProjectStats analyze(String filePath, Detector detector,
BugPattern bugPattern, BugReporter bugReporter)
throws CheckedAnalysisException, IOException, InterruptedException {
// internal to FindBugs, the code uses the Detector2 interface
Detector2 det = new DetectorToDetector2Adapter(detector);

// register the rules message
I18N.instance().registerBugPattern(bugPattern);

// a great deal of code to say
// 'analyze the files in this directory'
IClassFactory classFactory = ClassFactory.instance();
IClassPath classPath = classFactory.createClassPath();
IAnalysisCache analysisCache = classFactory
.createAnalysisCache(classPath, bugReporter);
Global.setAnalysisCacheForCurrentThread(analysisCache);
FindBugs2.registerBuiltInAnalysisEngines(analysisCache);
IClassPathBuilder builder = classFactory
.createClassPathBuilder(bugReporter);
ICodeBaseLocator locator = classFactory
.createFilesystemCodeBaseLocator(filePath);
builder.addCodeBase(locator, true);
builder.build(classPath, new NoOpFindBugsProgress());
List classesToAnalyze = builder.getAppClassList();
AnalysisCacheToAnalysisContextAdapter analysisContext =
new AnalysisCacheToAnalysisContextAdapter();
AnalysisContext.setCurrentAnalysisContext(analysisContext);

// finally, perform the analysis
for ( ClassDescriptor d : classesToAnalyse) {
det.visitClass(d);
}

// return the results
return bugReporter.getProjectStats();
}

Since I'm not particularly worried about the reporting, I just created a simple PrintStream bug reporter:



private static class PrintStreamBugReporter implements BugReporter {
private ProjectStats stats = new ProjectStats();
private PrintStream os;
private List observers =
new ArrayList();

public PrintStreamBugReporter(PrintStream os) {
this.os = os;
}

@Override
public void addObserver(BugReporterObserver arg0) {
observers.add(arg0);
}

@Override
public void finish() {
// TODO Auto-generated method stub

}

@Override
public ProjectStats getProjectStats() {
return stats;
}

@Override
public BugReporter getRealBugReporter() {
return this;
}

@Override
public void reportBug(BugInstance arg0) {
stats.addBug(arg0);
for ( BugReporterObserver observer : observers ) {
observer.reportBug(arg0);
}
os.println(arg0.getAbridgedMessage());
}

@Override
public void reportQueuedErrors() {
}

@Override
public void setErrorVerbosity(int arg0) {
}

@Override
public void setPriorityThreshold(int arg0) {
}

@Override
public void logError(String arg0) {
os.println(arg0.getBytes());
}

@Override
public void logError(String arg0, Throwable arg1) {
os.println(arg0.getBytes());
arg1.printStackTrace(os);
}

@Override
public void reportMissingClass(ClassNotFoundException arg0) {
arg0.printStackTrace(os);
}

@Override
public void reportMissingClass(ClassDescriptor arg0) {
os.println("Class not found: " + arg0);
}

@Override
public void reportSkippedAnalysis(MethodDescriptor arg0) {
os.println("Skipped Method: " + arg0);
}

@Override
public void observeClass(ClassDescriptor arg0) {
}


}

There you go. Now, I can debug my detectors in my IDE.

3 comments: