fixed merge

This commit is contained in:
Jeremy Long
2017-03-25 09:10:41 -04:00
18 changed files with 105 additions and 58 deletions

View File

@@ -941,13 +941,14 @@ public class Check extends Update {
} }
} }
DatabaseProperties prop = null; DatabaseProperties prop = null;
CveDB cve;
try { try {
cve = CveDB.getInstance(); final CveDB cve = CveDB.getInstance();
prop = cve.getDatabaseProperties(); prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) { } catch (DatabaseException ex) {
//TODO shouldn't this be a fatal exception //TODO shouldn't this be a fatal exception
log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG); log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
} finally {
CveDB.close();
} }
final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop); final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);

View File

@@ -285,6 +285,7 @@ public class App {
final CveDB cve = CveDB.getInstance(); final CveDB cve = CveDB.getInstance();
final DatabaseProperties prop = cve.getDatabaseProperties(); final DatabaseProperties prop = cve.getDatabaseProperties();
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop); final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
CveDB.close();
try { try {
report.generateReports(reportDirectory, outputFormat); report.generateReports(reportDirectory, outputFormat);
} catch (ReportException ex) { } catch (ReportException ex) {

View File

@@ -126,11 +126,7 @@ public class Engine implements FileFilter {
* Properly cleans up resources allocated during analysis. * Properly cleans up resources allocated during analysis.
*/ */
public void cleanup() { public void cleanup() {
try { CveDB.close();
CveDB.getInstance().closeDatabase();
} catch (DatabaseException ex) {
LOGGER.trace("Error closing the database", ex);
}
ConnectionFactory.cleanup(); ConnectionFactory.cleanup();
} }
@@ -754,6 +750,7 @@ public class Engine implements FileFilter {
if (!cve.dataExists()) { if (!cve.dataExists()) {
throw new NoDataException("No documents exist"); throw new NoDataException("No documents exist");
} }
CveDB.close();
} }
/** /**

View File

@@ -850,6 +850,8 @@ public class DependencyCheckScanAgent {
} catch (DatabaseException ex) { } catch (DatabaseException ex) {
//TODO shouldn't this throw an exception or return? //TODO shouldn't this throw an exception or return?
LOGGER.debug("Unable to retrieve DB Properties", ex); LOGGER.debug("Unable to retrieve DB Properties", ex);
} finally {
CveDB.close();
} }
final ReportGenerator r = new ReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop); final ReportGenerator r = new ReportGenerator(this.applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
try { try {

View File

@@ -182,6 +182,10 @@ public class CPEAnalyzer extends AbstractAnalyzer {
*/ */
@Override @Override
public void closeAnalyzer() { public void closeAnalyzer() {
if (cve != null) {
CveDB.close();
cve = null;
}
if (cpe != null) { if (cpe != null) {
cpe.close(); cpe.close();
cpe = null; cpe = null;

View File

@@ -68,6 +68,7 @@ public class NvdCveAnalyzer extends AbstractAnalyzer {
*/ */
@Override @Override
public void closeAnalyzer() { public void closeAnalyzer() {
CveDB.close();
cveDB = null; cveDB = null;
} }

View File

@@ -208,6 +208,14 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
} }
} }
/**
* Closes the data source.
*/
@Override
public void closeAnalyzer() {
CveDB.close();
cvedb = null;
}
/** /**
* Returns the name of the analyzer. * Returns the name of the analyzer.
* *

View File

@@ -64,6 +64,11 @@ public final class CveDB {
* Singleton instance of the CveDB. * Singleton instance of the CveDB.
*/ */
private static CveDB instance = null; private static CveDB instance = null;
/**
* Track the number of current users of the CveDB; so that if someone is
* using database another user cannot close the connection on them.
*/
private int usageCount = 0;
/** /**
* The logger. * The logger.
*/ */
@@ -84,7 +89,7 @@ public final class CveDB {
/** /**
* The prepared statements. * The prepared statements.
*/ */
private EnumMap<PreparedStatementCveDb, PreparedStatement> preparedStatements; private final EnumMap<PreparedStatementCveDb, PreparedStatement> preparedStatements = new EnumMap<>(PreparedStatementCveDb.class);
/** /**
* The enum value names must match the keys of the statements in the * The enum value names must match the keys of the statements in the
@@ -191,6 +196,10 @@ public final class CveDB {
if (instance == null) { if (instance == null) {
instance = new CveDB(); instance = new CveDB();
} }
if (!instance.isOpen()) {
instance.open();
}
instance.usageCount += 1;
return instance; return instance;
} }
@@ -202,17 +211,17 @@ public final class CveDB {
* database. * database.
*/ */
private CveDB() throws DatabaseException { private CveDB() throws DatabaseException {
openDatabase();
} }
/** /**
* Tries to determine the product name of the database. * Tries to determine the product name of the database.
* *
* @param conn the database connection
* @return the product name of the database if successful, {@code null} else * @return the product name of the database if successful, {@code null} else
*/ */
private synchronized String determineDatabaseProductName() { private static String determineDatabaseProductName(Connection conn) {
try { try {
final String databaseProductName = connection.getMetaData().getDatabaseProductName(); final String databaseProductName = conn.getMetaData().getDatabaseProductName();
LOGGER.debug("Database product: {}", databaseProductName); LOGGER.debug("Database product: {}", databaseProductName);
return databaseProductName; return databaseProductName;
} catch (SQLException se) { } catch (SQLException se) {
@@ -228,37 +237,42 @@ public final class CveDB {
* @throws DatabaseException thrown if there is an error opening the * @throws DatabaseException thrown if there is an error opening the
* database connection * database connection
*/ */
public synchronized void openDatabase() throws DatabaseException { private synchronized void open() throws DatabaseException {
if (!isOpen()) { if (!instance.isOpen()) {
connection = ConnectionFactory.getConnection(); instance.connection = ConnectionFactory.getConnection();
final String databaseProductName = determineDatabaseProductName(); final String databaseProductName = determineDatabaseProductName(instance.connection);
statementBundle = databaseProductName != null instance.statementBundle = databaseProductName != null
? ResourceBundle.getBundle("data/dbStatements", new Locale(databaseProductName)) ? ResourceBundle.getBundle("data/dbStatements", new Locale(databaseProductName))
: ResourceBundle.getBundle("data/dbStatements"); : ResourceBundle.getBundle("data/dbStatements");
preparedStatements = prepareStatements(); instance.prepareStatements();
databaseProperties = new DatabaseProperties(this); instance.databaseProperties = new DatabaseProperties(instance);
} }
} }
/** /**
* Closes the DB4O database. Close should be called on this object when it * Closes the database connection. Close should be called on this object
* is done being used. * when it is done being used.
*/ */
public synchronized void closeDatabase() { public static synchronized void close() {
if (isOpen()) { if (instance != null) {
closeStatements(); instance.usageCount -= 1;
try { if (instance.usageCount <= 0 && instance.isOpen()) {
connection.close(); instance.usageCount = 0;
} catch (SQLException ex) { instance.closeStatements();
LOGGER.error("There was an error attempting to close the CveDB, see the log for more details."); try {
LOGGER.debug("", ex); instance.connection.close();
} catch (Throwable ex) { } catch (SQLException ex) {
LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details."); LOGGER.error("There was an error attempting to close the CveDB, see the log for more details.");
LOGGER.debug("", ex); LOGGER.debug("", ex);
} catch (Throwable ex) {
LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
LOGGER.debug("", ex);
}
instance.statementBundle = null;
instance.preparedStatements.clear();
instance.databaseProperties = null;
instance.connection = null;
} }
connection = null;
preparedStatements = null;
databaseProperties = null;
} }
} }
@@ -272,16 +286,12 @@ public final class CveDB {
} }
/** /**
* Prepares all statements to be used and returns them. * Prepares all statements to be used.
* *
* @return the prepared statements
* @throws DatabaseException thrown if there is an error preparing the * @throws DatabaseException thrown if there is an error preparing the
* statements * statements
*/ */
private synchronized EnumMap<PreparedStatementCveDb, PreparedStatement> prepareStatements() private void prepareStatements() throws DatabaseException {
throws DatabaseException {
final EnumMap<PreparedStatementCveDb, PreparedStatement> result = new EnumMap<>(PreparedStatementCveDb.class);
for (PreparedStatementCveDb key : values()) { for (PreparedStatementCveDb key : values()) {
final String statementString = statementBundle.getString(key.name()); final String statementString = statementBundle.getString(key.name());
final PreparedStatement preparedStatement; final PreparedStatement preparedStatement;
@@ -294,9 +304,8 @@ public final class CveDB {
} catch (SQLException exception) { } catch (SQLException exception) {
throw new DatabaseException(exception); throw new DatabaseException(exception);
} }
result.put(key, preparedStatement); preparedStatements.put(key, preparedStatement);
} }
return result;
} }
/** /**
@@ -343,7 +352,7 @@ public final class CveDB {
@SuppressWarnings("FinalizeDeclaration") @SuppressWarnings("FinalizeDeclaration")
protected void finalize() throws Throwable { protected void finalize() throws Throwable {
LOGGER.debug("Entering finalize"); LOGGER.debug("Entering finalize");
closeDatabase(); close();
super.finalize(); super.finalize();
} }

View File

@@ -94,6 +94,7 @@ public class EngineVersionCheck implements CachedWebDataSource {
@Override @Override
public void update() throws UpdateException { public void update() throws UpdateException {
try { try {
final CveDB db = CveDB.getInstance();
final boolean autoupdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE, true); final boolean autoupdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE, true);
final boolean enabled = Settings.getBoolean(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED, true); final boolean enabled = Settings.getBoolean(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED, true);
final String original = Settings.getString(Settings.KEYS.CVE_ORIGINAL_MODIFIED_20_URL); final String original = Settings.getString(Settings.KEYS.CVE_ORIGINAL_MODIFIED_20_URL);
@@ -105,7 +106,9 @@ public class EngineVersionCheck implements CachedWebDataSource {
*/ */
if (enabled && autoupdate && original != null && original.equals(current)) { if (enabled && autoupdate && original != null && original.equals(current)) {
LOGGER.debug("Begin Engine Version Check"); LOGGER.debug("Begin Engine Version Check");
final DatabaseProperties properties = CveDB.getInstance().getDatabaseProperties();
final DatabaseProperties properties = db.getDatabaseProperties();
final long lastChecked = Long.parseLong(properties.getProperty(ENGINE_VERSION_CHECKED_ON, "0")); final long lastChecked = Long.parseLong(properties.getProperty(ENGINE_VERSION_CHECKED_ON, "0"));
final long now = System.currentTimeMillis(); final long now = System.currentTimeMillis();
updateToVersion = properties.getProperty(CURRENT_ENGINE_RELEASE, ""); updateToVersion = properties.getProperty(CURRENT_ENGINE_RELEASE, "");
@@ -124,6 +127,8 @@ public class EngineVersionCheck implements CachedWebDataSource {
throw new UpdateException("Error occurred updating database properties."); throw new UpdateException("Error occurred updating database properties.");
} catch (InvalidSettingException ex) { } catch (InvalidSettingException ex) {
LOGGER.debug("Unable to determine if autoupdate is enabled", ex); LOGGER.debug("Unable to determine if autoupdate is enabled", ex);
} finally {
CveDB.close();
} }
} }

View File

@@ -139,6 +139,7 @@ public class NvdCveUpdater implements CachedWebDataSource {
throw new UpdateException("Database Exception, unable to update the data to use the most current data.", ex); throw new UpdateException("Database Exception, unable to update the data to use the most current data.", ex);
} finally { } finally {
shutdownExecutorServices(); shutdownExecutorServices();
CveDB.close();
} }
} }
@@ -206,6 +207,8 @@ public class NvdCveUpdater implements CachedWebDataSource {
return cve.dataExists(); return cve.dataExists();
} catch (DatabaseException ex) { } catch (DatabaseException ex) {
return false; return false;
} finally {
CveDB.close();
} }
} }

View File

@@ -54,11 +54,6 @@ public abstract class BaseDBTestCase extends BaseTest {
CveDB.getInstance().openDatabase(); CveDB.getInstance().openDatabase();
} }
@AfterClass
public static void tearDownClass() throws Exception {
CveDB.getInstance().closeDatabase();
}
public static void ensureDBExists() throws Exception { public static void ensureDBExists() throws Exception {
File f = new File("./target/data/dc.h2.db"); File f = new File("./target/data/dc.h2.db");
if (f.exists() && f.isFile() && f.length() < 71680) { if (f.exists() && f.isFile() && f.length() < 71680) {

View File

@@ -73,6 +73,7 @@ public class EngineIntegrationTest extends BaseDBTestCase {
} }
CveDB cveDB = CveDB.getInstance(); CveDB cveDB = CveDB.getInstance();
DatabaseProperties dbProp = cveDB.getDatabaseProperties(); DatabaseProperties dbProp = cveDB.getDatabaseProperties();
CveDB.close();
ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), dbProp); ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), dbProp);
rg.generateReports("./target/", "ALL"); rg.generateReports("./target/", "ALL");
instance.cleanup(); instance.cleanup();

View File

@@ -166,6 +166,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
analyzer.initialize(); analyzer.initialize();
} catch (Exception e) { } catch (Exception e) {
//expected, so ignore. //expected, so ignore.
LOGGER.error("Exception", e);
} finally { } finally {
assertThat(analyzer.isEnabled(), is(false)); assertThat(analyzer.isEnabled(), is(false));
LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected."); LOGGER.info("phantom-bundle-audit is not available. Ruby Bundle Audit Analyzer is disabled as expected.");

View File

@@ -51,6 +51,8 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
instance.commit(); instance.commit();
} catch (DatabaseException | SQLException ex) { } catch (DatabaseException | SQLException ex) {
fail(ex.getMessage()); fail(ex.getMessage());
} finally {
CveDB.close();
} }
} }
@@ -64,6 +66,7 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
String product = "struts"; String product = "struts";
Set<VulnerableSoftware> result = instance.getCPEs(vendor, product); Set<VulnerableSoftware> result = instance.getCPEs(vendor, product);
assertTrue(result.size() > 5); assertTrue(result.size() > 5);
CveDB.close();
} }
/** /**
@@ -74,6 +77,7 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
CveDB instance = CveDB.getInstance(); CveDB instance = CveDB.getInstance();
Vulnerability result = instance.getVulnerability("CVE-2014-0094"); Vulnerability result = instance.getVulnerability("CVE-2014-0094");
assertEquals("The ParametersInterceptor in Apache Struts before 2.3.16.1 allows remote attackers to \"manipulate\" the ClassLoader via the class parameter, which is passed to the getClass method.", result.getDescription()); assertEquals("The ParametersInterceptor in Apache Struts before 2.3.16.1 allows remote attackers to \"manipulate\" the ClassLoader via the class parameter, which is passed to the getClass method.", result.getDescription());
CveDB.close();
} }
/** /**
@@ -110,6 +114,7 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
} }
} }
assertTrue("Expected " + expected + ", but was not identified", found); assertTrue("Expected " + expected + ", but was not identified", found);
CveDB.close();
} }
/** /**
@@ -165,5 +170,6 @@ public class CveDBIntegrationTest extends BaseDBTestCase {
identifiedVersion = new DependencyVersion("1.6.3"); identifiedVersion = new DependencyVersion("1.6.3");
results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion); results = instance.getMatchingSoftware(versions, "springsource", "spring_framework", identifiedVersion);
assertNotNull(results); assertNotNull(results);
CveDB.close();
} }
} }

View File

@@ -44,6 +44,8 @@ public class CveDBMySQLTest extends BaseTest {
} catch (DatabaseException ex) { } catch (DatabaseException ex) {
System.out.println("Unable to connect to the My SQL database; verify that the db server is running and that the schema has been generated"); System.out.println("Unable to connect to the My SQL database; verify that the db server is running and that the schema has been generated");
fail(ex.getMessage()); fail(ex.getMessage());
} finally {
CveDB.close();
} }
} }
@@ -61,6 +63,8 @@ public class CveDBMySQLTest extends BaseTest {
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("Unable to access the My SQL database; verify that the db server is running and that the schema has been generated"); System.out.println("Unable to access the My SQL database; verify that the db server is running and that the schema has been generated");
throw ex; throw ex;
} finally {
CveDB.close();
} }
} }
@@ -77,6 +81,8 @@ public class CveDBMySQLTest extends BaseTest {
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("Unable to access the My SQL database; verify that the db server is running and that the schema has been generated"); System.out.println("Unable to access the My SQL database; verify that the db server is running and that the schema has been generated");
throw ex; throw ex;
} finally {
CveDB.close();
} }
} }
} }

View File

@@ -41,6 +41,7 @@ public class DatabasePropertiesIntegrationTest extends BaseDBTestCase {
assertNotNull(instance); assertNotNull(instance);
//no exception means the call worked... whether or not it is empty depends on if the db is new //no exception means the call worked... whether or not it is empty depends on if the db is new
//assertEquals(expResult, result); //assertEquals(expResult, result);
CveDB.close();
} }
/** /**
@@ -59,6 +60,7 @@ public class DatabasePropertiesIntegrationTest extends BaseDBTestCase {
instance = cveDB.reloadProperties(); instance = cveDB.reloadProperties();
long results = Long.parseLong(instance.getProperty("NVD CVE " + key)); long results = Long.parseLong(instance.getProperty("NVD CVE " + key));
assertEquals(expected, results); assertEquals(expected, results);
CveDB.close();
} }
/** /**
@@ -73,6 +75,7 @@ public class DatabasePropertiesIntegrationTest extends BaseDBTestCase {
String expResult = "default"; String expResult = "default";
String result = instance.getProperty(key, defaultValue); String result = instance.getProperty(key, defaultValue);
assertEquals(expResult, result); assertEquals(expResult, result);
CveDB.close();
} }
/** /**
@@ -87,6 +90,7 @@ public class DatabasePropertiesIntegrationTest extends BaseDBTestCase {
double version = Double.parseDouble(result); double version = Double.parseDouble(result);
assertTrue(version >= 2.8); assertTrue(version >= 2.8);
assertTrue(version <= 10); assertTrue(version <= 10);
CveDB.close();
} }
/** /**
@@ -98,5 +102,6 @@ public class DatabasePropertiesIntegrationTest extends BaseDBTestCase {
DatabaseProperties instance = cveDB.getDatabaseProperties(); DatabaseProperties instance = cveDB.getDatabaseProperties();
Properties result = instance.getProperties(); Properties result = instance.getProperties();
assertTrue(result.size() > 0); assertTrue(result.size() > 0);
CveDB.close();
} }
} }

View File

@@ -149,6 +149,7 @@ public class ReportGeneratorIntegrationTest extends BaseDBTestCase {
ReportGenerator generator = new ReportGenerator("Test Report", engine.getDependencies(), engine.getAnalyzers(), dbProp); ReportGenerator generator = new ReportGenerator("Test Report", engine.getDependencies(), engine.getAnalyzers(), dbProp);
generator.generateReport(templateName, writeTo); generator.generateReport(templateName, writeTo);
CveDB.close();
engine.cleanup(); engine.cleanup();

View File

@@ -1017,6 +1017,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
} }
} }
final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop); final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
CveDB.close();
try { try {
r.generateReports(outputDir.getAbsolutePath(), format); r.generateReports(outputDir.getAbsolutePath(), format);
} catch (ReportException ex) { } catch (ReportException ex) {