Display LocalVariables along with Locations in the html report.
authorChris Jaekl <cejaekl@yahoo.com>
Sat, 16 Jan 2016 13:25:00 +0000 (22:25 +0900)
committerChris Jaekl <cejaekl@yahoo.com>
Sat, 16 Jan 2016 13:25:00 +0000 (22:25 +0900)
prod/net/jaekl/cfb/analyze/HtmlReport.java
prod/net/jaekl/cfb/util/XmlEscape.java [new file with mode: 0644]
test/net/jaekl/cfb/analyze/BugReportData.java [new file with mode: 0644]
test/net/jaekl/cfb/analyze/DeltaTest.java
test/net/jaekl/cfb/analyze/HtmlReportTest.java [new file with mode: 0644]
test/net/jaekl/cfb/analyze/MessageMapTest.java [new file with mode: 0644]
test/net/jaekl/cfb/util/XmlEscapeTest.java [new file with mode: 0644]
test/net/jaekl/cfb/xml/messages/MessagesData.java [new file with mode: 0644]

index 166a140886ee824d3c429ac467077867c0f069c7..7ff69629e5d2994c45718378f1ea8ffee648cebf 100644 (file)
@@ -7,11 +7,15 @@ import java.io.PrintWriter;
 import net.jaekl.cfb.CfbBundle;
 import net.jaekl.cfb.store.Location;
 import net.jaekl.cfb.util.Command;
+import net.jaekl.cfb.util.XmlEscape;
 import net.jaekl.cfb.xml.BugInstance;
+import net.jaekl.cfb.xml.LocalVariable;
 import net.jaekl.cfb.xml.messages.BugPattern;
 import net.jaekl.cfb.xml.messages.MessageCollection;
 
 public class HtmlReport {
+       private static final String NBSP = "&#160;";    // "&nbsp;" isn't valid XML, but "&#160;" is.
+       
        CfbBundle m_bundle;
        Delta m_delta;
        MessageCollection m_msgColl;
@@ -86,7 +90,9 @@ public class HtmlReport {
                                }
                        }
                        
-                       pw.println("        <TR><TD COLSPAN=\"2\" CLASS=\"Loc\">" + sb.toString() + "</TD></TR>");                                      
+                       String displayText = XmlEscape.toEscaped(sb.toString());
+                       
+                       pw.println("        <TR><TD COLSPAN=\"2\" CLASS=\"Loc\">" + displayText + "</TD></TR>");                                        
                }
        }
        
@@ -108,6 +114,7 @@ public class HtmlReport {
                        pw.println("          <TD>" + bug.getType() + "</TD>");
                        pw.println("        </TR>");
                        writeBugLocations(pw, bug);
+                       writeBugVariables(pw, bug);
                        pw.println("        <TR><TD COLSPAN=\"2\"><B>" + pattern.getShort() + "</B></TD></TR>");
                        pw.println("        <TR>");
                        pw.println("          <TD COLSPAN=\"2\">" + pattern.getDetails() + "</TD>");
@@ -118,6 +125,24 @@ public class HtmlReport {
                }
        }
        
+       void writeBugVariables(PrintWriter pw, BugInstance bug)
+       {
+               for (LocalVariable var : bug.getVariables()) {
+                       StringBuffer sb = new StringBuffer();
+                       
+                       if (null != var) {
+                               String name = var.getName();
+                               String role = var.getRole();
+                               sb.append(name);
+                               if (null != role) {
+                                       sb.append(" (").append(role).append(")");
+                               }
+                       }
+                       
+                       pw.println("        <TR><TD COLSPAN=\"2\" CLASS=\"Var\">" + sb.toString() + "</TD></TR>");                                      
+               }
+       }
+       
        void writeHeader(PrintWriter pw)
        {
                String title = trans(CfbBundle.CFB_REPORT);
@@ -139,7 +164,7 @@ public class HtmlReport {
        
        void writeSummary(PrintWriter pw)
        {
-               final String SEP = ":&nbsp;&nbsp;";
+               final String SEP = ":" + NBSP + NBSP;
                
                String earlierVersion = "";
                if (null != m_delta.getEarlier()) {
@@ -157,7 +182,7 @@ public class HtmlReport {
                pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.OLD_VERSION) + SEP + "</TD>");
                pw.println("          <TD CLASS=\"CategoryValue\">" + earlierVersion + "</TD>");
                pw.println("        </TR>");
-               pw.println("        <TR><TD>&nbsp;</TD></TR>");
+               pw.println("        <TR><TD>" + NBSP + "</TD></TR>");
                pw.println("        <TR>");
                pw.println("          <TD CLASS=\"CategoryName\">" + trans(CfbBundle.NEW_BUGS) + SEP + "</TD>");
                pw.println("          <TD CLASS=\"CategoryValue\">" + trans(CfbBundle.NUM_BUGS, m_delta.getNumNew()) + "</TD>");
@@ -182,6 +207,7 @@ public class HtmlReport {
            pw.println("    .CategoryValue { text-align: left; }");
                pw.println("    .Loc           { font-family: monospace; }");
            pw.println("    .SectionHead   td { background-color: #0000FF; color: #FFFFFF; font-size: 1.25em; font-weight: bold; }");
+               pw.println("    .Var           { font-family: monospace; }");
                pw.println("    </STYLE>");
        }
 }
diff --git a/prod/net/jaekl/cfb/util/XmlEscape.java b/prod/net/jaekl/cfb/util/XmlEscape.java
new file mode 100644 (file)
index 0000000..9e177bb
--- /dev/null
@@ -0,0 +1,39 @@
+package net.jaekl.cfb.util;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class XmlEscape {
+       // The following code adapted from:
+       // http://stackoverflow.com/questions/439298/best-way-to-encode-text-data-for-xml-in-java#439311
+       private final static String ESCAPE_CHARS = "<>&\"\'";
+       private final static List<String> ESCAPE_STRINGS = 
+                       Collections.unmodifiableList(Arrays.asList(new String[] {"&lt;", "&gt;", "&amp;", "&quot;", "&apos;" }));
+       
+       //should only use for the content of an attribute or tag      
+       public static String toEscaped(String content) {
+               String result = content;
+               
+               if ((content != null) && (content.length() > 0)) {
+                       boolean modified = false;
+                       StringBuilder stringBuilder = new StringBuilder(content.length());
+                       for (int i = 0, count = content.length(); i < count; ++i) {
+                               String character = content.substring(i, i + 1);
+                               int pos = ESCAPE_CHARS.indexOf(character);
+                               if (pos > -1) {
+                                       stringBuilder.append(ESCAPE_STRINGS.get(pos));
+                                       modified = true;
+                               }
+                               else {
+                                   stringBuilder.append(character);
+                               }
+                       }
+                       if (modified) {
+                           result = stringBuilder.toString();
+                       }
+               }
+               
+               return result;
+       }
+}
diff --git a/test/net/jaekl/cfb/analyze/BugReportData.java b/test/net/jaekl/cfb/analyze/BugReportData.java
new file mode 100644 (file)
index 0000000..7a6d222
--- /dev/null
@@ -0,0 +1,100 @@
+package net.jaekl.cfb.analyze;
+
+public class BugReportData {
+       private static final String DM_DEFAULT_ENCODING = ""
+                       + "<BugInstance type=\"DM_DEFAULT_ENCODING\" priority=\"1\" rank=\"19\" abbrev=\"Dm\" category=\"I18N\">\n"
+                       + "<Class classname=\"net.jaekl.cfb.CFB\">\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"32\" end=\"119\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
+                       + "</Class>\n"
+                       + "<Method classname=\"net.jaekl.cfb.CFB\" name=\"main\" signature=\"([Ljava/lang/String;)V\" isStatic=\"true\">\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"112\" end=\"119\" startBytecode=\"0\" endBytecode=\"266\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
+                       + "</Method>\n"
+                       + "<Method classname=\"java.io.PrintWriter\" name=\"&lt;init&gt;\" signature=\"(Ljava/io/OutputStream;)V\" isStatic=\"false\" role=\"METHOD_CALLED\">\n"
+                       + "<SourceLine classname=\"java.io.PrintWriter\" start=\"131\" end=\"132\" startBytecode=\"0\" endBytecode=\"62\" sourcefile=\"PrintWriter.java\" sourcepath=\"java/io/PrintWriter.java\"/>\n"
+                       + "</Method>\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"114\" end=\"114\" startBytecode=\"22\" endBytecode=\"22\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
+                       + "</BugInstance>\n";
+       
+       private static final String RCN_REDUNDANT_NULL_CHECK = ""
+                       + "<BugInstance type=\"RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE\" priority=\"2\" rank=\"18\" abbrev=\"RCN\" category=\"STYLE\">\n"
+                       + "<Class classname=\"net.jaekl.cfb.CFB\">\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"32\" end=\"119\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
+                       + "</Class>\n"
+                       + "<Method classname=\"net.jaekl.cfb.CFB\" name=\"doMain\" signature=\"(Ljava/io/PrintWriter;[Ljava/lang/String;)V\" isStatic=\"false\">\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"96\" end=\"109\" startBytecode=\"0\" endBytecode=\"407\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
+                       + "</Method>\n"
+                       + "<LocalVariable name=\"con\" register=\"5\" pc=\"44\" role=\"LOCAL_VARIABLE_VALUE_OF\"/>\n"
+                       + "<Method classname=\"net.jaekl.cfb.db.driver.DbDriver\" name=\"connect\" signature=\"(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/Connection;\" isStatic=\"false\" role=\"METHOD_RETURN_VALUE_OF\">\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.db.driver.DbDriver\" sourcefile=\"DbDriver.java\" sourcepath=\"net/jaekl/cfb/db/driver/DbDriver.java\"/>\n"
+                       + "</Method>\n"
+                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"101\" end=\"101\" startBytecode=\"46\" endBytecode=\"46\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\" role=\"SOURCE_REDUNDANT_NULL_CHECK\"/>\n"
+                       + "</BugInstance>\n";
+
+       private static String VO_VOLATILE_INCREMENT = ""
+                       + "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"MT_CORRECTNESS\">"
+                       + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
+                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+                       + "</Class>"
+                       + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
+                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+                       + "</Method>"
+                       + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
+                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+                       + "</Field>"
+                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
+                       + "</BugInstance>";
+       
+       private static final String DM_NUMBER_CTOR_156 = ""
+                       + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
+                       + "<Class classname=\"junit.framework.Assert\">"
+                       + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+                       + "</Class>"
+                       + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;BB)V\" isStatic=\"true\">"
+                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"157\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+                       + "</Method>"
+                       + "<Method classname=\"java.lang.Byte\" name=\"&lt;init&gt;\" signature=\"(B)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
+                       + "<SourceLine classname=\"java.lang.Byte\" start=\"307\" end=\"309\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
+                       + "</Method>"
+                       + "<Method classname=\"java.lang.Byte\" name=\"valueOf\" signature=\"(B)Ljava/lang/Byte;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
+                       + "<SourceLine classname=\"java.lang.Byte\" start=\"87\" end=\"87\" startBytecode=\"0\" endBytecode=\"33\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
+                       + "</Method>"
+                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"156\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+                       + "</BugInstance>";
+
+       private static final String DM_NUMBER_CTOR_169 = ""
+                       + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
+                       + "<Class classname=\"junit.framework.Assert\">"
+                       + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+                       + "</Class>"
+                       + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;CC)V\" isStatic=\"true\">"
+                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"170\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+                       + "</Method>"
+                       + "<Method classname=\"java.lang.Character\" name=\"&lt;init&gt;\" signature=\"(C)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
+                       + "<SourceLine classname=\"java.lang.Character\" start=\"2056\" end=\"2058\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
+                       + "</Method>"
+                       + "<Method classname=\"java.lang.Character\" name=\"valueOf\" signature=\"(C)Ljava/lang/Character;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
+                       + "<SourceLine classname=\"java.lang.Character\" start=\"2085\" end=\"2088\" startBytecode=\"0\" endBytecode=\"52\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
+                       + "</Method>"
+                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"169\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
+                       + "</BugInstance>";
+
+       private static final String PROLOGUE = ""
+                       + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+                       + "<BugCollection version=\"3.0.1\" sequence=\"0\" timestamp=\"1440757060000\" analysisTimestamp=\"1440761315847\" release=\"\">\n"
+                       + "<Project projectName=\"CFB\">\n"
+                       + "<Jar>/home/chris/prog/././cfb/bin</Jar>\n"
+                       + "<SrcDir>/home/chris/prog/././cfb/src</SrcDir>\n"
+                       + "</Project>\n";
+       
+       private static final String EPILOGUE = ""
+                       + "</BugCollection>\n";
+
+       public static String getDmDefaultEncoding() { return DM_DEFAULT_ENCODING; }
+       public static String getRcnRedundantNullCheck() { return RCN_REDUNDANT_NULL_CHECK; }
+       public static String getVoVolatileIncrement() { return VO_VOLATILE_INCREMENT; }
+       public static String getDmNumberCtor156() { return DM_NUMBER_CTOR_156; }
+       public static String getDmNumberCtor169() { return DM_NUMBER_CTOR_169; }
+       
+       public static String getPrologue() { return PROLOGUE; }
+       public static String getEpilogue() { return EPILOGUE; }
+}
index cb2222c77f35d31152852aaa0d3fb093b8cbdfd4..bc974eebddc69ac7cee7bdb462d2c580c6f1df5a 100644 (file)
@@ -15,94 +15,6 @@ import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
 public class DeltaTest {
-       private static final String DM_DEFAULT_ENCODING = ""
-                       + "<BugInstance type=\"DM_DEFAULT_ENCODING\" priority=\"1\" rank=\"19\" abbrev=\"Dm\" category=\"I18N\">\n"
-                       + "<Class classname=\"net.jaekl.cfb.CFB\">\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"32\" end=\"119\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
-                       + "</Class>\n"
-                       + "<Method classname=\"net.jaekl.cfb.CFB\" name=\"main\" signature=\"([Ljava/lang/String;)V\" isStatic=\"true\">\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"112\" end=\"119\" startBytecode=\"0\" endBytecode=\"266\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
-                       + "</Method>\n"
-                       + "<Method classname=\"java.io.PrintWriter\" name=\"&lt;init&gt;\" signature=\"(Ljava/io/OutputStream;)V\" isStatic=\"false\" role=\"METHOD_CALLED\">\n"
-                       + "<SourceLine classname=\"java.io.PrintWriter\" start=\"131\" end=\"132\" startBytecode=\"0\" endBytecode=\"62\" sourcefile=\"PrintWriter.java\" sourcepath=\"java/io/PrintWriter.java\"/>\n"
-                       + "</Method>\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"114\" end=\"114\" startBytecode=\"22\" endBytecode=\"22\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
-                       + "</BugInstance>\n";
-       
-       private static final String RCN_REDUNDANT_NULL_CHECK = ""
-                       + "<BugInstance type=\"RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE\" priority=\"2\" rank=\"18\" abbrev=\"RCN\" category=\"STYLE\">\n"
-                       + "<Class classname=\"net.jaekl.cfb.CFB\">\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"32\" end=\"119\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
-                       + "</Class>\n"
-                       + "<Method classname=\"net.jaekl.cfb.CFB\" name=\"doMain\" signature=\"(Ljava/io/PrintWriter;[Ljava/lang/String;)V\" isStatic=\"false\">\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"96\" end=\"109\" startBytecode=\"0\" endBytecode=\"407\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\"/>\n"
-                       + "</Method>\n"
-                       + "<LocalVariable name=\"con\" register=\"5\" pc=\"44\" role=\"LOCAL_VARIABLE_VALUE_OF\"/>\n"
-                       + "<Method classname=\"net.jaekl.cfb.db.driver.DbDriver\" name=\"connect\" signature=\"(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/Connection;\" isStatic=\"false\" role=\"METHOD_RETURN_VALUE_OF\">\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.db.driver.DbDriver\" sourcefile=\"DbDriver.java\" sourcepath=\"net/jaekl/cfb/db/driver/DbDriver.java\"/>\n"
-                       + "</Method>\n"
-                       + "<SourceLine classname=\"net.jaekl.cfb.CFB\" start=\"101\" end=\"101\" startBytecode=\"46\" endBytecode=\"46\" sourcefile=\"CFB.java\" sourcepath=\"net/jaekl/cfb/CFB.java\" role=\"SOURCE_REDUNDANT_NULL_CHECK\"/>\n"
-                       + "</BugInstance>\n";
-
-       private static String VO_VOLATILE_INCREMENT = ""
-                       + "<BugInstance type=\"VO_VOLATILE_INCREMENT\" priority=\"2\" abbrev=\"VO\" category=\"MT_CORRECTNESS\">"
-                       + "<Class classname=\"junit.extensions.ActiveTestSuite\">"
-                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
-                       + "</Class>"
-                       + "<Method classname=\"junit.extensions.ActiveTestSuite\" name=\"runFinished\" signature=\"()V\" isStatic=\"false\">"
-                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"69\" startBytecode=\"0\" endBytecode=\"64\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
-                       + "</Method>"
-                       + "<Field classname=\"junit.extensions.ActiveTestSuite\" name=\"fActiveTestDeathCount\" signature=\"I\" isStatic=\"false\">"
-                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
-                       + "</Field>"
-                       + "<SourceLine classname=\"junit.extensions.ActiveTestSuite\" start=\"67\" end=\"67\" startBytecode=\"7\" endBytecode=\"7\" sourcefile=\"ActiveTestSuite.java\" sourcepath=\"junit/extensions/ActiveTestSuite.java\"/>"
-                       + "</BugInstance>";
-       
-       private static final String DM_NUMBER_CTOR_156 = ""
-                       + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
-                       + "<Class classname=\"junit.framework.Assert\">"
-                       + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
-                       + "</Class>"
-                       + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;BB)V\" isStatic=\"true\">"
-                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"157\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
-                       + "</Method>"
-                       + "<Method classname=\"java.lang.Byte\" name=\"&lt;init&gt;\" signature=\"(B)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
-                       + "<SourceLine classname=\"java.lang.Byte\" start=\"307\" end=\"309\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
-                       + "</Method>"
-                       + "<Method classname=\"java.lang.Byte\" name=\"valueOf\" signature=\"(B)Ljava/lang/Byte;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
-                       + "<SourceLine classname=\"java.lang.Byte\" start=\"87\" end=\"87\" startBytecode=\"0\" endBytecode=\"33\" sourcefile=\"Byte.java\" sourcepath=\"java/lang/Byte.java\"/>"
-                       + "</Method>"
-                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"156\" end=\"156\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
-                       + "</BugInstance>";
-
-       private static final String DM_NUMBER_CTOR_169 = ""
-                       + "<BugInstance type=\"DM_NUMBER_CTOR\" priority=\"2\" abbrev=\"Bx\" category=\"PERFORMANCE\">"
-                       + "<Class classname=\"junit.framework.Assert\">"
-                       + "<SourceLine classname=\"junit.framework.Assert\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
-                       + "</Class>"
-                       + "<Method classname=\"junit.framework.Assert\" name=\"assertEquals\" signature=\"(Ljava/lang/String;CC)V\" isStatic=\"true\">"
-                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"170\" startBytecode=\"0\" endBytecode=\"86\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
-                       + "</Method>"
-                       + "<Method classname=\"java.lang.Character\" name=\"&lt;init&gt;\" signature=\"(C)V\" isStatic=\"false\" role=\"METHOD_CALLED\">"
-                       + "<SourceLine classname=\"java.lang.Character\" start=\"2056\" end=\"2058\" startBytecode=\"0\" endBytecode=\"41\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
-                       + "</Method>"
-                       + "<Method classname=\"java.lang.Character\" name=\"valueOf\" signature=\"(C)Ljava/lang/Character;\" isStatic=\"true\" role=\"SHOULD_CALL\">"
-                       + "<SourceLine classname=\"java.lang.Character\" start=\"2085\" end=\"2088\" startBytecode=\"0\" endBytecode=\"52\" sourcefile=\"Character.java\" sourcepath=\"java/lang/Character.java\"/>"
-                       + "</Method>"
-                       + "<SourceLine classname=\"junit.framework.Assert\" start=\"169\" end=\"169\" startBytecode=\"6\" endBytecode=\"6\" sourcefile=\"Assert.java\" sourcepath=\"junit/framework/Assert.java\"/>"
-                       + "</BugInstance>";
-
-       private static final String PROLOGUE = ""
-                       + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
-                       + "<BugCollection version=\"3.0.1\" sequence=\"0\" timestamp=\"1440757060000\" analysisTimestamp=\"1440761315847\" release=\"\">\n"
-                       + "<Project projectName=\"CFB\">\n"
-                       + "<Jar>/home/chris/prog/././cfb/bin</Jar>\n"
-                       + "<SrcDir>/home/chris/prog/././cfb/src</SrcDir>\n"
-                       + "</Project>\n";
-       
-       private static final String EPILOGUE = ""
-                       + "</BugCollection>\n";
-
        private Analysis analysisFromXml(String xml, String projectName, String version) 
                throws FileNotFoundException, IOException, SAXException 
        {
@@ -126,11 +38,11 @@ public class DeltaTest {
        
        private String buildXml(String[][] bugSpecs, int from, int to)
        {
-               StringBuilder sb = new StringBuilder(PROLOGUE);
+               StringBuilder sb = new StringBuilder(BugReportData.getPrologue());
                for (int i = from; i <= to; ++i) {
                        sb.append(bugSpecs[i][0]);
                }
-               sb.append(EPILOGUE);
+               sb.append(BugReportData.getEpilogue());
                
                return sb.toString();           
        }
@@ -190,10 +102,9 @@ public class DeltaTest {
        public void test_computeDeltas() throws FileNotFoundException, IOException, SAXException 
        {
                String[][] bugSpecs = {
-                               { DM_DEFAULT_ENCODING, "DM_DEFAULT_ENCODING" },
-                               { RCN_REDUNDANT_NULL_CHECK, "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" },
-                               { DM_NUMBER_CTOR_156, "DM_NUMBER_CTOR" },
-                               { DM_NUMBER_CTOR_169, "DM_NUMBER_CTOR" }
+                               { BugReportData.getDmDefaultEncoding(), "DM_DEFAULT_ENCODING" },
+                               { BugReportData.getRcnRedundantNullCheck(), "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" },
+                               { BugReportData.getDmNumberCtor169(), "DM_NUMBER_CTOR" }
                };
 
                for (int w = 0; w < bugSpecs.length; ++w) {
@@ -211,11 +122,11 @@ public class DeltaTest {
        public void test_deltaWithNoPrior() throws FileNotFoundException, IOException, SAXException 
        {
                String[][] bugSpecs = {
-                               { DM_DEFAULT_ENCODING, "DM_DEFAULT_ENCODING" },
-                               { RCN_REDUNDANT_NULL_CHECK, "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" },
-                               { VO_VOLATILE_INCREMENT, "VO_VOLATILE_INCREMENT" },
-                               { DM_NUMBER_CTOR_156, "DM_NUMBER_CTOR" },
-                               { DM_NUMBER_CTOR_169, "DM_NUMBER_CTOR" }
+                               { BugReportData.getDmDefaultEncoding(), "DM_DEFAULT_ENCODING" },
+                               { BugReportData.getRcnRedundantNullCheck(), "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE" },
+                               { BugReportData.getVoVolatileIncrement(), "VO_VOLATILE_INCREMENT" },
+                               { BugReportData.getDmNumberCtor156(), "DM_NUMBER_CTOR" },
+                               { BugReportData.getDmNumberCtor169(), "DM_NUMBER_CTOR" }
                };
                
                final String PROJECT_NAME = "AlphaOne";
diff --git a/test/net/jaekl/cfb/analyze/HtmlReportTest.java b/test/net/jaekl/cfb/analyze/HtmlReportTest.java
new file mode 100644 (file)
index 0000000..26f9f8e
--- /dev/null
@@ -0,0 +1,199 @@
+package net.jaekl.cfb.analyze;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import net.jaekl.cfb.CfbBundle;
+import net.jaekl.cfb.CfbBundleMock;
+import net.jaekl.cfb.util.Command;
+import net.jaekl.cfb.xml.messages.MessageCollection;
+import net.jaekl.cfb.xml.messages.MessagesData;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class HtmlReportTest {
+       private static class CheckWellFormedHandler extends DefaultHandler 
+       {
+               @Override
+               public void warning(SAXParseException spe) throws SAXException 
+               {
+                       throw new SAXException(spe);
+               }
+               
+               @Override
+               public void error(SAXParseException spe) throws SAXException 
+               {
+                       throw new SAXException(spe);
+               }
+               
+               @Override 
+               public void fatalError(SAXParseException spe) throws SAXException
+               {
+                       throw new SAXException(spe);
+               }
+       }
+       
+       String[] BUG_XMLS = { 
+               BugReportData.getDmDefaultEncoding(),
+               BugReportData.getDmNumberCtor156(),
+               BugReportData.getRcnRedundantNullCheck(),
+               BugReportData.getVoVolatileIncrement()
+       };
+
+       private static final String PROJECT_NAME = "Project Name";
+       private static final String FIRST_VERSION = "1.0.1.3145";
+       private static final String SECOND_VERSION = "1.0.1.3146";
+
+       private CfbBundleMock m_bundle;
+       private MessageMapMock m_msgMap;
+       
+       private Analysis analysisFromXml(String xml, String projectName, String version) 
+                       throws FileNotFoundException, IOException, SAXException 
+       {
+               Analysis analysis = new Analysis(projectName, version);
+               ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes(Command.UTF_8));
+               InputSource inputSource = new InputSource(bais); 
+               analysis.parse(inputSource);
+               
+               return analysis;
+       }
+       
+       private void assertContainsTagExactlyOnce(String html, String tag)
+       {
+               int pos = html.indexOf("<" + tag + ">");
+               assertTrue(pos >= 0);
+               String substr = html.substring(pos + 1);
+               assertFalse(substr.contains("<" + tag + ">"));
+               assertTrue(substr.contains("</" + tag + ">"));
+       }
+       
+       private void checkForWellFormedXml(String xml) throws IOException, ParserConfigurationException, SAXException
+       {
+               SAXParserFactory spf = SAXParserFactory.newInstance();
+               spf.setValidating(false);
+               SAXParser parser = spf.newSAXParser();
+               
+               try ( ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes(Command.UTF_8)) )
+               {
+                       InputSource source = new InputSource(bais);
+                       CheckWellFormedHandler handler = new CheckWellFormedHandler();
+                       
+                       parser.parse(source, handler);
+               }
+       }
+       
+       private String createReport(String firstXml, String secondXml) throws IOException, SAXException
+       {
+               Analysis first = null;
+               if (null != firstXml) {
+                       first = analysisFromXml(firstXml, PROJECT_NAME, FIRST_VERSION);
+               }
+               
+               Analysis second = analysisFromXml(secondXml, PROJECT_NAME, SECOND_VERSION);
+               Delta delta = new Delta(first, second);
+               MessageCollection msgColl = m_msgMap.getColl();
+               assertNotNull(msgColl);
+               
+               HtmlReport htmlReport = new HtmlReport(m_bundle, msgColl, delta);
+
+               try (
+                               StringWriter sw = new StringWriter();
+                               PrintWriter pw = new PrintWriter(sw);
+                       )
+               {
+                       htmlReport.write(pw);
+                       pw.close();
+                       sw.close();
+                       return sw.toString();
+               }               
+       }
+
+       private void doTestDelta(String firstXml, String secondXml) throws FileNotFoundException, IOException, SAXException, ParserConfigurationException 
+       {
+               String html = createReport(firstXml, secondXml);
+               validateReport(html);
+       }
+       
+       private void validateReport(String html) throws IOException, ParserConfigurationException, SAXException 
+       {
+               assertNotNull(html);
+               
+               // Report should be well-formed XHTML
+               checkForWellFormedXml(html);
+               
+               // Certain tags should be present exactly once
+               for (String tag : new String[]{"HTML", "HEAD", "BODY", "STYLE"}) 
+               {
+                       assertContainsTagExactlyOnce(html, tag);
+               }
+               
+               // Title should be the result of translating CFB_REPORT
+               String title = m_bundle.get(CfbBundle.CFB_REPORT);
+               assertTrue(html.contains("<TITLE>" + title + "</TITLE>"));
+                               
+               // The character set UTF-8 should be specified
+               assertTrue(html.contains("<META CHARSET=\"UTF-8\"/>"));         
+       }
+       
+       @Before
+       public void setUp() throws FileNotFoundException, IOException, SAXException 
+       {
+               m_bundle = new CfbBundleMock();
+               m_msgMap = new MessageMapMock();
+               
+               try (ByteArrayInputStream bais = new ByteArrayInputStream(MessagesData.getData().getBytes(Command.UTF_8))) {
+                       m_msgMap.parse(new InputSource(bais));
+               }
+       }
+
+       @Test
+       public void testVariousDeltas() throws FileNotFoundException, IOException, SAXException, ParserConfigurationException 
+       {
+               StringBuilder sbFirst = new StringBuilder(BugReportData.getPrologue());
+               StringBuilder sbSecond = new StringBuilder(BugReportData.getPrologue());
+               for (int i = 0; i < BUG_XMLS.length; ++i) {
+                       sbFirst.append(BUG_XMLS[i]);
+                       for (int j = 0; j < BUG_XMLS.length; ++j) {
+                               sbSecond.append(BUG_XMLS[j]);
+                               
+                               String firstXml = sbFirst.toString() + BugReportData.getEpilogue();
+                               String secondXml = sbSecond.toString() + BugReportData.getEpilogue();
+                               
+                               doTestDelta(firstXml, secondXml);
+                       }
+               }
+       }
+       
+       @Test
+       public void testLocalVariable() throws FileNotFoundException, IOException, SAXException, ParserConfigurationException 
+       {
+               String xml = BugReportData.getPrologue()
+                                  + BugReportData.getRcnRedundantNullCheck()
+                                  + BugReportData.getEpilogue();
+
+               String html = createReport(null, xml);
+               validateReport(html);
+               
+               String expected = "con (LOCAL_VARIABLE_VALUE_OF)";
+               // expected string should be present exactly once
+               int pos = html.indexOf(expected);
+               assertTrue(pos > 0);
+               assertFalse(html.substring(pos + expected.length()).contains(expected));
+       }
+}
diff --git a/test/net/jaekl/cfb/analyze/MessageMapTest.java b/test/net/jaekl/cfb/analyze/MessageMapTest.java
new file mode 100644 (file)
index 0000000..45ada91
--- /dev/null
@@ -0,0 +1,63 @@
+package net.jaekl.cfb.analyze;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
+import net.jaekl.cfb.util.Command;
+import net.jaekl.cfb.xml.messages.BugCategory;
+import net.jaekl.cfb.xml.messages.BugPattern;
+import net.jaekl.cfb.xml.messages.MessageCollection;
+import net.jaekl.cfb.xml.messages.MessagesData;
+
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class MessageMapTest {
+
+       private boolean containsCategory(MessageCollection msgColl, String catName) {
+               for (BugCategory cat : msgColl.getCategories()) {
+                       if (catName.equals(cat.getCategory())) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
+       private boolean containsPattern(MessageCollection msgColl, String patName) {
+               BugPattern pat = msgColl.getPattern(patName);
+               return(null != pat);
+       }
+       
+       @Test
+       public void testParseMessagesData() throws FileNotFoundException, IOException, SAXException 
+       {
+               MessageMap msgMap = new MessageMap();
+               
+               ByteArrayInputStream bais = new ByteArrayInputStream(MessagesData.getData().getBytes(Command.UTF_8));
+               InputSource source = new InputSource(bais);             
+               msgMap.parse(source);
+               
+               MessageCollection msgColl = msgMap.getColl();
+               assertNotNull(msgColl);
+               
+               // Non-exhaustive list of category names that should have been picked up by the parse
+               String[] expectedCategories = { "BAD_PRACTICE", "CORRECTNESS", "PERFORMANCE", "STYLE" };
+       
+               for (String catName : expectedCategories) {
+                       assertTrue(containsCategory(msgMap.getColl(), catName));
+               }
+               
+               // Non-exhaustive list of pattern names that sohuld have been picked up by the parse
+               String[] expectedPatterns = { "DM_DEFAULT_ENCODING", "VO_VOLATILE_INCREMENT" };
+               
+               for (String patName : expectedPatterns) {
+                       assertTrue(containsPattern(msgMap.getColl(), patName));
+               }
+       }
+
+}
diff --git a/test/net/jaekl/cfb/util/XmlEscapeTest.java b/test/net/jaekl/cfb/util/XmlEscapeTest.java
new file mode 100644 (file)
index 0000000..f514e95
--- /dev/null
@@ -0,0 +1,53 @@
+package net.jaekl.cfb.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class XmlEscapeTest {
+
+       @Test
+       public void test() {
+               String[][] data = {
+                               { null, null },
+                               { "", "" },
+                               { "fred", "fred" },
+                               { "org.example.Foo.<init>()", "org.example.Foo.&lt;init&gt;()" },
+                               {
+                                       "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ",
+                                       "ἄνδρα μοι ἔννεπε, μοῦσα, πολύτροπον, ὃς μάλα πολλὰ"
+                               },
+                               {
+                                         "L'amour est enfant de Bohême\n"
+                                       + "Il n'a jamais, jamais connu de loi\n"
+                                       + "Si tu ne m'aimes pas, je t'aime\n"
+                                       + "Si je t'aime, prends garde à toi!\n"
+                                       + "Si tu ne m’aimes pas\n"
+                                       + "Si tu ne m’aimes pas, je t’aime!\n"
+                                       + "Mais, si je t’aime\n"
+                                       + "Si je t’aime, prends garde à toi!",
+                                       
+                                         "L&apos;amour est enfant de Bohême\n"
+                                       + "Il n&apos;a jamais, jamais connu de loi\n"
+                                       + "Si tu ne m&apos;aimes pas, je t&apos;aime\n"
+                                       + "Si je t&apos;aime, prends garde à toi!\n"
+                                       + "Si tu ne m’aimes pas\n"
+                                       + "Si tu ne m’aimes pas, je t’aime!\n"
+                                       + "Mais, si je t’aime\n"
+                                       + "Si je t’aime, prends garde à toi!",
+                               },
+                               {
+                                       "\"I'm sorry Dave,\" said Hal, \"but I can't do that.\"",
+                                       "&quot;I&apos;m sorry Dave,&quot; said Hal, &quot;but I can&apos;t do that.&quot;"
+                               }
+                       };
+               
+               for (String[] datum : data) {
+                       String input = datum[0];
+                       String expected = datum[1];
+                       String actual = XmlEscape.toEscaped(input);
+                       assertEquals(expected, actual);
+               }
+       }
+
+}
diff --git a/test/net/jaekl/cfb/xml/messages/MessagesData.java b/test/net/jaekl/cfb/xml/messages/MessagesData.java
new file mode 100644 (file)
index 0000000..28360b2
--- /dev/null
@@ -0,0 +1,450 @@
+package net.jaekl.cfb.xml.messages;
+
+public class MessagesData
+{
+    private static final String DATA =  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+           + "\n"
+           + "<MessageCollection xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
+           + "  xsi:noNamespaceSchemaLocation=\"messagecollection.xsd\">\n"
+           + "  <!--\n"
+           + "  **********************************************************************\n"
+           + "  Plugin information\n"
+           + "  **********************************************************************\n"
+           + "  -->\n"
+           + "  <Plugin>\n"
+           + "    <ShortDescription>Core FindBugs plugin</ShortDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p>\n"
+           + "This plugin contains all of the standard FindBugs detectors.\n"
+           + "</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "    <BugsUrl>http://findbugs.sourceforge.net/bugDescriptions.html</BugsUrl>\n"
+           + "    <AllBugsUrl>http://findbugs.sourceforge.net/allBugDescriptions.html</AllBugsUrl>\n"
+           + "  </Plugin>\n"
+           + "  <FindBugsMain cmd=\"addMessages\" class=\"edu.umd.cs.findbugs.AddMessages\">\n"
+           + "    <Description>Add msgs (e.g., textual descriptions of bugs) to analysis results</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"analyze\" class=\"edu.umd.cs.findbugs.FindBugs2\">\n"
+           + "    <Description>Perform FindBugs Analysis</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"gui\" class=\"edu.umd.cs.findbugs.gui2.Driver\">\n"
+           + "    <Description>Launch FindBugs GUI</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"list\" class=\"edu.umd.cs.findbugs.PrintingBugReporter\">\n"
+           + "    <Description>Convert analysis results to textual form</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"help\" class=\"edu.umd.cs.findbugs.ShowHelp\">\n"
+           + "    <Description>Provide help for commands</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"version\" class=\"edu.umd.cs.findbugs.Version\">\n"
+           + "    <Description>List FindBugs version</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"filter\" class=\"edu.umd.cs.findbugs.workflow.Filter\">\n"
+           + "    <Description>Filter analysis results</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"set\" class=\"edu.umd.cs.findbugs.workflow.SetBugDatabaseInfo\">\n"
+           + "    <Description>Set project configuration/options</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"history\" class=\"edu.umd.cs.findbugs.workflow.MineBugHistory\">\n"
+           + "    <Description>List details from multi-version analysis results</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"union\" class=\"edu.umd.cs.findbugs.workflow.UnionResults\">\n"
+           + "    <Description>Merge analysis results from disjoint components</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"merge\" class=\"edu.umd.cs.findbugs.workflow.Update\">\n"
+           + "    <Description>Combine analysis results from different versions of software to produce multi-version analysis results</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "\n"
+           + "  <FindBugsMain cmd=\"dis\" class=\"edu.umd.cs.findbugs.workflow.PrintClass\">\n"
+           + "    <Description>Disassemble a class file</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "  <FindBugsMain cmd=\"errors\" class=\"edu.umd.cs.findbugs.workflowListErrors\">\n"
+           + "    <Description>List analysis errors stored in results file</Description>\n"
+           + "  </FindBugsMain>\n"
+           + "\n"
+           + "  <!-- On changing this, please also update default cloud id in FindbugsPlugin -->\n"
+           + "  <Cloud id=\"edu.umd.cs.findbugs.cloud.doNothingCloud\">\n"
+           + "    <Description>(cloud disabled)</Description>\n"
+           + "    <Details>Bug reviews are disabled when using this plugin.</Details>\n"
+           + "  </Cloud>\n"
+           + "  <PluginComponent id=\"edu.umd.cs.findbugs.bugReporter.SuppressMultithreaded\">\n"
+           + "    <Description>Suppress multithreaded correctness issues</Description>\n"
+           + "    <Details>Suppress all multithreaded correctness issues</Details>\n"
+           + "  </PluginComponent>\n"
+           + "  <PluginComponent id=\"edu.umd.cs.findbugs.bugReporter.SuppressI18N\">\n"
+           + "    <Description>Suppress internationalization issues</Description>\n"
+           + "    <Details>Suppress all internationalization issues</Details>\n"
+           + "  </PluginComponent>\n"
+           + "  <PluginComponent id=\"edu.umd.cs.findbugs.bugReporter.SelectivelySuppressI18N\">\n"
+           + "    <Description>Suppress internationalization issues in all but selected packages</Description>\n"
+           + "    <Details>Suppress all internationalization issues except those specified in the i18n.properties resource</Details>\n"
+           + "  </PluginComponent>\n"
+           + "  <PluginComponent id=\"edu.umd.cs.findbugs.bugReporter.MaxRank14\">\n"
+           + "    <Description>Suppress all issues with rank higher than 14</Description>\n"
+           + "    <Details>Suppress all issues with rank higher than 14</Details>\n"
+           + "  </PluginComponent>\n"
+           + "  <PluginComponent id=\"edu.umd.cs.findbugs.bugReporter.SuppressMalicious\">\n"
+           + "    <Description>Suppress warnings about vulnerabilities to malicious code</Description>\n"
+           + "    <Details>Suppress warnings about vulnerabilities to malicious code</Details>\n"
+           + "  </PluginComponent>\n"
+           + "  <!--\n"
+           + "  **********************************************************************\n"
+           + "  Categories (replacing the BugCategoryDescriptions.properties file)\n"
+           + "  **********************************************************************\n"
+           + "   -->\n"
+           + "  <BugCategory category=\"CORRECTNESS\">\n"
+           + "    <Description>Correctness</Description>\n"
+           + "    <Abbreviation>C</Abbreviation>\n"
+           + "    <Details>Probable bug - an apparent coding mistake\n"
+           + "            resulting in code that was probably not what the\n"
+           + "            developer intended. We strive for a low false positive rate.</Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"NOISE\">\n"
+           + "    <Description>Bogus random noise</Description>\n"
+           + "    <Abbreviation>N</Abbreviation>\n"
+           + "    <Details>Bogus random noise: intended to be useful\n"
+           + "    as a control in data mining experiments, not in finding actual bugs in software\n"
+           + "            </Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"SECURITY\">\n"
+           + "    <Description>Security</Description>\n"
+           + "    <Abbreviation>S</Abbreviation>\n"
+           + "    <Details>A use of untrusted input in a way that could create a remotely exploitable security vulnerability.\n"
+           + "    </Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"BAD_PRACTICE\">\n"
+           + "    <Description>Bad practice</Description>\n"
+           + "    <Abbreviation>B</Abbreviation>\n"
+           + "    <Details>Violations of recommended and essential\n"
+           + "            coding practice. Examples include hash code and equals\n"
+           + "            problems, cloneable idiom, dropped exceptions,\n"
+           + "            Serializable problems, and misuse of finalize.\n"
+           + "            We strive to make this analysis accurate,\n"
+           + "            although some groups may\n"
+           + "            not care about some of the bad practices.</Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"STYLE\">\n"
+           + "    <Description>Dodgy code</Description>\n"
+           + "    <Abbreviation>D</Abbreviation>\n"
+           + "    <Details>code that is confusing, anomalous, or\n"
+           + "            written in a way that leads itself to errors.\n"
+           + "            Examples include dead local stores, switch fall through,\n"
+           + "            unconfirmed casts, and redundant null check of value\n"
+           + "            known to be null.\n"
+           + "            More false positives accepted.\n"
+           + "            In previous versions of FindBugs, this category was known as Style.\n"
+           + "</Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"PERFORMANCE\">\n"
+           + "    <Description>Performance</Description>\n"
+           + "    <Abbreviation>P</Abbreviation>\n"
+           + "    <Details>code that is not necessarily incorrect but may be inefficient</Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"MALICIOUS_CODE\">\n"
+           + "    <Description>Malicious code vulnerability</Description>\n"
+           + "    <Abbreviation>V</Abbreviation>\n"
+           + "    <Details>code that is vulnerable to attacks from untrusted code</Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"MT_CORRECTNESS\">\n"
+           + "    <Description>Multithreaded correctness</Description>\n"
+           + "    <Abbreviation>M</Abbreviation>\n"
+           + "    <Details>code flaws having to do with threads, locks, and volatiles</Details>\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"I18N\">\n"
+           + "    <Description>Internationalization</Description>\n"
+           + "    <Abbreviation>I</Abbreviation>\n"
+           + "    <Details>code flaws having to do with internationalization and locale</Details>\n"
+           + "    <!-- DM_CONVERT_CASE is the only core bug pattern in this category -->\n"
+           + "  </BugCategory>\n"
+           + "  <BugCategory category=\"EXPERIMENTAL\">\n"
+           + "    <Description>Experimental</Description>\n"
+           + "    <Abbreviation>X</Abbreviation>\n"
+           + "    <Details>Experimental and not fully vetted bug patterns</Details>\n"
+           + "    <!-- DM_CONVERT_CASE is the only core bug pattern in this category -->\n"
+           + "  </BugCategory>\n"
+           + "  <!--\n"
+           + "  **********************************************************************\n"
+           + "  Detectors\n"
+           + "  **********************************************************************\n"
+           + "   -->\n"
+           + "  <Detector class=\"edu.umd.cs.findbugs.detect.FindRoughConstants\">\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> Finds constants which roughly (but not precisely) equal to known values like Math.PI.\n"
+           + "</p>\n"
+           + "]]>\n"
+           + "     </Details>\n"
+           + "  </Detector>\n"
+           + "  <!--\n"
+           + "  **********************************************************************\n"
+           + "  BugPatterns\n"
+           + "  **********************************************************************\n"
+           + "   -->\n"
+           + "  <BugPattern type=\"DM_DEFAULT_ENCODING\">\n"
+           + "    <ShortDescription>Reliance on default encoding</ShortDescription>\n"
+           + "    <LongDescription>Found reliance on default encoding in {1}: {2}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> Found a call to a method which will perform a byte to String (or String to byte) conversion, and will assume that the default platform encoding is suitable. This will cause the application behaviour to vary between platforms. Use an alternative API and specify a charset name or Charset object explicitly.  </p>\n"
+           + "]]>\n"
+           + "      </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE\">\n"
+           + "    <ShortDescription>Nullcheck of value previously dereferenced</ShortDescription>\n"
+           + "    <LongDescription>Nullcheck of {2.givenClass} at {4.lineNumber} of value previously dereferenced in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> A value is checked here to see whether it is null, but this value can't\n"
+           + "be null because it was previously dereferenced and if it were null a null pointer\n"
+           + "exception would have occurred at the earlier dereference.\n"
+           + "Essentially, this code and the previous dereference\n"
+           + "disagree as to whether this value is allowed to be null. Either the check is redundant\n"
+           + "or the previous dereference is erroneous.</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE\">\n"
+           + "    <ShortDescription>Redundant nullcheck of value known to be null</ShortDescription>\n"
+           + "    <LongDescription>Redundant nullcheck of {2} which is known to be null in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> This method contains a redundant check of a known null value against\n"
+           + "the constant null.</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE\">\n"
+           + "    <ShortDescription>Redundant nullcheck of value known to be non-null</ShortDescription>\n"
+           + "    <LongDescription>Redundant nullcheck of {2}, which is known to be non-null in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> This method contains a redundant check of a known non-null value against\n"
+           + "the constant null.</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"RCN_REDUNDANT_COMPARISON_TWO_NULL_VALUES\">\n"
+           + "    <ShortDescription>Redundant comparison of two null values</ShortDescription>\n"
+           + "    <LongDescription>Redundant comparison of two null values in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> This method contains a redundant comparison of two references known to\n"
+           + "both be definitely null.</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"RCN_REDUNDANT_COMPARISON_OF_NULL_AND_NONNULL_VALUE\">\n"
+           + "    <ShortDescription>Redundant comparison of non-null value to null</ShortDescription>\n"
+           + "    <LongDescription>Redundant comparison of non-null value to null in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> This method contains a reference known to be non-null with another reference\n"
+           + "known to be null.</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"RCN_REDUNDANT_CHECKED_NULL_COMPARISON\" deprecated=\"true\">\n"
+           + "    <!-- deprecated in favor of two separate RCN_ patterns -->\n"
+           + "    <ShortDescription>Redundant comparison to null of previously checked value</ShortDescription>\n"
+           + "    <LongDescription>Redundant comparison to null of previously checked {2} in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p> This method contains a redundant comparison of a reference value\n"
+           + "to null. Two types of redundant comparison are reported:\n"
+           + "</p>\n"
+           + "<ul>\n"
+           + "<li> Both values compared are definitely null</li>\n"
+           + "<li> One value is definitely null and the other is definitely not null</li>\n"
+           + "</ul>\n"
+           + "\n"
+           + "<p> This particular warning generally indicates that a\n"
+           + "value known not to be null was checked against null.\n"
+           + "While the check is not necessary, it may simply be a case\n"
+           + "of defensive programming.</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"VO_VOLATILE_INCREMENT\">\n"
+           + "    <ShortDescription>An increment to a volatile field isn't atomic</ShortDescription>\n"
+           + "    <LongDescription>Increment of volatile field {2} in {1}</LongDescription>\n"
+           + "    <Details>\n"
+           + "<![CDATA[\n"
+           + "<p>This code increments a volatile field. Increments of volatile fields aren't\n"
+           + "atomic. If more than one thread is incrementing the field at the same time,\n"
+           + "increments could be lost.\n"
+           + "</p>\n"
+           + "]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <BugPattern type=\"DM_NUMBER_CTOR\">\n"
+           + "    <ShortDescription>Method invokes inefficient Number constructor; use static valueOf instead</ShortDescription>\n"
+           + "    <LongDescription>{1} invokes inefficient {2} constructor; use {3} instead</LongDescription>\n"
+           + "    <Details>\n"
+           + "      <![CDATA[\n"
+           + "      <p>\n"
+           + "      Using <code>new Integer(int)</code> is guaranteed to always result in a new object whereas\n"
+           + "      <code>Integer.valueOf(int)</code> allows caching of values to be done by the compiler, class library, or JVM.\n"
+           + "      Using of cached values avoids object allocation and the code will be faster.\n"
+           + "      </p>\n"
+           + "      <p>\n"
+           + "      Values between -128 and 127 are guaranteed to have corresponding cached instances\n"
+           + "      and using <code>valueOf</code> is approximately 3.5 times faster than using constructor.\n"
+           + "      For values outside the constant range the performance of both styles is the same.\n"
+           + "      </p>\n"
+           + "      <p>\n"
+           + "      Unless the class must be compatible with JVMs predating Java 1.5,\n"
+           + "      use either autoboxing or the <code>valueOf()</code> method when creating instances of\n"
+           + "      <code>Long</code>, <code>Integer</code>, <code>Short</code>, <code>Character</code>, and <code>Byte</code>.\n"
+           + "      </p>\n"
+           + "      ]]>\n"
+           + "    </Details>\n"
+           + "  </BugPattern>\n"
+           + "  <!--\n"
+           + "  **********************************************************************\n"
+           + "   BugCodes\n"
+           + "  **********************************************************************\n"
+           + "   -->\n"
+           + "  <BugCode abbrev=\"FS\">Format string problem</BugCode>\n"
+           + "  <BugCode abbrev=\"SKIPPED\">Analysis skipped</BugCode>\n"
+           + "  <BugCode abbrev=\"IL\">Infinite Loop</BugCode>\n"
+           + "  <BugCode abbrev=\"VO\">Use of volatile</BugCode>\n"
+           + "  <BugCode abbrev=\"UI\">Unsafe inheritance</BugCode>\n"
+           + "  <BugCode abbrev=\"FL\">Use of floating point precision</BugCode>\n"
+           + "  <BugCode abbrev=\"TEST\">Testing prototype and incomplete bug pattern</BugCode>\n"
+           + "  <BugCode abbrev=\"IMSE\">Dubious catching of IllegalMonitorStateException</BugCode>\n"
+           + "  <BugCode abbrev=\"CN\">Bad implementation of cloneable idiom</BugCode>\n"
+           + "  <BugCode abbrev=\"CAA\">Covariant array assignment</BugCode>\n"
+           + "  <BugCode abbrev=\"AT\">Possible atomicity violation</BugCode>\n"
+           + "  <BugCode abbrev=\"FI\">Incorrect use of finalizers</BugCode>\n"
+           + "  <BugCode abbrev=\"ES\">Checking String equality using == or !=</BugCode>\n"
+           + "  <BugCode abbrev=\"ML\">Synchronization on updated field (Mutable Lock)</BugCode>\n"
+           + "  <BugCode abbrev=\"UG\">Unsynchronized get method, synchronized set method</BugCode>\n"
+           + "  <BugCode abbrev=\"IO\">Input/Output problem</BugCode>\n"
+           + "  <BugCode abbrev=\"IC\">Initialization circularity</BugCode>\n"
+           + "  <BugCode abbrev=\"SI\">Suspicious static initializer</BugCode>\n"
+           + "  <BugCode abbrev=\"MSF\">Mutable servlet field</BugCode>\n"
+           + "  <BugCode abbrev=\"IS\">Inconsistent synchronization</BugCode>\n"
+           + "  <BugCode abbrev=\"Eq\">Problems with implementation of equals()</BugCode>\n"
+           + "  <BugCode abbrev=\"Co\">Problems with implementation of compareTo()</BugCode>\n"
+           + "  <BugCode abbrev=\"HE\">Equal objects must have equal hashcodes</BugCode>\n"
+           + "  <BugCode abbrev=\"AM\">API misuse</BugCode>\n"
+           + "  <BugCode abbrev=\"Dm\">Dubious method used</BugCode>\n"
+           + "  <BugCode abbrev=\"Bx\">Questionable Boxing of primitive value</BugCode>\n"
+           + "  <BugCode abbrev=\"UR\">Uninitialized read of field in constructor</BugCode>\n"
+           + "  <BugCode abbrev=\"RR\">Method ignores results of InputStream.read()</BugCode>\n"
+           + "  <BugCode abbrev=\"NN\">Naked notify</BugCode>\n"
+           + "  <BugCode abbrev=\"UW\">Unconditional wait</BugCode>\n"
+           + "  <BugCode abbrev=\"SP\">Method spins on field</BugCode>\n"
+           + "  <BugCode abbrev=\"DC\">Double check pattern</BugCode>\n"
+           + "  <BugCode abbrev=\"Wa\">Wait not in loop</BugCode>\n"
+           + "  <BugCode abbrev=\"No\">Using notify() rather than notifyAll()</BugCode>\n"
+           + "  <BugCode abbrev=\"DE\">Dropped or ignored exception</BugCode>\n"
+           + "  <BugCode abbrev=\"Ru\">Method invokes run()</BugCode>\n"
+           + "  <BugCode abbrev=\"It\">Incorrect definition of Iterator</BugCode>\n"
+           + "  <BugCode abbrev=\"SnVI\">Serializable class with no Version ID</BugCode>\n"
+           + "  <BugCode abbrev=\"Se\">Incorrect definition of Serializable class</BugCode>\n"
+           + "  <BugCode abbrev=\"WS\">Class's writeObject() method is synchronized but nothing else is</BugCode>\n"
+           + "  <BugCode abbrev=\"RS\">Class's readObject() method is synchronized</BugCode>\n"
+           + "  <BugCode abbrev=\"SC\">Constructor invokes Thread.start()</BugCode>\n"
+           + "  <BugCode abbrev=\"MS\">Mutable static field</BugCode>\n"
+           + "  <BugCode abbrev=\"ME\">Mutable enum field</BugCode>\n"
+           + "  <BugCode abbrev=\"EI\">Method returning array may expose internal representation</BugCode>\n"
+           + "  <BugCode abbrev=\"Nm\">Confusing method name</BugCode>\n"
+           + "  <BugCode abbrev=\"SS\">Unread field should be static</BugCode>\n"
+           + "  <BugCode abbrev=\"UuF\">Unused field</BugCode>\n"
+           + "  <BugCode abbrev=\"UrF\">Unread field</BugCode>\n"
+           + "  <BugCode abbrev=\"UwF\">Unwritten field</BugCode>\n"
+           + "  <BugCode abbrev=\"SIC\">Inner class could be made static</BugCode>\n"
+           + "  <BugCode abbrev=\"TLW\">Wait with two locks held</BugCode>\n"
+           + "  <BugCode abbrev=\"RANGE\">Range checks</BugCode>\n"
+           + "  <BugCode abbrev=\"RV\">Bad use of return value from method</BugCode>\n"
+           + "  <BugCode abbrev=\"LG\">Logger problem</BugCode>\n"
+           + "  <BugCode abbrev=\"IA\">Ambiguous invocation</BugCode>\n"
+           + "  <BugCode abbrev=\"HSC\">Huge String constants</BugCode>\n"
+           + "  <BugCode abbrev=\"HRS\">HTTP Response splitting vulnerability</BugCode>\n"
+           + "  <BugCode abbrev=\"PT\">Path traversal</BugCode>\n"
+           + "  <BugCode abbrev=\"XSS\">Cross site scripting vulnerability</BugCode>\n"
+           + "  <BugCode abbrev=\"NP\">Null pointer dereference</BugCode>\n"
+           + "  <BugCode abbrev=\"NOISE\">Bogus random warning</BugCode>\n"
+           + "  <BugCode abbrev=\"RpC\">Repeated conditional test</BugCode>\n"
+           + "  <BugCode abbrev=\"OS\">Stream not closed on all paths</BugCode>\n"
+           + "  <BugCode abbrev=\"PZLA\">Prefer zero length arrays to null to indicate no results</BugCode>\n"
+           + "  <BugCode abbrev=\"UCF\">Useless control flow</BugCode>\n"
+           + "  <BugCode abbrev=\"RCN\">Redundant comparison to null</BugCode>\n"
+           + "  <BugCode abbrev=\"UL\">Lock not released on all paths</BugCode>\n"
+           + "  <BugCode abbrev=\"RC\">Questionable use of reference equality rather than calling equals</BugCode>\n"
+           + "  <BugCode abbrev=\"EC\">Comparing incompatible types for equality</BugCode>\n"
+           + "  <BugCode abbrev=\"MWN\">Mismatched wait() or notify()</BugCode>\n"
+           + "  <BugCode abbrev=\"SA\">Useless self-operation</BugCode>\n"
+           + "  <BugCode abbrev=\"INT\">Suspicious integer expression</BugCode>\n"
+           + "  <BugCode abbrev=\"BIT\">Suspicious bitwise logical expression</BugCode>\n"
+           + "  <BugCode abbrev=\"LI\">Unsynchronized Lazy Initialization</BugCode>\n"
+           + "  <BugCode abbrev=\"JLM\">Synchronization on java.util.concurrent objects</BugCode>\n"
+           + "  <BugCode abbrev=\"UPM\">Private method is never called</BugCode>\n"
+           + "  <BugCode abbrev=\"UMAC\">Uncallable method of anonymous class</BugCode>\n"
+           + "  <BugCode abbrev=\"EI2\">Storing reference to mutable object</BugCode>\n"
+           + "  <BugCode abbrev=\"NS\">Suspicious use of non-short-circuit boolean operator</BugCode>\n"
+           + "  <BugCode abbrev=\"ODR\">Database resource not closed on all paths</BugCode>\n"
+           + "  <BugCode abbrev=\"SBSC\">String concatenation in loop using + operator</BugCode>\n"
+           + "  <BugCode abbrev=\"IIL\">Inefficient code which can be moved outside of the loop</BugCode>\n"
+           + "  <BugCode abbrev=\"IIO\">Inefficient use of String.indexOf(String) or String.lastIndexOf(String)</BugCode>\n"
+           + "  <BugCode abbrev=\"ITA\">Inefficient use of collection.toArray(new Foo[0])</BugCode>\n"
+           + "  <BugCode abbrev=\"SW\">Swing coding rules</BugCode>\n"
+           + "  <BugCode abbrev=\"IJU\">Improperly implemented JUnit TestCase</BugCode>\n"
+           + "  <BugCode abbrev=\"BOA\">Badly Overridden Adapter</BugCode>\n"
+           + "  <BugCode abbrev=\"SF\">Switch case falls through</BugCode>\n"
+           + "  <BugCode abbrev=\"SIO\">Superfluous instanceof</BugCode>\n"
+           + "  <BugCode abbrev=\"BAC\">Bad Applet Constructor</BugCode>\n"
+           + "  <BugCode abbrev=\"UOE\">Use Object Equals</BugCode>\n"
+           + "  <BugCode abbrev=\"STI\">Suspicious Thread Interrupted</BugCode>\n"
+           + "  <BugCode abbrev=\"DLS\">Dead local store</BugCode>\n"
+           + "  <BugCode abbrev=\"IP\">Ignored parameter</BugCode>\n"
+           + "  <BugCode abbrev=\"MF\">Masked Field</BugCode>\n"
+           + "  <BugCode abbrev=\"WMI\">Inefficient Map Iterator</BugCode>\n"
+           + "  <BugCode abbrev=\"ISC\">Instantiated Static Class</BugCode>\n"
+           + "  <BugCode abbrev=\"REC\">RuntimeException capture</BugCode>\n"
+           + "  <BugCode abbrev=\"FE\">Test for floating point equality</BugCode>\n"
+           + "  <BugCode abbrev=\"UM\">Unnecessary Math on constants</BugCode>\n"
+           + "  <BugCode abbrev=\"UC\">Useless code</BugCode>\n"
+           + "  <BugCode abbrev=\"CNT\">Rough value of known constant</BugCode>\n"
+           + "  <BugCode abbrev=\"CD\">Circular Dependencies</BugCode>\n"
+           + "  <BugCode abbrev=\"RI\">Redundant Interfaces</BugCode>\n"
+           + "  <BugCode abbrev=\"MTIA\">Multithreaded Instance Access</BugCode>\n"
+           + "  <BugCode abbrev=\"PS\">Public Semaphores</BugCode>\n"
+           + "  <BugCode abbrev=\"BSHIFT\">Bad shift</BugCode>\n"
+           + "  <BugCode abbrev=\"ICAST\">Casting from integer values</BugCode>\n"
+           + "  <BugCode abbrev=\"RE\">Regular expressions</BugCode>\n"
+           + "  <BugCode abbrev=\"SQL\">Potential SQL Problem</BugCode>\n"
+           + "  <BugCode abbrev=\"WL\">Possible locking on wrong object</BugCode>\n"
+           + "  <BugCode abbrev=\"ESync\">Empty Synchronized blocks</BugCode>\n"
+           + "  <BugCode abbrev=\"QF\">Questionable for loops</BugCode>\n"
+           + "  <BugCode abbrev=\"VA\">Var arg problems</BugCode>\n"
+           + "  <BugCode abbrev=\"BC\">Bad casts of object references</BugCode>\n"
+           + "  <BugCode abbrev=\"IM\">Questionable integer math</BugCode>\n"
+           + "  <BugCode abbrev=\"ST\">Misuse of static fields</BugCode>\n"
+           + "  <BugCode abbrev=\"JCIP\">Violation of net.jcip annotations</BugCode>\n"
+           + "  <BugCode abbrev=\"USELESS_STRING\">Useless/non-informative string generated</BugCode>\n"
+           + "  <BugCode abbrev=\"DMI\">Dubious method invocation</BugCode>\n"
+           + "  <BugCode abbrev=\"PZ\">Warning inspired by Josh Bloch's and Neal Gafter's Programming Puzzlers</BugCode>\n"
+           + "  <BugCode abbrev=\"SWL\">Sleep with lock held</BugCode>\n"
+           + "  <BugCode abbrev=\"J2EE\">J2EE error</BugCode>\n"
+           + "  <BugCode abbrev=\"DB\">Duplicate Branches</BugCode>\n"
+           + "  <BugCode abbrev=\"IMA\">Inefficient Member Access</BugCode>\n"
+           + "  <BugCode abbrev=\"XFB\">XML Factory Bypass</BugCode>\n"
+           + "  <BugCode abbrev=\"USM\">Useless Subclass Method</BugCode>\n"
+           + "  <BugCode abbrev=\"CI\">Confused Inheritance</BugCode>\n"
+           + "  <BugCode abbrev=\"QBA\">Questionable Boolean Assignment</BugCode>\n"
+           + "  <BugCode abbrev=\"VR\">Version compatibility issue</BugCode>\n"
+           + "  <BugCode abbrev=\"DP\">Use doPrivileged</BugCode>\n"
+           + "  <BugCode abbrev=\"GC\">Suspicious calls to generic collection methods</BugCode>\n"
+           + "  <BugCode abbrev=\"STCAL\">Static use of type Calendar or DateFormat</BugCode>\n"
+           + "  <BugCode abbrev=\"TQ\">Inconsistent use of type qualifier annotations</BugCode>\n"
+           + "  <BugCode abbrev=\"OBL\">Unsatisfied obligation to clean up stream or resource</BugCode>\n"
+           + "  <BugCode abbrev=\"FB\">FindBugs did not produce the expected warnings on a method</BugCode>\n"
+           + "  <BugCode abbrev=\"DL\">Unintended contention or possible deadlock due to locking on shared objects</BugCode>\n"
+           + "</MessageCollection>\n";
+    
+    public static String getData() { return DATA; }
+}