+analysis.failed=Attempt to analyze source code failed. Will now stop.
cannot.connect.to.db=Unable to connect to database {2} on {0}:{1} as user {3}.
cannot.exec=Got result code {1} when attempting to execute command-line: {0}
stderr.was=-----8<------ Error (stderr) output was: ------8<-----
-stdout.was=-----8<----- Console (stdout) output was: -----8<-----
\ No newline at end of file
+stdout.was=-----8<----- Console (stdout) output was: -----8<-----
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Locale;
+import java.util.Locale.Category;
import net.jaekl.cfb.analyze.Analysis;
import net.jaekl.cfb.analyze.Analyzer;
+import net.jaekl.cfb.analyze.MessageMap;
import net.jaekl.cfb.db.CfbSchema;
import net.jaekl.cfb.db.driver.DbDriver;
import net.jaekl.cfb.db.driver.PostgresqlDriver;
+import net.jaekl.cfb.store.DbStore;
import net.jaekl.qd.xml.XmlParseException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
+import org.xml.sax.SAXException;
public class CFB {
DbDriver m_driver;
int m_port; // db port
String m_user; // db user
String m_pass; // db password
+ String m_buildNum; // build number (version)
CFB(Locale locale) {
m_driver = new PostgresqlDriver();
m_port = 5432;
m_pass = "";
m_user = "user";
+ m_buildNum = null;
}
Options createOptions() {
opt.addOption("d", "dbname", true, "DB name");
opt.addOption("f", "fbp", true, "FindBugsProject file");
opt.addOption("h", "host", true, "DB hostname");
+ opt.addOption("n", "number", true, "Build number (version)");
opt.addOption("p", "pass", true, "DB password");
opt.addOption("t", "port", true, "DB port");
opt.addOption("u", "user", true, "DB username");
if (line.hasOption("h")) {
m_host = line.getOptionValue("h");
}
+ if (line.hasOption("n")) {
+ m_buildNum = line.getOptionValue("n");
+ }
if (line.hasOption("p")) {
m_pass = line.getOptionValue("p");
}
return System.getProperty(propName);
}
+ File getFindBugsDir() {
+ return (null != m_fbDir) ? m_fbDir : new File(".");
+ }
+
void initArgs() {
String findBugsDir = getenv("FINDBUGS_HOME");
if (null != findBugsDir) {
}
}
- void doMain(PrintWriter pw, String[] args) throws SQLException, IOException, XmlParseException {
+ void doMain(PrintWriter pw, String[] args) throws SQLException, IOException, XmlParseException, SAXException {
initArgs(); // read environment and system properties
if ( ! parseArgs(pw, args) ) {
return;
m_schema.ensureDbInitialized(con);
}
catch (SQLException exc) {
- String cannotConnectFormat = trans(CfbBundle.CANNOT_CONNECT);
- String cannotConnect = MessageFormat.format(cannotConnectFormat, m_host, ""+m_port, m_dbName, m_user);
- exc.printStackTrace(pw);
- pw.println(cannotConnect);
+ reportUnableToConnect(pw, exc);
return;
}
- File findBugsDir = (null != m_fbDir) ? m_fbDir : new File(".");
+ File findBugsDir = getFindBugsDir();
File workDir = new File(".");
- Analyzer analyzer = new Analyzer(findBugsDir);
- Analysis analysis = analyzer.analyze(pw, workDir, m_fbp);
- if (null != analysis) {
- // TODO
+ MessageMap messageMap = new MessageMap();
+ messageMap.load(findBugsDir, Locale.getDefault(Category.DISPLAY));
+ Analyzer analyzer = new Analyzer(messageMap);
+ Analysis analysis = analyzer.analyze(pw, workDir, m_fbp, m_buildNum);
+ if (null == analysis) {
+ pw.println(trans(CfbBundle.ANALYSIS_FAILED));
+ return;
+ }
+
+ try (Connection con = m_driver.connect(m_host, m_port, m_dbName, m_user, m_pass)) {
+ DbStore store = new DbStore(con);
+
+ store.put(analysis);
+ }
+ catch (SQLException exc) {
+ reportUnableToConnect(pw, exc);
+ return;
}
}
+
+ private void reportUnableToConnect(PrintWriter pw, SQLException exc) {
+ String cannotConnectFormat = trans(CfbBundle.CANNOT_CONNECT);
+ String cannotConnect = MessageFormat.format(cannotConnectFormat, m_host, ""+m_port, m_dbName, m_user);
+ exc.printStackTrace(pw);
+ pw.println(cannotConnect);
+ }
public static void main(String[] args) {
CFB cfb = new CFB(Locale.getDefault());
try (PrintWriter pw = new PrintWriter(System.out)){
cfb.doMain(pw, args);
pw.flush();
- } catch (SQLException | IOException | XmlParseException exc) {
+ } catch (SQLException | IOException | XmlParseException | SAXException exc) {
exc.printStackTrace();
}
}
import net.jaekl.qd.QDBundleFactory;
public class CfbBundle {
+ public static final String ANALYSIS_FAILED = "analysis.failed";
public static final String CANNOT_CONNECT = "cannot.connect.to.db";
public static final String CANNOT_EXEC = "cannot.exec";
public static final String STDERR_WAS = "stderr.was";
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Date;
import net.jaekl.cfb.xml.BugCollection;
import net.jaekl.qd.xml.ParseErrorHandler;
public class Analysis {
BugCollection m_bugCollection;
+ String m_buildNumber;
+ Date m_date; // Date/time when analysis was started
- public Analysis() {
+ public Analysis(String buildNumber) {
m_bugCollection = null;
+ m_buildNumber = buildNumber;
+ m_date = new Date();
}
public BugCollection getBugCollection() { return m_bugCollection; }
import net.jaekl.qd.xml.XmlParseException;
public class Analyzer {
- File m_findbugsDir;
+ MessageMap m_msgMap;
- public Analyzer(File findbugsDir) {
- m_findbugsDir = findbugsDir;
+ public Analyzer(MessageMap msgMap) {
+ m_msgMap = msgMap;
}
- public Analysis analyze(PrintWriter pw, File workDir, File fbp) throws IOException, XmlParseException {
- Analysis result = new Analysis();
+ public Analysis analyze(PrintWriter pw, File workDir, File fbp, String buildNumber) throws IOException, XmlParseException, SAXException
+ {
+ Analysis result = new Analysis(buildNumber);
File fbOutput = outputWorkFile(workDir, fbp);
return null;
}
- result = parseFbOutput(new InputSource(fbOutput.getAbsolutePath()));
+ result.parse(new InputSource(fbOutput.getAbsolutePath()));
result.dump(pw);
return result;
}
StringBuilder sb = new StringBuilder();
- sb.append(m_findbugsDir.getAbsolutePath())
+ sb.append(m_msgMap.getFindBugsDir().getAbsolutePath())
.append(File.separator)
.append("bin")
.append(File.separator)
return new File(workPath + File.separator + projName + ".xml");
}
-
- // Parse the output.xml that resulted from a FindBugs run,
- // and store its findings into an Analysis object.
- Analysis parseFbOutput(InputSource fbOutput) throws XmlParseException
- {
- Analysis result = new Analysis();
- try {
- result.parse(fbOutput);
- } catch (IOException | SAXException exc) {
- throw new XmlParseException(exc);
- }
- return result;
- }
}
--- /dev/null
+package net.jaekl.cfb.analyze;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Locale;
+
+import net.jaekl.cfb.xml.messages.MessageCollection;
+import net.jaekl.qd.xml.ParseErrorHandler;
+import net.jaekl.qd.xml.ParseHandler;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+public class MessageMap {
+ static final String MESSAGES = "messages";
+ static final String XML = "xml";
+
+ MessageCollection m_msgColl;
+ File m_findBugsDir;
+
+ public MessageMap() {
+ m_msgColl = null;
+ m_findBugsDir = null;
+ }
+
+ public MessageCollection getColl() { return m_msgColl; }
+ public File getFindBugsDir() { return m_findBugsDir; }
+
+ public void load(File findBugsDir, Locale locale) throws FileNotFoundException, IOException, SAXException
+ {
+ m_findBugsDir = findBugsDir;
+
+ String langName = locale.getLanguage();
+
+ File msgXml = new File(findBugsDir.getAbsolutePath() + File.separator + MESSAGES + "_" + langName + "." + XML);
+ if (! msgXml.canRead()) {
+ msgXml = new File(findBugsDir.getAbsolutePath() + File.separator + MESSAGES + "." + XML);
+ }
+
+ if (! msgXml.canRead()) {
+ throw new FileNotFoundException(msgXml.getAbsolutePath());
+ }
+
+ parse(new InputSource(new FileInputStream(msgXml)));
+
+ }
+
+ void parse(InputSource xml) throws FileNotFoundException, IOException, SAXException
+ {
+ m_msgColl = new MessageCollection();
+
+ XMLReader reader = XMLReaderFactory.createXMLReader();
+ ParseHandler ph = new ParseHandler(m_msgColl);
+ ParseErrorHandler peh = new ParseErrorHandler();
+ reader.setContentHandler(ph);
+ reader.setErrorHandler(peh);
+ reader.parse(xml);
+ }
+}
// }
private static final Object[][][] TABLES = {
{
- { "BUGS" },
+ // Description of each possible bug
+ { "BUG" },
{ "BUGID", INTEGER, -1, NOT_NULL },
- { "TYPE", VARCHAR, 80, NOT_NULL },
- { "SHORTDESCR", VARCHAR, 128, NOT_NULL },
- { "LONGDESCR", VARCHAR, 128, NOT_NULL },
- { "DETAILS", VARCHAR, 4096, NOT_NULL }
+ { "TYPE", VARCHAR, 80, NOT_NULL }
},
{
- { "CATEGORIES" },
+ // Description of each possible bug category
+ { "CATEGORY" },
{ "CATEGORYID", INTEGER, -1, NOT_NULL },
- { "DESCRIPTION", VARCHAR, 128, NOT_NULL },
- { "ABBREVIATION", CHAR, 1, NOT_NULL },
- { "DETAILS", VARCHAR, 4096, NOT_NULL }
+ { "CATEGORY", VARCHAR, 80, NOT_NULL }
},
{
+ // One BugInstance, found during an analysis
{ "FOUND" },
{ "FOUNDID", INTEGER, -1, NOT_NULL },
{ "BUGID", INTEGER, -1, NOT_NULL },
{ "THIRDLOCID", INTEGER, -1, NULL }
},
{
+ // Location in the source code referenced by a BugInstance
{ "LOCATION" },
{ "LOCID", INTEGER, -1, NOT_NULL },
{ "CLASSNAME", VARCHAR, 256, NOT_NULL },
},
{
// Runs of FindBugs, normally one per build version
- { "RUNS" },
+ { "RUN" },
{ "RUNID", INTEGER, -1, NOT_NULL },
{ "VERSION", VARCHAR, 32, NULL },
{ "STARTTIME", TIMESTAMPTZ, -1, NOT_NULL },
--- /dev/null
+package net.jaekl.cfb.db;
+
+public class Condition {
+
+ Column m_column;
+ Object m_value;
+ Operation m_operation;
+
+ public Condition(Column column, Object value, Operation operation)
+ {
+ m_column = column;
+ m_value = value;
+ m_operation = operation;
+ }
+
+ public Condition(Column column, Object value) {
+ this(column, value, Operation.EQUAL);
+ }
+
+ public Column getColumn() { return m_column; }
+ public Object getValue() { return m_value; }
+ public Operation getOperation() { return m_operation; }
+}
--- /dev/null
+package net.jaekl.cfb.db;
+
+public enum Operation {
+ EQUAL(" = ? ", true),
+ LESS_THAN(" < ? ", true),
+ GREATER_THAN(" > ? ", true),
+ NULL(" is null ", false),
+ NOT_NULL(" is not null ", false);
+
+ String m_sql;
+ boolean m_hasParam;
+
+ Operation(String sql, boolean hasParam) {
+ m_sql = sql;
+ m_hasParam = hasParam;
+ }
+
+ public String getSql() { return m_sql; }
+ public boolean hasParam() { return m_hasParam; }
+}
--- /dev/null
+package net.jaekl.cfb.db;
+
+
+public class Row {
+ Column[] m_columns;
+ Object[] m_values;
+
+ public Row(Column[] columns, Object[] values)
+ {
+ m_columns = columns.clone();
+ m_values = values.clone();
+ }
+
+ public int getNumColumns() { return m_columns.length; }
+
+ public String getString(int index) throws TypeMismatchException {
+ checkType(index, Column.Type.VARCHAR);
+ return (String)m_values[index];
+ }
+
+ public int getInt(int index) throws TypeMismatchException
+ {
+ checkType(index, Column.Type.INTEGER);
+ Number num = (Number)m_values[index];
+ return num.intValue();
+ }
+
+ public long getLong(int index) throws TypeMismatchException
+ {
+ checkType(index, Column.Type.INTEGER);
+ Number num = (Number)m_values[index];
+ return num.longValue();
+ }
+
+ protected void checkType(int index, Column.Type type) throws TypeMismatchException {
+ Column column = m_columns[index];
+ if (column.getType().equals(type)) {
+ return;
+ }
+
+ String msg = "Column " + column.getName()
+ + " is of type " + column.getType().name()
+ + " which cannot be coerced to type " + type.name() + ".";
+ throw new TypeMismatchException(msg);
+ }
+}
String m_name;
DbDriver m_driver;
ArrayList<Table> m_tables;
+ ArrayList<Sequence> m_sequences;
public Schema(String name, DbDriver driver) {
m_name = name;
m_driver = driver;
m_tables = new ArrayList<Table>();
+ m_sequences = new ArrayList<Sequence>();
}
public boolean ensureDbInitialized(Connection con) throws SQLException {
return false;
}
+ if (!createAllSequences(con)) {
+ return false;
+ }
+
return true;
}
return true;
}
+ boolean createAllSequences(Connection con) throws SQLException {
+ for (Sequence seq : m_sequences) {
+ if (!m_driver.createSequence(con, seq)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
void addTable(Table table) {
m_tables.add(table);
}
for (Object[][] table : tables) {
addTable(Table.construct(table));
}
- }
+ }
+
+ void addSequence(Sequence seq) {
+ m_sequences.add(seq);
+ }
}
--- /dev/null
+package net.jaekl.cfb.db;
+
+public class Sequence {
+ String m_name;
+
+ public Sequence(String name) {
+ m_name = name;
+ }
+
+ public String getName() { return m_name; }
+}
--- /dev/null
+package net.jaekl.cfb.db;
+
+public class TypeMismatchException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public TypeMismatchException(String msg) {
+ super(msg);
+ }
+}
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
import net.jaekl.cfb.db.Column;
import net.jaekl.cfb.db.Column.Type;
+import net.jaekl.cfb.db.Condition;
+import net.jaekl.cfb.db.Row;
+import net.jaekl.cfb.db.Sequence;
import net.jaekl.cfb.db.Table;
public abstract class DbDriver {
return true;
}
- public abstract ResultSet selectColumnsFromWhere(Column[] columns, Table[] tables, String where);
+ public boolean createSequence(Connection con, Sequence seq) throws SQLException
+ {
+ String sql = createSequenceSql(seq);
+ try (PreparedStatement ps = con.prepareStatement(sql)) {
+ ps.executeUpdate();
+ }
+ catch (SQLException exc) {
+ throw new SQLException("Failed to executeUpdate: " + sql, exc);
+ }
+
+ return true;
+ }
+
+ public List<Row> select(Connection con, Column[] columns, Table[] tables, Condition[] conditions)
+ throws SQLException
+ {
+ String sql = selectSql(columns, tables, conditions);
+ ArrayList<Row> result = new ArrayList<Row>();
+
+ try (PreparedStatement ps = con.prepareStatement(sql)) {
+ int index = 0;
+ for (Condition condition : conditions) {
+ if (condition.getOperation().hasParam()) {
+ index++;
+ ps.setObject(index, condition.getValue());
+ }
+ }
+
+ try (ResultSet rs = ps.executeQuery()) {
+ while (rs.next()) {
+ Object[] values = new Object[columns.length];
+ for (index = 0; index < columns.length; ++index) {
+ values[index] = rs.getObject(index);
+ }
+ Row row = new Row(columns, values);
+ result.add(row);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ protected String selectSql(Column[] columns, Table[] tables, Condition[] conditions)
+ {
+ StringBuilder sb = new StringBuilder("SELECT ");
+
+ boolean firstColumn = true;
+ for (Column column : columns) {
+ if (firstColumn) {
+ firstColumn = false;
+ }
+ else {
+ sb.append(", ");
+ }
+ sb.append(column.getName());
+ }
+
+ sb.append(" FROM ");
+
+ boolean firstTable = true;
+ for (Table table : tables) {
+ if (firstTable) {
+ firstTable = false;
+ }
+ else {
+ sb.append(", ");
+ }
+ sb.append(table.getName());
+ }
+
+ if (null != conditions && conditions.length > 0) {
+ sb.append(" WHERE ");
+
+ boolean firstCondition = true;
+
+ for (Condition condition : conditions) {
+ if (firstCondition) {
+ firstCondition = false;
+ }
+ else {
+ sb.append(" AND ");
+ }
+
+ sb.append(condition.getColumn().getName())
+ .append(condition.getOperation().getSql());
+ }
+ }
+
+ return sb.toString();
+ }
protected String typeName(Type type) {
return type.toString();
return sb.toString();
}
+
+ protected String createSequenceSql(Sequence seq) {
+ assert(null != seq);
+ assert(null != seq.getName());
+
+ return "CREATE SEQUENCE " + seq.getName();
+ }
}
import java.sql.Connection;
import java.sql.DriverManager;
-import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
-import net.jaekl.cfb.db.Column;
-import net.jaekl.cfb.db.Table;
-
public class PostgresqlDriver extends DbDriver {
@Override
//props.setProperty("ssl", "true");
return DriverManager.getConnection(url, props);
}
-
- @Override
- public ResultSet selectColumnsFromWhere(Column[] columns, Table[] tables, String where) {
- // TODO Auto-generated method stub
- return null;
- }
-
}
--- /dev/null
+package net.jaekl.cfb.store;
+
+import java.sql.Connection;
+
+import net.jaekl.cfb.analyze.Analysis;
+
+public class DbStore {
+ Connection m_conn;
+
+ public DbStore(Connection conn) {
+ m_conn = conn;
+ }
+
+ public boolean put(Analysis analysis) {
+ if (null == analysis) {
+ return false;
+ }
+
+
+
+ return true;
+ }
+}
--- /dev/null
+package net.jaekl.cfb.xml.messages;
+
+import org.xml.sax.Attributes;
+
+import net.jaekl.qd.xml.MissingAttributeException;
+import net.jaekl.qd.xml.ParseResult;
+import net.jaekl.qd.xml.XmlParseException;
+
+public class BugCategory extends ParseResult {
+ static final String CATEGORY = "category"; // attribute name
+ static final String DESCRIPTION = "Description";
+ static final String ABBREVIATION = "Abbreviation";
+ static final String DETAILS = "Details";
+
+ static final String TAG = "BugCategory";
+ static final String[] INTERNAL = { DESCRIPTION, ABBREVIATION, DETAILS };
+ static final Object[][] EXTERNAL = { };
+
+ String m_category;
+ String m_descr;
+ String m_abbrev;
+ String m_details;
+
+ public BugCategory(String tagName, String[] internalMemberTags, Object[][] externalParserTags)
+ {
+ super(tagName, internalMemberTags, externalParserTags);
+ m_category = m_descr = m_abbrev = m_details = "";
+ }
+
+ public String getCategory() { return m_category; }
+ public String getDescr() { return m_descr; }
+ public String getAbbrev() { return m_abbrev; }
+ public String getDetails() { return m_details; }
+
+ @Override
+ public void endContents(String uri, String localName, String qName, String chars) throws XmlParseException
+ {
+ if (DESCRIPTION.equals(localName)) {
+ m_descr = chars;
+ }
+ else if (ABBREVIATION.equals(localName)) {
+ m_abbrev = chars;
+ }
+ else if (DETAILS.equals(localName)) {
+ m_details = chars;
+ }
+ }
+
+ @Override
+ public void endExternal(String uri, String localName, String qName)
+ throws XmlParseException
+ {
+ // nothing to do
+ }
+
+ // Called once for this tag itself
+ @Override
+ public void handleMainAttributes(Attributes attr) throws MissingAttributeException {
+ m_category = this.getRequiredAttr(TAG, attr, CATEGORY);
+ }
+
+}
--- /dev/null
+package net.jaekl.cfb.xml.messages;
+
+import net.jaekl.qd.xml.MissingAttributeException;
+import net.jaekl.qd.xml.ParseResult;
+import net.jaekl.qd.xml.XmlParseException;
+
+import org.xml.sax.Attributes;
+
+public class BugPattern extends ParseResult {
+ static final String TYPE = "type";
+ static final String SHORT = "ShortDescription";
+ static final String LONG = "LongDescription";
+ static final String DETAILS = "Details";
+
+ static final String TAG = "BugPattern";
+ static final String[] INTERNAL = { SHORT, LONG, DETAILS };
+ static final Object[][] EXTERNAL = { };
+
+ String m_type;
+ String m_short;
+ String m_long;
+ String m_details;
+
+ public BugPattern(String tagName, String[] internalMemberTags, Object[][] externalParserTags)
+ {
+ super(tagName, internalMemberTags, externalParserTags);
+ m_type = m_short = m_long = m_details = "";
+ }
+
+ public String getType() { return m_type; }
+ public String getShort() { return m_short; }
+ public String getLong() { return m_long; }
+ public String getDetails() { return m_details; }
+
+ @Override
+ public void endContents(String uri, String localName, String qName, String chars) throws XmlParseException
+ {
+ if (SHORT.equals(localName)) {
+ m_short = chars;
+ }
+ else if (LONG.equals(localName)) {
+ m_long = chars;
+ }
+ else if (DETAILS.equals(localName)) {
+ m_details = chars;
+ }
+ }
+
+ @Override
+ public void endExternal(String uri, String localName, String qName) throws XmlParseException
+ {
+ // nothing to do
+ }
+
+ // Called once for this tag itself
+ @Override
+ public void handleMainAttributes(Attributes attr) throws MissingAttributeException {
+ m_type = this.getRequiredAttr(TAG, attr, TYPE);
+ }
+}
--- /dev/null
+package net.jaekl.cfb.xml.messages;
+
+import java.util.HashMap;
+
+import net.jaekl.qd.xml.ParseResult;
+import net.jaekl.qd.xml.XmlParseException;
+
+public class MessageCollection extends ParseResult {
+ static final String TAG = "MessageCollection";
+ static final String[] INTERNAL = { };
+ static final Object[][] EXTERNAL = { { BugCategory.TAG, BugCategory.class },
+ { BugPattern.TAG, BugPattern.class } };
+
+ HashMap<String, BugCategory> m_categories;
+ HashMap<String, BugPattern> m_patterns;
+
+ public MessageCollection()
+ {
+ super(TAG, INTERNAL, EXTERNAL);
+ m_categories = new HashMap<String, BugCategory>();
+ m_patterns = new HashMap<String, BugPattern>();
+ }
+
+ @Override
+ public void endContents(String uri, String localName, String qName, String chars)
+ throws XmlParseException
+ {
+ // Nothing to do
+ }
+
+ @Override
+ public void endExternal(String uri, String localName, String qName) throws XmlParseException
+ {
+ ParseResult[] prs;
+
+ prs = collectParsedChildren(BugCategory.class);
+ if (null != prs && prs.length > 0) {
+ for (ParseResult pr : prs) {
+ assert(pr instanceof BugCategory);
+ BugCategory bc = (BugCategory)pr;
+ m_categories.put(bc.getCategory(), bc);
+ }
+ }
+
+ prs = collectParsedChildren(BugPattern.class);
+ if (null != prs && prs.length > 0) {
+ for (ParseResult pr : prs) {
+ assert(pr instanceof BugPattern);
+ BugPattern bp = (BugPattern) pr;
+ m_patterns.put(bp.getType(), bp);
+ }
+ }
+ }
+
+}
--- /dev/null
+package net.jaekl.cfb.analyze;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+
+import net.jaekl.cfb.xml.BugCollection;
+import net.jaekl.cfb.xml.BugInstance;
+import net.jaekl.qd.xml.XmlParseException;
+
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class AnalysisTest {
+ private static final String UTF8 = "utf-8";
+
+ private static final String SAMPLE1_XML = ""
+ + "<?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"
+ + "<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=\"<init>\" 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"
+ + "<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"
+ + "</BugCollection>\n";
+
+ @Test
+ public void testParseSample1() throws IOException, XmlParseException, SAXException {
+ Charset utf8 = Charset.forName(UTF8);
+ BugInstance inst = null;
+
+ try ( ByteArrayInputStream bais = new ByteArrayInputStream(SAMPLE1_XML.getBytes(utf8)))
+ {
+ InputSource inputSource = new InputSource(bais);
+ Analysis analysis = new Analysis(null);
+ analysis.parse(inputSource);
+
+ assertNotNull(analysis);
+
+ BugCollection bugColl = analysis.getBugCollection();
+
+ assertNotNull(bugColl);
+ assertEquals(2, bugColl.size());
+
+ HashMap<String, BugInstance> typeMap = new HashMap<String, BugInstance>();
+ for (int idx = 0; idx < bugColl.size(); ++idx) {
+ inst = bugColl.get(idx);
+ typeMap.put(inst.getType(), inst);
+ }
+
+ inst = typeMap.get("DM_DEFAULT_ENCODING");
+ assertNotNull(inst);
+
+ inst = typeMap.get("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE");
+ assertNotNull(inst);
+ }
+ }
+}
package net.jaekl.cfb.analyze;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
-import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-
-import net.jaekl.cfb.xml.BugCollection;
-import net.jaekl.cfb.xml.BugInstance;
-import net.jaekl.qd.xml.XmlParseException;
import org.junit.Test;
-import org.xml.sax.InputSource;
public class AnalyzerTest {
- private static final String UTF8 = "utf-8";
-
- private static final String SAMPLE1_XML = ""
- + "<?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"
- + "<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=\"<init>\" 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"
- + "<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"
- + "</BugCollection>\n";
-
@Test
public void testOutputWorkFile() {
final String[][] DATA = {
File fbp = new File(datum[2]);
File expected = new File(datum[3]);
- Analyzer analyzer = new Analyzer(findBugsDir);
+ MessageMapMock mmm = new MessageMapMock();
+ mmm.mock_setFindBugsDir(findBugsDir);
+
+ Analyzer analyzer = new Analyzer(mmm);
File actual = analyzer.outputWorkFile(workDir, fbp);
assertEquals(expected.getAbsolutePath(), actual.getAbsolutePath());
}
}
- @Test
- public void testParseSample1() throws IOException, XmlParseException {
- Charset utf8 = Charset.forName(UTF8);
- BugInstance inst = null;
-
- try ( ByteArrayInputStream bais = new ByteArrayInputStream(SAMPLE1_XML.getBytes(utf8)))
- {
- InputSource inputSource = new InputSource(bais);
- Analyzer analyzer = new Analyzer(new File("."));
- Analysis analysis = analyzer.parseFbOutput(inputSource);
-
- assertNotNull(analysis);
-
- BugCollection bugColl = analysis.getBugCollection();
-
- assertNotNull(bugColl);
- assertEquals(2, bugColl.size());
-
- HashMap<String, BugInstance> typeMap = new HashMap<String, BugInstance>();
- for (int idx = 0; idx < bugColl.size(); ++idx) {
- inst = bugColl.get(idx);
- typeMap.put(inst.getType(), inst);
- }
-
- inst = typeMap.get("DM_DEFAULT_ENCODING");
- assertNotNull(inst);
-
- inst = typeMap.get("RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE");
- assertNotNull(inst);
- }
- }
}
--- /dev/null
+package net.jaekl.cfb.analyze;
+
+import java.io.File;
+
+public class MessageMapMock extends MessageMap {
+ void mock_setFindBugsDir(File fbd) {
+ this.m_findBugsDir = fbd;
+ }
+}