diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTask.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTask.java index 83d85d0fe..2e65813ef 100644 --- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTask.java +++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/DependencyCheckTask.java @@ -741,47 +741,57 @@ public class DependencyCheckTask extends Task { validateConfiguration(); populateSettings(); - final Engine engine = new Engine(); - - for (Resource resource : path) { - final FileProvider provider = resource.as(FileProvider.class); - if (provider != null) { - final File file = provider.getFile(); - if (file != null && file.exists()) { - engine.scan(file); - } - } - } + Engine engine = null; try { - engine.analyzeDependencies(); - DatabaseProperties prop = null; - CveDB cve = null; - try { - cve = new CveDB(); - cve.open(); - prop = cve.getDatabaseProperties(); - } catch (DatabaseException ex) { - Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex); - } finally { - if (cve != null) { - cve.close(); + engine = new Engine(); + + for (Resource resource : path) { + final FileProvider provider = resource.as(FileProvider.class); + if (provider != null) { + final File file = provider.getFile(); + if (file != null && file.exists()) { + engine.scan(file); + } } } - final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop); - reporter.generateReports(reportOutputDirectory, reportFormat); + try { + engine.analyzeDependencies(); + DatabaseProperties prop = null; + CveDB cve = null; + try { + cve = new CveDB(); + cve.open(); + prop = cve.getDatabaseProperties(); + } catch (DatabaseException ex) { + Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex); + } finally { + if (cve != null) { + cve.close(); + } + } + final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop); + reporter.generateReports(reportOutputDirectory, reportFormat); - if (this.failBuildOnCVSS <= 10) { - checkForFailure(engine.getDependencies()); + if (this.failBuildOnCVSS <= 10) { + checkForFailure(engine.getDependencies()); + } + if (this.showSummary) { + showSummary(engine.getDependencies()); + } + } catch (IOException ex) { + Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to generate dependency-check report", ex); + throw new BuildException("Unable to generate dependency-check report", ex); + } catch (Exception ex) { + Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "An exception occurred; unable to continue task", ex); + throw new BuildException("An exception occurred; unable to continue task", ex); } - if (this.showSummary) { - showSummary(engine.getDependencies()); + } catch (DatabaseException ex) { + Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); + Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "", ex); + } finally { + if (engine != null) { + engine.cleanup(); } - } catch (IOException ex) { - Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to generate dependency-check report", ex); - throw new BuildException("Unable to generate dependency-check report", ex); - } catch (Exception ex) { - Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "An exception occurred; unable to continue task", ex); - throw new BuildException("An exception occurred; unable to continue task", ex); } } diff --git a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java index b2d186775..6afc096b0 100644 --- a/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java +++ b/dependency-check-cli/src/main/java/org/owasp/dependencycheck/App.java @@ -98,36 +98,46 @@ public class App { * @param files the files/directories to scan */ private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, String extraExtensions) { - final Engine scanner = new Engine(); - - for (String file : files) { - scanner.scan(file); - } - - scanner.analyzeDependencies(); - final List dependencies = scanner.getDependencies(); - DatabaseProperties prop = null; - CveDB cve = null; + Engine scanner = null; try { - cve = new CveDB(); - cve.open(); - prop = cve.getDatabaseProperties(); - } catch (DatabaseException ex) { - Logger.getLogger(App.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex); - } finally { - if (cve != null) { - cve.close(); + scanner = new Engine(); + + for (String file : files) { + scanner.scan(file); + } + + scanner.analyzeDependencies(); + final List dependencies = scanner.getDependencies(); + DatabaseProperties prop = null; + CveDB cve = null; + try { + cve = new CveDB(); + cve.open(); + prop = cve.getDatabaseProperties(); + } catch (DatabaseException ex) { + Logger.getLogger(App.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex); + } finally { + if (cve != null) { + cve.close(); + } + } + final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop); + try { + report.generateReports(reportDirectory, outputFormat); + } catch (IOException ex) { + Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an IO error while attempting to generate the report."); + Logger.getLogger(App.class.getName()).log(Level.FINE, null, ex); + } catch (Exception ex) { + Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an error while attempting to generate the report."); + Logger.getLogger(App.class.getName()).log(Level.FINE, null, ex); + } + } catch (DatabaseException ex) { + Logger.getLogger(App.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); + Logger.getLogger(App.class.getName()).log(Level.FINE, "", ex); + } finally { + if (scanner != null) { + scanner.cleanup(); } - } - final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop); - try { - report.generateReports(reportDirectory, outputFormat); - } catch (IOException ex) { - Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an IO error while attempting to generate the report."); - Logger.getLogger(App.class.getName()).log(Level.INFO, null, ex); - } catch (Exception ex) { - Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an error while attempting to generate the report."); - Logger.getLogger(App.class.getName()).log(Level.INFO, null, ex); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java index 7263b2bc1..3915d5a11 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/Engine.java @@ -32,6 +32,7 @@ import org.owasp.dependencycheck.analyzer.AnalyzerService; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex; import org.owasp.dependencycheck.data.cpe.IndexException; +import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; import org.owasp.dependencycheck.data.nvdcve.CveDB; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.data.update.CachedWebDataSource; @@ -67,11 +68,14 @@ public class Engine { /** * Creates a new Engine. + * + * @throws DatabaseException thrown if there is an error connecting to the database */ - public Engine() { + public Engine() throws DatabaseException { this.extensions = new HashSet(); this.dependencies = new ArrayList(); this.analyzers = new EnumMap>(AnalysisPhase.class); + ConnectionFactory.initialize(); boolean autoUpdate = true; try { @@ -85,6 +89,13 @@ public class Engine { loadAnalyzers(); } + /** + * Properly cleans up resources allocated during analysis. + */ + public void cleanup() { + ConnectionFactory.cleanup(); + } + /** * Loads the analyzers specified in the configuration file (or system properties). */ @@ -291,7 +302,7 @@ public class Engine { } catch (Exception ex) { final String msg = String.format("Exception occurred initializing %s.", a.getName()); Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, msg); - Logger.getLogger(Engine.class.getName()).log(Level.INFO, null, ex); + Logger.getLogger(Engine.class.getName()).log(Level.FINE, null, ex); try { a.close(); } catch (Exception ex1) { @@ -326,7 +337,7 @@ public class Engine { Logger.getLogger(Engine.class.getName()).log(Level.FINE, "", ex); } catch (Throwable ex) { final String axMsg = String.format("An unexpected error occurred during analysis of '%s'", d.getActualFilePath()); - final AnalysisException ax = new AnalysisException(axMsg, ex); + //final AnalysisException ax = new AnalysisException(axMsg, ex); Logger.getLogger(Engine.class.getName()).log(Level.WARNING, axMsg); Logger.getLogger(Engine.class.getName()).log(Level.FINE, "", ex); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java index 5c80345e7..c9e906f23 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzer.java @@ -95,9 +95,9 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer { private static final Set EXTENSIONS = newHashSet("tar", "gz", "tgz"); static { - String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); + final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS); if (additionalZipExt != null) { - HashSet ext = new HashSet(Arrays.asList(additionalZipExt)); + final HashSet ext = new HashSet(Arrays.asList(additionalZipExt)); ZIPPABLES.addAll(ext); } EXTENSIONS.addAll(ZIPPABLES); @@ -263,7 +263,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer { try { fis = new FileInputStream(archive); } catch (FileNotFoundException ex) { - Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.INFO, null, ex); + Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex); throw new AnalysisException("Archive file was not found.", ex); } final String archiveExt = org.owasp.dependencycheck.utils.FileUtils.getFileExtension(archive.getName()).toLowerCase(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java index 626cb49e6..063a89f7f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AssemblyAnalyzer.java @@ -17,7 +17,6 @@ */ package org.owasp.dependencycheck.analyzer; -import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -33,6 +32,7 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.owasp.dependencycheck.Engine; +import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Evidence; @@ -172,7 +172,7 @@ public class AssemblyAnalyzer extends AbstractAnalyzer { grokAssemblyExe = tempFile; // Set the temp file to get deleted when we're done grokAssemblyExe.deleteOnExit(); - LOG.log(Level.INFO, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath()); + LOG.log(Level.FINE, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath()); } catch (IOException ioe) { LOG.log(Level.WARNING, "Could not extract GrokAssembly.exe: {0}", ioe.getMessage()); throw new AnalysisException("Could not extract GrokAssembly.exe", ioe); @@ -201,13 +201,15 @@ public class AssemblyAnalyzer extends AbstractAnalyzer { final XPath xpath = XPathFactory.newInstance().newXPath(); final String error = xpath.evaluate("/assembly/error", doc); if (p.exitValue() != 1 || error == null || "".equals(error)) { - LOG.warning("GrokAssembly.exe is not working properly"); + LOG.warning("An error occured with the .NET AssemblyAnalyzer, please see the log for more details."); + LOG.fine("GrokAssembly.exe is not working properly"); grokAssemblyExe = null; - throw new AnalysisException("Could not execute GrokAssembly"); + throw new AnalysisException("Could not execute .NET AssemblyAnalyzer"); } } catch (Exception e) { - LOG.warning("Could not execute GrokAssembly " + e.getMessage()); - throw new AnalysisException("Could not execute GrokAssembly", e); + LOG.warning("An error occured with the .NET AssemblyAnalyzer, please see the log for more details."); + LOG.fine("Could not execute GrokAssembly " + e.getMessage()); + throw new AnalysisException("An error occured with the .NET AssemblyAnalyzer", e); } builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java index 3138154ce..bdfc22cb9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/JarAnalyzer.java @@ -261,7 +261,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer { jar = new JarFile(dependency.getActualFilePath()); } catch (IOException ex) { final String msg = String.format("Unable to read JarFile '%s'.", dependency.getActualFilePath()); - final AnalysisException ax = new AnalysisException(msg, ex); + //final AnalysisException ax = new AnalysisException(msg, ex); Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg); Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex); return false; @@ -271,9 +271,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer { pomEntries = retrievePomListing(jar); } catch (IOException ex) { final String msg = String.format("Unable to read Jar file entries in '%s'.", dependency.getActualFilePath()); - final AnalysisException ax = new AnalysisException(msg, ex); + //final AnalysisException ax = new AnalysisException(msg, ex); Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg); - Logger.getLogger(JarAnalyzer.class.getName()).log(Level.INFO, msg, ex); + Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, msg, ex); return false; } if (pomEntries.isEmpty()) { @@ -314,7 +314,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer { } catch (AnalysisException ex) { final String msg = String.format("An error occured while analyzing '%s'.", dependency.getActualFilePath()); Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg); - Logger.getLogger(JarAnalyzer.class.getName()).log(Level.INFO, "", ex); + Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, "", ex); } } return foundSomething; @@ -768,7 +768,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer { } else { versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM); } - } else if (key.equals("build-id")) { + } else if ("build-id".equals(key)) { int pos = value.indexOf('('); if (pos >= 0) { value = value.substring(0, pos - 1); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/package-info.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/package-info.java new file mode 100644 index 000000000..397aafb53 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/package-info.java @@ -0,0 +1,12 @@ +/** + * + * + * org.owasp.dependencycheck.analyzer.exception + * + * + *

+ * A collection of exception classes used within the analyzers.

+ * + * + */ +package org.owasp.dependencycheck.analyzer.exception; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java index 93101e417..4c8851caa 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/CpeMemoryIndex.java @@ -18,10 +18,9 @@ package org.owasp.dependencycheck.data.cpe; import java.io.IOException; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.lucene.analysis.Analyzer; @@ -45,6 +44,8 @@ import org.owasp.dependencycheck.data.lucene.FieldAnalyzer; import org.owasp.dependencycheck.data.lucene.LuceneUtils; import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer; import org.owasp.dependencycheck.data.nvdcve.CveDB; +import org.owasp.dependencycheck.data.nvdcve.DatabaseException; +import org.owasp.dependencycheck.utils.Pair; /** * An in memory lucene index that contains the vendor/product combinations from the CPE (application) identifiers within @@ -210,7 +211,7 @@ public final class CpeMemoryIndex { } /** - * Builds the lucene index based off of the data within the CveDB. + * Builds the CPE Lucene Index based off of the data within the CveDB. * * @param cve the data base containing the CPE data * @throws IndexException thrown if there is an issue creating the index @@ -222,15 +223,12 @@ public final class CpeMemoryIndex { analyzer = createIndexingAnalyzer(); final IndexWriterConfig conf = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer); indexWriter = new IndexWriter(index, conf); - final ResultSet rs = cve.getVendorProductList(); - if (rs == null) { - throw new IndexException("No data exists"); - } try { - while (rs.next()) { - saveEntry(rs.getString(1), rs.getString(2), indexWriter); + final Set> data = cve.getVendorProductList(); + for (Pair pair : data) { + saveEntry(pair.getLeft(), pair.getRight(), indexWriter); } - } catch (SQLException ex) { + } catch (DatabaseException ex) { Logger.getLogger(CpeMemoryIndex.class.getName()).log(Level.FINE, null, ex); throw new IndexException("Error reading CPE data", ex); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/UrlTokenizingFilter.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/UrlTokenizingFilter.java index 03f4c0a63..e4cf05d96 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/UrlTokenizingFilter.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/UrlTokenizingFilter.java @@ -67,7 +67,7 @@ public final class UrlTokenizingFilter extends AbstractTokenizingFilter { final List data = UrlStringUtils.extractImportantUrlData(part); tokens.addAll(data); } catch (MalformedURLException ex) { - Logger.getLogger(UrlTokenizingFilter.class.getName()).log(Level.INFO, "error parsing " + part, ex); + Logger.getLogger(UrlTokenizingFilter.class.getName()).log(Level.FINE, "error parsing " + part, ex); tokens.add(part); } } else { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java index f4525c787..b94d9cb2a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/ConnectionFactory.java @@ -24,6 +24,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.sql.CallableStatement; import java.sql.Connection; +import java.sql.Driver; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; @@ -50,6 +51,22 @@ public final class ConnectionFactory { * Resource location for SQL file used to create the database schema. */ public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql"; + /** + * The database driver used to connect to the database. + */ + private static Driver driver = null; + /** + * The database connection string. + */ + private static String connectionString = null; + /** + * The username to connect to the database. + */ + private static String userName = null; + /** + * The password for the database. + */ + private static String password = null; /** * Private constructor for this factory class; no instance is ever needed. @@ -58,64 +75,134 @@ public final class ConnectionFactory { } /** - * Constructs a new database connection object per the database configuration. This will load the appropriate - * database driver, via the DriverManager, if configured. + * Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be + * made successfully. * - * @return a database connection object - * @throws DatabaseException thrown if there is an exception loading the database connection + * @throws DatabaseException thrown if we are unable to connect to the database */ - public static Connection getConnection() throws DatabaseException { + public static synchronized void initialize() throws DatabaseException { + //this only needs to be called once. + if (connectionString != null) { + return; + } + + //load the driver if necessary + final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, ""); + if (!driverName.isEmpty()) { //likely need to load the correct driver + Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver: {0}", driverName); + final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, ""); + try { + if (!driverPath.isEmpty()) { + Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver from: {0}", driverPath); + driver = DriverLoader.load(driverName, driverPath); + } else { + driver = DriverLoader.load(driverName); + } + } catch (DriverLoadException ex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to load database driver", ex); + throw new DatabaseException("Unable to load database driver"); + } + } + userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser"); + //yes, yes - hard-coded password - only if there isn't one in the properties file. + password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!"); + try { + connectionString = getConnectionString(); + } catch (IOException ex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, + "Unable to retrieve the database connection string", ex); + throw new DatabaseException("Unable to retrieve the database connection string"); + } + boolean shouldCreateSchema = false; + try { + if (connectionString.startsWith("jdbc:h2:file:")) { //H2 + shouldCreateSchema = !dbSchemaExists(); + Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Need to create DB Structure: {0}", shouldCreateSchema); + } + } catch (IOException ioex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to verify database exists", ioex); + throw new DatabaseException("Unable to verify database exists"); + } + Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading database connection"); + Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Connection String: {0}", connectionString); + Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Database User: {0}", userName); + Connection conn = null; try { - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading database connection"); - - final String connStr = getConnectionString(); - final String user = Settings.getString(Settings.KEYS.DB_USER, "dcuser"); - //yes, yes - hard-coded password - only if there isn't one in the properties file. - final String pass = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!"); - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Connection String: {0}", connStr); - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Database User: {0}", user); - boolean createTables = false; - if (connStr.startsWith("jdbc:h2:file:")) { //H2 - createTables = needToCreateDatabaseStructure(); - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Need to create DB Structure: {0}", createTables); - } - final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, ""); - if (!driverName.isEmpty()) { //likely need to load the correct driver - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver: {0}", driverName); - final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, ""); - if (!driverPath.isEmpty()) { //ugh, driver is not on classpath? - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver from: {0}", driverPath); - DriverLoader.load(driverName, driverPath); - } else { - DriverLoader.load(driverName); + conn = DriverManager.getConnection(connectionString, userName, password); + } catch (SQLException ex) { + if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) { + connectionString = connectionString.replace("AUTO_SERVER=TRUE;", ""); + try { + conn = DriverManager.getConnection(connectionString, userName, password); + Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString); + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, + "Unable to start the database in server mode; reverting to single user mode"); + } catch (SQLException sqlex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to connect to the database", ex); + throw new DatabaseException("Unable to connect to the database"); } + } else { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to connect to the database", ex); + throw new DatabaseException("Unable to connect to the database"); } - //JDBC4 drivers don't need this call. - //Class.forName("org.h2.Driver"); - conn = DriverManager.getConnection(connStr, user, pass); - if (createTables) { + if (shouldCreateSchema) { try { createTables(conn); - } catch (DatabaseException ex) { - Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex); + } catch (DatabaseException dex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, dex); throw new DatabaseException("Unable to create the database structure"); } } else { try { ensureSchemaVersion(conn); - } catch (DatabaseException ex) { - Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex); + } catch (DatabaseException dex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, dex); throw new DatabaseException("Database schema does not match this version of dependency-check"); } } - } catch (IOException ex) { - Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex); - throw new DatabaseException("Unable to load database"); - } catch (DriverLoadException ex) { - Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex); - throw new DatabaseException("Unable to load database driver"); + } finally { + if (conn != null) { + try { + conn.close(); + } catch (SQLException ex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "An error occured closing the connection", ex); + } + } + } + } + + /** + * Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is + * unregistered prior to the finalize method being called as during shutdown the class loader used to load the + * driver may be unloaded prior to the driver being de-registered. + */ + public static synchronized void cleanup() { + if (driver != null) { + try { + DriverManager.deregisterDriver(driver); + } catch (SQLException ex) { + Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "An error occured unloading the databse driver", ex); + } + driver = null; + } + connectionString = null; + userName = null; + password = null; + } + + /** + * Constructs a new database connection object per the database configuration. + * + * @return a database connection object + * @throws DatabaseException thrown if there is an exception loading the database connection + */ + public static Connection getConnection() throws DatabaseException { + initialize(); + Connection conn = null; + try { + conn = DriverManager.getConnection(connectionString, userName, password); } catch (SQLException ex) { Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex); throw new DatabaseException("Unable to connect to the database"); @@ -164,11 +251,11 @@ public final class ConnectionFactory { * @return true if the H2 database file does not exist; otherwise false * @throws IOException thrown if the data directory does not exist and cannot be created */ - private static boolean needToCreateDatabaseStructure() throws IOException { + private static boolean dbSchemaExists() throws IOException { final File dir = getDataDirectory(); final String name = String.format("cve.%s.h2.db", DB_SCHEMA_VERSION); final File file = new File(dir, name); - return !file.exists(); + return file.exists(); } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index 462c20a52..5ccbf08a9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -38,6 +38,7 @@ import org.owasp.dependencycheck.dependency.VulnerableSoftware; import org.owasp.dependencycheck.utils.DBUtils; import org.owasp.dependencycheck.utils.DependencyVersion; import org.owasp.dependencycheck.utils.DependencyVersionUtil; +import org.owasp.dependencycheck.utils.Pair; /** * The database holding information about the NVD CVE data. @@ -295,19 +296,27 @@ public class CveDB { /** * Returns the entire list of vendor/product combinations. * - * @return the entire list of vendor/product combinations. + * @return the entire list of vendor/product combinations + * @throws DatabaseException thrown when there is an error retrieving the data from the DB */ - public ResultSet getVendorProductList() { + public Set> getVendorProductList() throws DatabaseException { + HashSet data = new HashSet>(); ResultSet rs = null; + PreparedStatement ps = null; try { - final PreparedStatement ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST); + ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST); rs = ps.executeQuery(); + while (rs.next()) { + data.add(new Pair(rs.getString(1), rs.getString(2))); + } } catch (SQLException ex) { final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details."; - Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg); - Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex); - } // can't close the statement in the PS as the resultset is returned, closing PS would close the resultset - return rs; + throw new DatabaseException(msg, ex); + } finally { + DBUtils.closeResultSet(rs); + DBUtils.closeStatement(ps); + } + return data; } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoader.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoader.java index 07ab2e46f..71e135b70 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoader.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoader.java @@ -47,11 +47,12 @@ public final class DriverLoader { * Loads the specified class using the system class loader and registers the driver with the driver manager. * * @param className the fully qualified name of the desired class + * @return the loaded Driver * @throws DriverLoadException thrown if the driver cannot be loaded */ - public static void load(String className) throws DriverLoadException { + public static Driver load(String className) throws DriverLoadException { final ClassLoader loader = DriverLoader.class.getClassLoader(); //ClassLoader.getSystemClassLoader(); - load(className, loader); + return load(className, loader); } /** @@ -64,9 +65,10 @@ public final class DriverLoader { * @param className the fully qualified name of the desired class * @param pathToDriver the path to the JAR file containing the driver; note, this can be a semi-colon separated list * of paths + * @return the loaded Driver * @throws DriverLoadException thrown if the driver cannot be loaded */ - public static void load(String className, String pathToDriver) throws DriverLoadException { + public static Driver load(String className, String pathToDriver) throws DriverLoadException { final URLClassLoader parent = (URLClassLoader) ClassLoader.getSystemClassLoader(); final ArrayList urls = new ArrayList(); final String[] paths = pathToDriver.split(File.pathSeparator); @@ -103,7 +105,7 @@ public final class DriverLoader { } }); - load(className, loader); + return load(className, loader); } /** @@ -111,15 +113,18 @@ public final class DriverLoader { * * @param className the fully qualified name of the desired class * @param loader the class loader to use when loading the driver + * @return the loaded Driver * @throws DriverLoadException thrown if the driver cannot be loaded */ - private static void load(String className, ClassLoader loader) throws DriverLoadException { + private static Driver load(String className, ClassLoader loader) throws DriverLoadException { try { final Class c = Class.forName(className, true, loader); //final Class c = loader.loadClass(className); final Driver driver = (Driver) c.newInstance(); + final Driver shim = new DriverShim(driver); //using the DriverShim to get around the fact that the DriverManager won't register a driver not in the base class path - DriverManager.registerDriver(new DriverShim(driver)); + DriverManager.registerDriver(shim); + return shim; } catch (ClassNotFoundException ex) { final String msg = String.format("Unable to load database driver '%s'", className); Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java index 354d1f59f..9c4d63ec1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/EvidenceCollection.java @@ -360,7 +360,7 @@ public class EvidenceCollection implements Iterable { final List data = UrlStringUtils.extractImportantUrlData(part); sb.append(' ').append(StringUtils.join(data, ' ')); } catch (MalformedURLException ex) { - Logger.getLogger(EvidenceCollection.class.getName()).log(Level.INFO, "error parsing " + part, ex); + Logger.getLogger(EvidenceCollection.class.getName()).log(Level.FINE, "error parsing " + part, ex); sb.append(' ').append(part); } } else { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java index ff5c48f96..5ea80f944 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java @@ -160,7 +160,7 @@ public final class FileUtils { try { fis = new FileInputStream(archive); } catch (FileNotFoundException ex) { - Logger.getLogger(FileUtils.class.getName()).log(Level.INFO, null, ex); + Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex); throw new ExtractionException("Archive file was not found.", ex); } zis = new ZipInputStream(new BufferedInputStream(fis)); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Pair.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Pair.java new file mode 100644 index 000000000..eee908a09 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Pair.java @@ -0,0 +1,124 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2014 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.utils; + +/** + * A generic pair of elements. + * + * @author Jeremy Long + */ +public class Pair { + + /** + * Constructs a new empty pair. + */ + public Pair() { + } + + /** + * Constructs a new Pair with the given left and right values. + * + * @param left the value for the left pair + * @param right the value for the right pair + */ + public Pair(K left, V right) { + this.left = left; + this.right = right; + } + /** + * The left element of the pair. + */ + private K left = null; + + /** + * Get the value of left + * + * @return the value of left + */ + public K getLeft() { + return left; + } + + /** + * Set the value of left + * + * @param left new value of left + */ + public void setLeft(K left) { + this.left = left; + } + /** + * The right element of the pair. + */ + private V right = null; + + /** + * Get the value of right + * + * @return the value of right + */ + public V getRight() { + return right; + } + + /** + * Set the value of right + * + * @param right new value of right + */ + public void setRight(V right) { + this.right = right; + } + + /** + * Generates the hash code using the hash codes from the contained objects. + * + * @return the hash code of the Pair + */ + @Override + public int hashCode() { + int hash = 3; + hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0); + hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0); + return hash; + } + + /** + * Determines the equality of this and the provided object. + * + * @param obj the {@link Object} to check for equality to this + * @return true if this and the provided {@link Object} are equal; otherwise false + */ + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Pair other = (Pair) obj; + if (this.left != other.left && (this.left == null || !this.left.equals(other.left))) { + return false; + } + if (this.right != other.right && (this.right == null || !this.right.equals(other.right))) { + return false; + } + return true; + } +} diff --git a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer index e06c7230d..d752f4294 100644 --- a/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer +++ b/dependency-check-core/src/main/resources/META-INF/services/org.owasp.dependencycheck.analyzer.Analyzer @@ -10,3 +10,4 @@ org.owasp.dependencycheck.analyzer.NvdCveAnalyzer org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer org.owasp.dependencycheck.analyzer.NexusAnalyzer org.owasp.dependencycheck.analyzer.NuspecAnalyzer +org.owasp.dependencycheck.analyzer.AssemblyAnalyzer \ No newline at end of file diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java index 4a4319f70..1b2b64b4c 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIntegrationTest.java @@ -69,5 +69,6 @@ public class EngineIntegrationTest { ReportGenerator rg = new ReportGenerator("DependencyCheck", instance.getDependencies(), instance.getAnalyzers(), dbProp); rg.generateReports("./target/", "ALL"); + instance.cleanup(); } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java index 554923f0c..b9a3adced 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerTest.java @@ -160,6 +160,8 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase { instance.analyze(dependency, engine); int ending_size = engine.getDependencies().size(); + engine.cleanup(); + assertTrue(initial_size < ending_size); } finally { @@ -186,6 +188,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase { int initial_size = engine.getDependencies().size(); instance.analyze(dependency, engine); int ending_size = engine.getDependencies().size(); + engine.cleanup(); assertTrue(initial_size < ending_size); @@ -214,7 +217,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase { engine.scan(file); engine.analyzeDependencies(); int ending_size = engine.getDependencies().size(); - + engine.cleanup(); assertTrue(initial_size < ending_size); } finally { @@ -261,7 +264,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase { engine.scan(file); engine.analyzeDependencies(); int ending_size = engine.getDependencies().size(); - + engine.cleanup(); assertTrue(initial_size < ending_size); } finally { @@ -292,6 +295,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase { // } // assertTrue(failed); int ending_size = engine.getDependencies().size(); + engine.cleanup(); assertEquals(initial_size, ending_size); } finally { instance.close(); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DriverLoaderTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DriverLoaderTest.java index 311e7f0eb..410fba3e0 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DriverLoaderTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nvdcve/DriverLoaderTest.java @@ -59,7 +59,14 @@ public class DriverLoaderTest { @Test public void testLoad_String() throws Exception { String className = "org.h2.Driver"; - DriverLoader.load(className); + Driver d = null; + try { + d = DriverLoader.load(className); + } finally { + if (d != null) { + DriverManager.deregisterDriver(d); + } + } } /** @@ -68,7 +75,7 @@ public class DriverLoaderTest { @Test(expected = DriverLoadException.class) public void testLoad_String_ex() throws Exception { String className = "bad.Driver"; - DriverLoader.load(className); + Driver d = DriverLoader.load(className); } /** @@ -82,9 +89,16 @@ public class DriverLoaderTest { File driver = new File(testClassPath, "../../src/test/resources/mysql-connector-java-5.1.27-bin.jar"); assertTrue("MySQL Driver JAR file not found in src/test/resources?", driver.isFile()); - DriverLoader.load(className, driver.getAbsolutePath()); - Driver d = DriverManager.getDriver("jdbc:mysql://localhost:3306/dependencycheck"); - assertNotNull(d); + Driver d = null; + try { + d = DriverLoader.load(className, driver.getAbsolutePath()); + d = DriverManager.getDriver("jdbc:mysql://localhost:3306/dependencycheck"); + assertNotNull(d); + } finally { + if (d != null) { + DriverManager.deregisterDriver(d); + } + } } /** @@ -99,7 +113,14 @@ public class DriverLoaderTest { final File dir2 = new File(testClassPath, "../../src/test/resources/"); final String paths = String.format("%s" + File.pathSeparator + "%s", dir1.getAbsolutePath(), dir2.getAbsolutePath()); - DriverLoader.load(className, paths); + Driver d = null; + try { + d = DriverLoader.load(className, paths); + } finally { + if (d != null) { + DriverManager.deregisterDriver(d); + } + } } /** @@ -113,7 +134,7 @@ public class DriverLoaderTest { File driver = new File(testClassPath, "../../src/test/resources/mysql-connector-java-5.1.27-bin.jar"); assertTrue("MySQL Driver JAR file not found in src/test/resources?", driver.isFile()); - DriverLoader.load(className, driver.getAbsolutePath()); + Driver d = DriverLoader.load(className, driver.getAbsolutePath()); } /** @@ -125,6 +146,6 @@ public class DriverLoaderTest { //we know this is in target/test-classes File testClassPath = (new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath())).getParentFile(); File driver = new File(testClassPath, "../../src/test/bad/mysql-connector-java-5.1.27-bin.jar"); - DriverLoader.load(className, driver.getAbsolutePath()); + Driver d = DriverLoader.load(className, driver.getAbsolutePath()); } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorTest.java index 09b126540..dd0d7da50 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/reporting/ReportGeneratorTest.java @@ -150,6 +150,8 @@ public class ReportGeneratorTest { ReportGenerator generator = new ReportGenerator("Test Report", engine.getDependencies(), engine.getAnalyzers(), dbProp); generator.generateReport(templateName, writeTo); + engine.cleanup(); + InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/DependencyCheck.xsd"); StreamSource xsdSource = new StreamSource(xsdStream); StreamSource xmlSource = new StreamSource(new File(writeTo)); diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java index cf4174215..31831e96a 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/DependencyCheckMojo.java @@ -280,30 +280,37 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR * * @return the Engine used to scan the dependencies. */ - private Engine executeDependencyCheck() { + private Engine executeDependencyCheck() throws DatabaseException { final InputStream in = DependencyCheckMojo.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE); LogUtils.prepareLogger(in, logFile); populateSettings(); - final Engine engine = new Engine(); - final Set artifacts = project.getArtifacts(); - for (Artifact a : artifacts) { - if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) { - continue; - } + Engine engine = null; + try { + engine = new Engine(); + final Set artifacts = project.getArtifacts(); + for (Artifact a : artifacts) { + if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) { + continue; + } - if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) { - continue; - } + if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) { + continue; + } - if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) { - continue; - } + if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) { + continue; + } - engine.scan(a.getFile().getAbsolutePath()); + engine.scan(a.getFile().getAbsolutePath()); + } + engine.analyzeDependencies(); + } finally { + if (engine != null) { + engine.cleanup(); + } } - engine.analyzeDependencies(); return engine; } @@ -794,13 +801,23 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR * @throws MojoFailureException thrown if a CVSS score is found that is higher then the configured level */ public void execute() throws MojoExecutionException, MojoFailureException { - final Engine engine = executeDependencyCheck(); - generateExternalReports(engine); - if (this.showSummary) { - showSummary(engine.getDependencies()); - } - if (this.failBuildOnCVSS <= 10) { - checkForFailure(engine.getDependencies()); + Engine engine = null; + try { + engine = executeDependencyCheck(); + generateExternalReports(engine); + if (this.showSummary) { + showSummary(engine.getDependencies()); + } + if (this.failBuildOnCVSS <= 10) { + checkForFailure(engine.getDependencies()); + } + } catch (DatabaseException ex) { + Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); + Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.FINE, "", ex); + } finally { + if (engine != null) { + engine.cleanup(); + } } } @@ -825,8 +842,18 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR * @throws MavenReportException if a maven report exception occurs */ public void generate(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException { - final Engine engine = executeDependencyCheck(); - generateMavenSiteReport(engine, sink); + Engine engine = null; + try { + engine = executeDependencyCheck(); + generateMavenSiteReport(engine, sink); + } catch (DatabaseException ex) { + Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped"); + Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.FINE, "", ex); + } finally { + if (engine != null) { + engine.cleanup(); + } + } } //