fixed bug were an exception would cause the lock not to be released

This commit is contained in:
Jeremy Long
2017-10-15 07:57:33 -04:00
parent c8bfdddd59
commit f4b11d8e44
6 changed files with 156 additions and 162 deletions

View File

@@ -59,23 +59,15 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
private String name = "dependency-check:aggregate";
/**
* Executes the aggregate dependency-check goal. This runs dependency-check
* and generates the subsequent reports.
* Scans the dependencies of the projects in aggregate.
*
* @throws MojoExecutionException thrown if there is ane exception running
* the Mojo
* @throws MojoFailureException thrown if dependency-check is configured to
* fail the build
* @param engine the engine used to perform the scanning
* @return a collection of exceptions
* @throws MojoExecutionException thrown if a fatal exception occurs
*/
@Override
public void runCheck() throws MojoExecutionException, MojoFailureException {
final Engine engine = loadEngine();
if (engine == null) {
return;
}
protected ExceptionCollection scanDependencies(final Engine engine) throws MojoExecutionException {
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
for (MavenProject childProject : getDescendants(this.getProject())) {
final ExceptionCollection ex = scanArtifacts(childProject, engine);
if (ex != null) {
@@ -96,61 +88,7 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
}
}
}
try {
engine.analyzeDependencies();
} catch (ExceptionCollection ex) {
if (exCol == null) {
exCol = ex;
} else if (ex.isFatal()) {
exCol.setFatal(true);
exCol.getExceptions().addAll(ex.getExceptions());
}
if (exCol.isFatal()) {
final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName());
if (this.isFailOnError()) {
throw new MojoExecutionException(msg, exCol);
}
getLog().error(msg);
if (getLog().isDebugEnabled()) {
getLog().debug(exCol);
}
return;
} else {
final String msg = String.format("Exception(s) analyzing %s", getProject().getName());
if (getLog().isDebugEnabled()) {
getLog().debug(msg, exCol);
}
}
}
File outputDir = getCorrectOutputDirectory(this.getProject());
if (outputDir == null) {
//in some regards we shouldn't be writing this, but we are anyway.
//we shouldn't write this because nothing is configured to generate this report.
outputDir = new File(this.getProject().getBuild().getDirectory());
}
try {
final MavenProject p = this.getProject();
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, getFormat());
} catch (ReportException ex) {
if (exCol == null) {
exCol = new ExceptionCollection("Error writing aggregate report", ex);
} else {
exCol.addException(ex);
}
if (this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
} else {
getLog().debug("One or more exceptions occurred during dependency-check analysis", exCol);
}
}
showSummary(this.getProject(), engine.getDependencies());
checkForFailure(engine.getDependencies());
if (exCol != null && this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
}
engine.close();
getSettings().cleanup();
return exCol;
}
/**
@@ -242,32 +180,6 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
return "pom".equals(mavenProject.getPackaging());
}
/**
* Initializes the engine.
*
* @return the Engine used to execute dependency-check
* @throws MojoExecutionException thrown if there is an exception running
* the Mojo
* @throws MojoFailureException thrown if dependency-check is configured to
* fail the build if severe CVEs are identified.
*/
protected Engine loadEngine() throws MojoExecutionException, MojoFailureException {
Engine engine = null;
try {
engine = initializeEngine();
} catch (DatabaseException ex) {
if (getLog().isDebugEnabled()) {
getLog().debug("Database connection error", ex);
}
final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
if (this.isFailOnError()) {
throw new MojoExecutionException(msg, ex);
}
getLog().error(msg, ex);
}
return engine;
}
@Override
public boolean canGenerateReport() {
return true; //aggregate always returns true for now - we can look at a more complicated/accurate solution later

View File

@@ -59,6 +59,7 @@ import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.DependencyNotFoundException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.exception.ReportException;
import org.owasp.dependencycheck.utils.Filter;
import org.owasp.dependencycheck.utils.Settings;
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
@@ -902,7 +903,102 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
* @throws MojoFailureException thrown if dependency-check is configured to
* fail the build
*/
public abstract void runCheck() throws MojoExecutionException, MojoFailureException;
protected void runCheck() throws MojoExecutionException, MojoFailureException {
try (Engine engine = initializeEngine()) {
ExceptionCollection exCol = scanDependencies(engine);
try {
engine.analyzeDependencies();
} catch (ExceptionCollection ex) {
exCol = handleAnalysisExceptions(exCol, ex);
}
if (exCol == null || !exCol.isFatal()) {
File outputDir = getCorrectOutputDirectory(this.getProject());
if (outputDir == null) {
//in some regards we shouldn't be writing this, but we are anyway.
//we shouldn't write this because nothing is configured to generate this report.
outputDir = new File(this.getProject().getBuild().getDirectory());
}
try {
final MavenProject p = this.getProject();
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, getFormat());
} catch (ReportException ex) {
if (exCol == null) {
exCol = new ExceptionCollection("Error writing aggregate report", ex);
} else {
exCol.addException(ex);
}
if (this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
} else {
getLog().debug("Error writting the report", ex);
}
}
showSummary(this.getProject(), engine.getDependencies());
checkForFailure(engine.getDependencies());
if (exCol != null && this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
}
}
} catch (DatabaseException ex) {
if (getLog().isDebugEnabled()) {
getLog().debug("Database connection error", ex);
}
final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
if (this.isFailOnError()) {
throw new MojoExecutionException(msg, ex);
}
getLog().error(msg, ex);
} finally {
getSettings().cleanup();
}
}
/**
* Combines the two exception collections and if either are fatal, throw an
* MojoExecutionException
*
* @param currentEx the primary exception collection
* @param newEx the new exception collection to add
* @return the combined exception collection
* @throws MojoExecutionException
*/
private ExceptionCollection handleAnalysisExceptions(ExceptionCollection currentEx, ExceptionCollection newEx) throws MojoExecutionException {
ExceptionCollection returnEx = currentEx;
if (returnEx == null) {
returnEx = newEx;
} else {
returnEx.getExceptions().addAll(newEx.getExceptions());
if (newEx.isFatal()) {
returnEx.setFatal(true);
}
}
if (returnEx.isFatal()) {
final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName());
if (this.isFailOnError()) {
throw new MojoExecutionException(msg, returnEx);
}
getLog().error(msg);
if (getLog().isDebugEnabled()) {
getLog().debug(returnEx);
}
} else {
final String msg = String.format("Exception(s) analyzing %s", getProject().getName());
if (getLog().isDebugEnabled()) {
getLog().debug(msg, returnEx);
}
}
return returnEx;
}
/**
* Scans the dependencies of the projects in aggregate.
*
* @param engine the engine used to perform the scanning
* @return a collection of exceptions
* @throws MojoExecutionException thrown if a fatal exception occurs
*/
protected abstract ExceptionCollection scanDependencies(final Engine engine) throws MojoExecutionException;
/**
* Sets the Reporting output directory.
@@ -979,7 +1075,9 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
//</editor-fold>
/**
* Initializes a new <code>Engine</code> that can be used for scanning.
* Initializes a new <code>Engine</code> that can be used for scanning. This
* method should only be called in a try-with-resources to ensure that the
* engine is properly closed.
*
* @return a newly instantiated <code>Engine</code>
* @throws DatabaseException thrown if there is a database exception

View File

@@ -72,67 +72,6 @@ public class CheckMojo extends BaseDependencyCheckMojo {
return isCapable;
}
/**
* Executes the dependency-check engine on the project's dependencies and
* generates the report.
*
* @throws MojoExecutionException thrown if there is an exception executing
* the goal
* @throws MojoFailureException thrown if dependency-check is configured to
* fail the build
*/
@Override
public void runCheck() throws MojoExecutionException, MojoFailureException {
Engine engine = null;
try {
engine = initializeEngine();
} catch (DatabaseException ex) {
if (getLog().isDebugEnabled()) {
getLog().debug("Database connection error", ex);
}
final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
if (this.isFailOnError()) {
throw new MojoExecutionException(msg, ex);
}
getLog().error(msg);
}
if (engine != null) {
ExceptionCollection exCol = scanArtifacts(getProject(), engine);
if (engine.getDependencies().length == 0) {
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
}
try {
engine.analyzeDependencies();
} catch (ExceptionCollection ex) {
if (this.isFailOnError() && ex.isFatal()) {
throw new MojoExecutionException("One or more exceptions occurred during analysis", ex);
}
exCol = ex;
}
if (exCol == null || !exCol.isFatal()) {
try {
final MavenProject p = this.getProject();
engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), getCorrectOutputDirectory(), getFormat());
} catch (ReportException ex) {
if (this.isFailOnError()) {
if (exCol != null) {
exCol.addException(ex);
} else {
exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
}
}
}
showSummary(getProject(), engine.getDependencies());
checkForFailure(engine.getDependencies());
if (exCol != null && this.isFailOnError()) {
throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
}
}
engine.close();
}
getSettings().cleanup();
}
/**
* Returns the report name.
*
@@ -156,5 +95,17 @@ public class CheckMojo extends BaseDependencyCheckMojo {
return "Generates a report providing details on any published vulnerabilities within project dependencies. "
+ "This report is a best effort and may contain false positives and false negatives.";
}
/**
* Scans the dependencies of the project.
*
* @param engine the engine used to perform the scanning
* @return a collection of exceptions
* @throws MojoExecutionException thrown if a fatal exception occurs
*/
@Override
protected ExceptionCollection scanDependencies(final Engine engine) throws MojoExecutionException {
return scanArtifacts(getProject(), engine);
}
}

View File

@@ -25,6 +25,8 @@ import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.utils.Settings;
/**
@@ -61,7 +63,7 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
* fail the build
*/
@Override
public void runCheck() throws MojoExecutionException, MojoFailureException {
protected void runCheck() throws MojoExecutionException, MojoFailureException {
if (getConnectionString() != null && !getConnectionString().isEmpty()) {
final String msg = "Unable to purge the local NVD when using a non-default connection string";
@@ -125,4 +127,15 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
return "Purges the local cache of the NVD dataT.";
}
/**
* Throws an exception if called. The purge mojo does not scan dependencies.
*
* @param engine the engine used to scan
* @return a collection of exceptions
* @throws MojoExecutionException thrown if there is an exception
*/
@Override
protected ExceptionCollection scanDependencies(Engine engine) throws MojoExecutionException {
throw new UnsupportedOperationException("Operation not supported");
}
}

View File

@@ -26,6 +26,7 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.update.exception.UpdateException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
/**
* Maven Plugin that checks the project dependencies to see if they have any
@@ -63,7 +64,7 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
* fail the build
*/
@Override
public void runCheck() throws MojoExecutionException, MojoFailureException {
protected void runCheck() throws MojoExecutionException, MojoFailureException {
try (Engine engine = initializeEngine()) {
engine.doUpdates();
} catch (DatabaseException ex) {
@@ -106,4 +107,17 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
public String getDescription(Locale locale) {
return "Updates the local cache of the NVD data from NIST.";
}
/**
* Throws an exception if called. The update mojo does not scan
* dependencies.
*
* @param engine the engine used to scan
* @return a collection of exceptions
* @throws MojoExecutionException thrown if there is an exception
*/
@Override
protected ExceptionCollection scanDependencies(Engine engine) throws MojoExecutionException {
throw new UnsupportedOperationException("Operation not supported");
}
}

View File

@@ -37,6 +37,7 @@ import org.junit.Assume;
import org.junit.Test;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.exception.ExceptionCollection;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
@@ -113,8 +114,8 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
public class BaseDependencyCheckMojoImpl extends BaseDependencyCheckMojo {
@Override
public void runCheck() throws MojoExecutionException, MojoFailureException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
protected void runCheck() throws MojoExecutionException, MojoFailureException {
throw new UnsupportedOperationException("Operation not supported");
}
@Override
@@ -129,7 +130,12 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
@Override
public boolean canGenerateReport() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
throw new UnsupportedOperationException("Operation not supported");
}
@Override
protected ExceptionCollection scanDependencies(Engine engine) throws MojoExecutionException {
throw new UnsupportedOperationException("Operation not supported");
}
}
}