diff --git a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java index 919c5f93b..75bf4553b 100644 --- a/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java +++ b/dependency-check-ant/src/main/java/org/owasp/dependencycheck/taskdefs/Check.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.taskdefs; import java.io.File; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; @@ -46,6 +47,7 @@ import org.slf4j.impl.StaticLoggerBinder; * * @author Jeremy Long */ +@NotThreadSafe public class Check extends Update { /** @@ -161,6 +163,7 @@ public class Check extends Update { /** * Suppression file paths. */ + @SuppressWarnings("CanBeFinal") private List suppressionFiles = new ArrayList<>(); /** @@ -1065,7 +1068,7 @@ public class Check extends Update { * @throws BuildException thrown if a CVSS score is found that is higher * than the threshold set */ - private void checkForFailure(List dependencies) throws BuildException { + private void checkForFailure(Dependency[] dependencies) throws BuildException { final StringBuilder ids = new StringBuilder(); for (Dependency d : dependencies) { for (Vulnerability v : d.getVulnerabilities()) { @@ -1092,7 +1095,7 @@ public class Check extends Update { * * @param dependencies a list of dependency objects */ - private void showSummary(List dependencies) { + private void showSummary(Dependency[] dependencies) { final StringBuilder summary = new StringBuilder(); for (Dependency d : dependencies) { boolean firstEntry = true; diff --git a/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 70423496b..e718950dd 100644 --- a/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/dependency-check-ant/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -48,7 +48,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { * * @return the StaticLoggerBinder singleton */ - public static final StaticLoggerBinder getSingleton() { + public static StaticLoggerBinder getSingleton() { return SINGLETON; } 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 742017611..2b8ad9e34 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 @@ -312,7 +312,6 @@ public class App { * @param excludes an array of ant style excludes * @return returns the set of identified files * @throws InvalidScanPathException thrown when the scan path is invalid - * @throws IllegalStateException */ private Set scanAntStylePaths(List antStylePaths, int symLinkDepth, String[] excludes) throws InvalidScanPathException { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java index 21b6da092..9a09bcce6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/AnalysisTask.java @@ -21,12 +21,12 @@ import org.owasp.dependencycheck.analyzer.Analyzer; import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; -import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.concurrent.Callable; +import javax.annotation.concurrent.ThreadSafe; /** * Task to support parallelism of dependency-check analysis. Analyses a single @@ -34,6 +34,7 @@ import java.util.concurrent.Callable; * * @author Stefan Neuhaus */ +@ThreadSafe public class AnalysisTask implements Callable { /** @@ -57,10 +58,6 @@ public class AnalysisTask implements Callable { * The list of exceptions that may occur during analysis. */ private final List exceptions; - /** - * A reference to the global settings object. - */ - private final Settings settings; /** * Creates a new analysis task. @@ -70,16 +67,12 @@ public class AnalysisTask implements Callable { * @param engine the dependency-check engine * @param exceptions exceptions that occur during analysis will be added to * this collection of exceptions - * @param settings a reference to the global settings object; this is - * necessary so that when the thread is started the dependencies have a - * correct reference to the global settings. */ - AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List exceptions, Settings settings) { + AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List exceptions) { this.analyzer = analyzer; this.dependency = dependency; this.engine = engine; this.exceptions = exceptions; - this.settings = settings; } /** 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 96cfd4ca3..ee80f0355 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 @@ -57,6 +57,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.NotThreadSafe; import static org.owasp.dependencycheck.analyzer.AnalysisPhase.*; @@ -68,6 +69,7 @@ import static org.owasp.dependencycheck.analyzer.AnalysisPhase.*; * * @author Jeremy Long */ +@NotThreadSafe public class Engine implements FileFilter, AutoCloseable { /** @@ -170,7 +172,7 @@ public class Engine implements FileFilter, AutoCloseable { * The ClassLoader to use when dynamically loading Analyzer and Update * services. */ - private ClassLoader serviceClassLoader; + private final ClassLoader serviceClassLoader; /** * A reference to the database. */ @@ -304,8 +306,42 @@ public class Engine implements FileFilter, AutoCloseable { * @see Collections#synchronizedList(List) * @see Analyzer#supportsParallelProcessing() */ - public synchronized List getDependencies() { - return dependencies; +// public synchronized List getDependencies() { +// return dependencies; +// } + /** + * Adds a dependency. + * + * @param dependency the dependency to add + */ + public synchronized void addDependency(Dependency dependency) { + dependencies.add(dependency); + } + + /** + * Sorts the dependency list. + */ + public synchronized void sortDependencies() { + //TODO - is this actually necassary???? + Collections.sort(dependencies); + } + + /** + * Removes the dependency. + * + * @param dependency the dependency to remove. + */ + public synchronized void removeDependency(Dependency dependency) { + dependencies.remove(dependency); + } + + /** + * Returns a copy of the dependencies as an array. + * + * @return the dependencies identified + */ + public synchronized Dependency[] getDependencies() { + return dependencies.toArray(new Dependency[dependencies.size()]); } /** @@ -750,7 +786,7 @@ public class Engine implements FileFilter, AutoCloseable { final List result = new ArrayList<>(); synchronized (dependencies) { for (final Dependency dependency : dependencies) { - final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions, settings); + final AnalysisTask task = new AnalysisTask(analyzer, dependency, this, exceptions); result.add(task); } } @@ -907,9 +943,9 @@ public class Engine implements FileFilter, AutoCloseable { } /** - * Returns + * Returns the configured settings. * - * @return + * @return the configured settings */ public Settings getSettings() { return settings; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java index fea1064c7..6234b21c3 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/agent/DependencyCheckScanAgent.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.agent; import java.io.File; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.dependency.Dependency; @@ -59,6 +60,7 @@ import org.slf4j.LoggerFactory; * @author Steve Springett */ @SuppressWarnings("unused") +@NotThreadSafe public class DependencyCheckScanAgent { // @@ -938,7 +940,7 @@ public class DependencyCheckScanAgent { * @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if * there is an exception executing the scan. */ - private void checkForFailure(List dependencies) throws ScanAgentException { + private void checkForFailure(Dependency[] dependencies) throws ScanAgentException { final StringBuilder ids = new StringBuilder(); for (Dependency d : dependencies) { boolean addName = true; @@ -969,7 +971,7 @@ public class DependencyCheckScanAgent { * * @param dependencies a list of dependency objects */ - private void showSummary(List dependencies) { + private void showSummary(Dependency[] dependencies) { final StringBuilder summary = new StringBuilder(); for (Dependency d : dependencies) { boolean firstEntry = true; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.java index 682bf411a..4ae521fe1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractAnalyzer.java @@ -23,6 +23,7 @@ import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.exception.InitializationException; import org.owasp.dependencycheck.utils.InvalidSettingException; import org.owasp.dependencycheck.utils.Settings; +import javax.annotation.concurrent.ThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public abstract class AbstractAnalyzer implements Analyzer { /** @@ -153,7 +155,7 @@ public abstract class AbstractAnalyzer implements Analyzer { try { this.setEnabled(settings.getBoolean(key, true)); } catch (InvalidSettingException ex) { - String msg = String.format("Invalid setting for property '{}'", key); + final String msg = String.format("Invalid setting for property '%s'", key); LOGGER.warn(msg); LOGGER.debug(msg, ex); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractDependencyComparingAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractDependencyComparingAnalyzer.java new file mode 100644 index 000000000..f8efe205d --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractDependencyComparingAnalyzer.java @@ -0,0 +1,125 @@ +/* + * 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) 2017 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.analyzer; + +import java.util.HashSet; +import java.util.Set; +import javax.annotation.concurrent.ThreadSafe; +import org.owasp.dependencycheck.Engine; +import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +import org.owasp.dependencycheck.dependency.Dependency; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + *

+ * This analyzer ensures dependencies that should be grouped together, to remove + * excess noise from the report, are grouped. An example would be Spring, Spring + * Beans, Spring MVC, etc. If they are all for the same version and have the + * same relative path then these should be grouped into a single dependency + * under the core/main library.

+ *

+ * Note, this grouping only works on dependencies with identified CVE + * entries

+ * + * @author Jeremy Long + */ +@ThreadSafe +public abstract class AbstractDependencyComparingAnalyzer extends AbstractAnalyzer { + + /** + * The Logger. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDependencyComparingAnalyzer.class); + + /** + * a flag indicating if this analyzer has run. This analyzer only runs once. + */ + private boolean analyzed = false; + + /** + * Returns a flag indicating if this analyzer has run. This analyzer only + * runs once. Note this is currently only used in the unit tests. + * + * @return a flag indicating if this analyzer has run. This analyzer only + * runs once + */ + protected synchronized boolean getAnalyzed() { + return analyzed; + } + + /** + * Does not support parallel processing as it only runs once and then + * operates on all dependencies. + * + * @return whether or not parallel processing is enabled + * @see #analyze(Dependency, Engine) + */ + @Override + public final boolean supportsParallelProcessing() { + return false; + } + + /** + * Analyzes a set of dependencies. If they have been found to have the same + * base path and the same set of identifiers they are likely related. The + * related dependencies are bundled into a single reportable item. + * + * @param ignore this analyzer ignores the dependency being analyzed + * @param engine the engine that is scanning the dependencies + * @throws AnalysisException is thrown if there is an error reading the JAR + * file. + */ + @Override + protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException { + if (!analyzed) { + analyzed = true; + final Set dependenciesToRemove = new HashSet<>(); + + final Dependency[] dependencies = engine.getDependencies(); + if (dependencies.length < 2) { + return; + } + for (int x = 0; x < dependencies.length - 1; x++) { + final Dependency dependency = dependencies[x]; + if (!dependenciesToRemove.contains(dependency)) { + for (int y = x + 1; y < dependencies.length; y++) { + final Dependency nextDependency = dependencies[y]; + if (evaluateDependencies(dependency, nextDependency, dependenciesToRemove)) { + break; + } + } + } + } + for (Dependency d : dependenciesToRemove) { + engine.removeDependency(d); + } + } + } + + /** + * Evaluates the dependencies + * + * @param dependency a dependency to compare + * @param nextDependency a dependency to compare + * @param dependenciesToRemove a set of dependencies that will be removed + * @return true if a dependency is removed; otherwise false + */ + protected abstract boolean evaluateDependencies(final Dependency dependency, + final Dependency nextDependency, final Set dependenciesToRemove); +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java index fb12ffdd3..e81c6dfb1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractFileTypeAnalyzer.java @@ -25,6 +25,7 @@ import java.io.FileFilter; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.exception.InitializationException; @@ -34,6 +35,7 @@ import org.owasp.dependencycheck.exception.InitializationException; * * @author Jeremy Long */ +@ThreadSafe public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implements FileTypeAnalyzer { // @@ -46,15 +48,6 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen */ private boolean filesMatched = false; - /** - * Get the value of filesMatched. A flag indicating whether the scan - * included any file types this analyzer supports. - * - * @return the value of filesMatched - */ - protected boolean isFilesMatched() { - return filesMatched; - } /** * Set the value of filesMatched. A flag indicating whether the scan diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java index 6aec24cff..931f1380a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AbstractSuppressionAnalyzer.java @@ -22,10 +22,11 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; @@ -47,6 +48,7 @@ import org.xml.sax.SAXException; * * @author Jeremy Long */ +@ThreadSafe public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { /** @@ -56,15 +58,15 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { /** * The list of suppression rules */ - private List rules; + private SuppressionRule[] rules = null; /** * Get the number of suppression rules. * * @return the number of suppression rules */ - protected synchronized int getRuleCount() { - return rules.size(); + protected int getRuleCount() { + return rules.length; } /** @@ -83,17 +85,19 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { * @throws InitializationException thrown if there is an exception */ @Override - public void initializeAnalyzer(Engine engine) throws InitializationException { - try { - loadSuppressionData(); - } catch (SuppressionParseException ex) { - throw new InitializationException("Error initializing the suppression analyzer: " + ex.getLocalizedMessage(), ex); + public synchronized void initializeAnalyzer(Engine engine) throws InitializationException { + if (rules == null) { + try { + rules = loadSuppressionData(); + } catch (SuppressionParseException ex) { + throw new InitializationException("Error initializing the suppression analyzer: " + ex.getLocalizedMessage(), ex); + } } } @Override - protected synchronized void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { - if (rules == null || rules.size() <= 0) { + protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { + if (rules == null || rules.length <= 0) { return; } for (final SuppressionRule rule : rules) { @@ -104,40 +108,43 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { /** * Loads all the suppression rules files configured in the {@link Settings}. * + * @return the array of rules that were loaded * @throws SuppressionParseException thrown if the XML cannot be parsed. */ - private synchronized void loadSuppressionData() throws SuppressionParseException { + private SuppressionRule[] loadSuppressionData() throws SuppressionParseException { + List ruleList; final SuppressionParser parser = new SuppressionParser(); try { final InputStream in = FileUtils.getResourceAsStream("dependencycheck-base-suppression.xml"); - rules = Collections.synchronizedList(parser.parseSuppressionRules(in)); + ruleList = parser.parseSuppressionRules(in); } catch (SAXException ex) { throw new SuppressionParseException("Unable to parse the base suppression data file", ex); } final String[] suppressionFilePaths = getSettings().getArray(Settings.KEYS.SUPPRESSION_FILE); - if (suppressionFilePaths == null || suppressionFilePaths.length == 0) { - return; + if (suppressionFilePaths != null && suppressionFilePaths.length > 0) { + // Load all the suppression file paths + for (final String suppressionFilePath : suppressionFilePaths) { + ruleList.addAll(loadSuppressionFile(parser, suppressionFilePath)); + } } - - // Load all the suppression file paths - for (final String suppressionFilePath : suppressionFilePaths) { - loadSuppressionFile(parser, suppressionFilePath); - } - LOGGER.debug("{} suppression rules were loaded.", rules.size()); + LOGGER.debug("{} suppression rules were loaded.", ruleList.size()); + return ruleList.toArray(new SuppressionRule[ruleList.size()]); } /** * Load a single suppression rules file from the path provided using the * parser provided. * - * @param parser the parser to use for loading the file. - * @param suppressionFilePath the path to load. + * @param parser the parser to use for loading the file + * @param suppressionFilePath the path to load + * @return the list of loaded suppression rules * @throws SuppressionParseException thrown if the suppression file cannot * be loaded and parsed. */ - private synchronized void loadSuppressionFile(final SuppressionParser parser, final String suppressionFilePath) throws SuppressionParseException { + private List loadSuppressionFile(final SuppressionParser parser, + final String suppressionFilePath) throws SuppressionParseException { LOGGER.debug("Loading suppression rules from '{}'", suppressionFilePath); - + final List list = new ArrayList<>(); File file = null; boolean deleteTempFile = false; try { @@ -146,7 +153,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { deleteTempFile = true; file = getSettings().getTempFile("suppression", "xml"); final URL url = new URL(suppressionFilePath); - Downloader downloader = new Downloader(getSettings()); + final Downloader downloader = new Downloader(getSettings()); try { downloader.fetchFile(url, file, false); } catch (DownloadFailedException ex) { @@ -177,7 +184,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { throw new SuppressionParseException(msg); } try { - rules.addAll(parser.parseSuppressionRules(file)); + list.addAll(parser.parseSuppressionRules(file)); } catch (SuppressionParseException ex) { LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath()); LOGGER.warn(ex.getMessage()); @@ -197,6 +204,7 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer { FileUtils.delete(file); } } + return list; } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Analyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Analyzer.java index c00565ecd..59b4f27fe 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Analyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/Analyzer.java @@ -27,10 +27,10 @@ import org.owasp.dependencycheck.utils.Settings; *

* An interface that defines an Analyzer that is used to identify Dependencies. * An analyzer will collect information about the dependency in the form of - * Evidence.

+ * Evidence.

*

* When the {@link org.owasp.dependencycheck.Engine} executes it will load the - * analyzers and call the methods in the following order: + * analyzers and call the methods in the following order:

*
    *
  1. {@link #initializeSettings(org.owasp.dependencycheck.utils.Settings)}
  2. *
  3. {@link #initialize(org.owasp.dependencycheck.Engine)}
  4. @@ -75,7 +75,7 @@ public interface Analyzer { * * @param settings the configured settings */ - public void initializeSettings(Settings settings); + void initializeSettings(Settings settings); /** * The initialize method is called (once) prior to the analyze method being diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java index aa87b8924..ff0b19428 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AnalyzerService.java @@ -24,13 +24,15 @@ import static java.util.Arrays.asList; import java.util.Iterator; import java.util.List; import java.util.ServiceLoader; +import javax.annotation.concurrent.ThreadSafe; /** * The Analyzer Service Loader. This class loads all services that implement - * org.owasp.dependencycheck.analyzer.Analyzer. + * {@link org.owasp.dependencycheck.analyzer.Analyzer}. * * @author Jeremy Long */ +@ThreadSafe public class AnalyzerService { /** 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 23a3609d6..b4136c009 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 @@ -111,7 +111,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { * Detects files with .zip extension. */ private static final FileFilter ZIP_FILTER = FileFilterBuilder.newInstance().addExtensions("zip").build(); - + // /** * The name of the analyzer. @@ -121,6 +121,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { * The phase that this analyzer is intended to run in. */ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INITIAL; + /** * Initializes the analyzer with the configured settings. * @@ -289,9 +290,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer { } if (REMOVE_FROM_ANALYSIS.accept(dependency.getActualFile())) { addDisguisedJarsToDependencies(dependency, engine); - engine.getDependencies().remove(dependency); + engine.removeDependency(dependency); } - Collections.sort(engine.getDependencies()); + engine.sortDependencies(); } /** 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 e0bf7a027..8b85f3a61 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 @@ -43,6 +43,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.ParserConfigurationException; import org.owasp.dependencycheck.exception.InitializationException; import org.apache.commons.lang3.SystemUtils; @@ -55,6 +56,7 @@ import org.owasp.dependencycheck.utils.XmlUtils; * @author colezlaw * */ +@ThreadSafe public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -111,20 +113,16 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { * @throws AnalysisException if anything goes sideways */ @Override - public void analyzeDependency(Dependency dependency, Engine engine) - throws AnalysisException { - + public void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { final File test = new File(dependency.getActualFilePath()); if (!test.isFile()) { throw new AnalysisException(String.format("%s does not exist and cannot be analyzed by dependency-check", dependency.getActualFilePath())); } - if (grokAssemblyExe == null) { LOGGER.warn("GrokAssembly didn't get deployed"); return; } - final List args = buildArgumentList(); if (args == null) { LOGGER.warn("Assembly Analyzer was unable to execute"); @@ -199,8 +197,6 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer { LOGGER.error("----------------------------------------------------"); throw new AnalysisException("Couldn't parse Assembly Analyzer results (GrokAssembly)", saxe); } - // This shouldn't happen - } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java index 4124fe993..91faf1378 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/AutoconfAnalyzer.java @@ -176,7 +176,7 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer { } } } else { - engine.getDependencies().remove(dependency); + engine.removeDependency(dependency); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java index a33ba330a..1e6804cc0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzer.java @@ -224,7 +224,7 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer { } final MessageDigest sha1 = getSha1MessageDigest(); currentDep.setSha1sum(Checksum.getHex(sha1.digest(path))); - engine.getDependencies().add(currentDep); + engine.addDependency(currentDep); } final String source = currentDep.getDisplayFileName(); currentDep.getProductEvidence().addEvidence(source, "Product", diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java index e65ac8da9..870df7bcc 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CPEAnalyzer.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Set; import java.util.StringTokenizer; import java.util.concurrent.TimeUnit; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang3.builder.CompareToBuilder; import org.apache.lucene.analysis.util.CharArraySet; import org.apache.lucene.document.Document; @@ -63,6 +64,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class CPEAnalyzer extends AbstractAnalyzer { /** @@ -92,6 +94,10 @@ public class CPEAnalyzer extends AbstractAnalyzer { * data that will be written into the string. */ private static final int STRING_BUILDER_BUFFER = 20; + /** + * The URL to perform a search of the NVD CVE data at NIST. + */ + public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; /** * The CPE in memory index. */ @@ -101,11 +107,6 @@ public class CPEAnalyzer extends AbstractAnalyzer { */ private CveDB cve; - /** - * The URL to perform a search of the NVD CVE data at NIST. - */ - public static final String NVD_SEARCH_URL = "https://web.nvd.nist.gov/view/vuln/search-results?adv_search=true&cves=on&cpe_version=%s"; - /** * Returns the name of this analyzer. * @@ -126,18 +127,18 @@ public class CPEAnalyzer extends AbstractAnalyzer { return AnalysisPhase.IDENTIFIER_ANALYSIS; } - /** - * The default is to support parallel processing. - * - * @return false - */ - @Override - public boolean supportsParallelProcessing() { - return false; - } - +// /** +// * The default is to support parallel processing. +// * +// * @return false +// */ +// @Override +// public boolean supportsParallelProcessing() { +// return false; +// } /** * Creates the CPE Lucene Index. + * * @param engine a reference to the dependency-check engine * @throws InitializationException is thrown if there is an issue opening * the index. @@ -164,7 +165,7 @@ public class CPEAnalyzer extends AbstractAnalyzer { * @throws DatabaseException when the database throws an exception. This * usually occurs when the database is in use by another process. */ - public void open(CveDB cve) throws IOException, DatabaseException { + public synchronized void open(CveDB cve) throws IOException, DatabaseException { if (!isOpen()) { this.cve = cve; this.cpe = CpeMemoryIndex.getInstance(); @@ -185,10 +186,6 @@ public class CPEAnalyzer extends AbstractAnalyzer { */ @Override public void closeAnalyzer() { - if (cve != null) { - cve.close(); - cve = null; - } if (cpe != null) { cpe.close(); cpe = null; @@ -490,7 +487,7 @@ public class CPEAnalyzer extends AbstractAnalyzer { final String[] words = text.split("[\\s_-]"); final List list = new ArrayList<>(); String tempWord = null; - CharArraySet stopWords = SearchFieldAnalyzer.getStopWords(); + final CharArraySet stopWords = SearchFieldAnalyzer.getStopWords(); for (String word : words) { if (stopWords.contains(word)) { continue; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java index b0bb13a03..8efb36581 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CentralAnalyzer.java @@ -36,6 +36,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.exception.InitializationException; import org.owasp.dependencycheck.utils.DownloadFailedException; import org.owasp.dependencycheck.utils.Downloader; @@ -49,6 +50,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author colezlaw */ +@ThreadSafe public class CentralAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -232,7 +234,7 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer { LOGGER.debug("Unable to delete temp file"); } LOGGER.debug("Downloading {}", ma.getPomUrl()); - Downloader downloader = new Downloader(getSettings()); + final Downloader downloader = new Downloader(getSettings()); downloader.fetchFile(new URL(ma.getPomUrl()), pomFile); PomUtils.analyzePOM(dependency, pomFile); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java index e12546ccc..fa84725a1 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CocoaPodsAnalyzer.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.FileUtils; import org.owasp.dependencycheck.Engine; @@ -41,6 +42,7 @@ import org.owasp.dependencycheck.utils.Settings; * @author Bianca Jiang (https://twitter.com/biancajiang) */ @Experimental +@ThreadSafe public class CocoaPodsAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java index 79ea9c6e6..207a58d96 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/ComposerLockAnalyzer.java @@ -117,7 +117,7 @@ public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer { d.getProductEvidence().addEvidence(COMPOSER_LOCK, "product", dep.getProject(), Confidence.HIGHEST); d.getVersionEvidence().addEvidence(COMPOSER_LOCK, "version", dep.getVersion(), Confidence.HIGHEST); LOGGER.info("Adding dependency {}", d); - engine.getDependencies().add(d); + engine.addDependency(d); } } catch (IOException ex) { LOGGER.warn("Error opening dependency {}", dependency.getActualFilePath()); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java index d563b7248..f243f0e9b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/CpeSuppressionAnalyzer.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.analyzer; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.utils.Settings; /** @@ -26,6 +27,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author Jeremy Long */ +@ThreadSafe public class CpeSuppressionAnalyzer extends AbstractSuppressionAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java index 47fc8b015..b2717c4ce 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzer.java @@ -18,14 +18,11 @@ package org.owasp.dependencycheck.analyzer; import java.io.File; -import java.util.HashSet; import java.util.Iterator; -import java.util.ListIterator; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.owasp.dependencycheck.Engine; -import org.owasp.dependencycheck.analyzer.exception.AnalysisException; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.utils.DependencyVersion; @@ -47,37 +44,19 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ -public class DependencyBundlingAnalyzer extends AbstractAnalyzer { +@ThreadSafe +public class DependencyBundlingAnalyzer extends AbstractDependencyComparingAnalyzer { /** * The Logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(DependencyBundlingAnalyzer.class); - // /** * A pattern for obtaining the first part of a filename. */ private static final Pattern STARTING_TEXT_PATTERN = Pattern.compile("^[a-zA-Z0-9]*"); - /** - * a flag indicating if this analyzer has run. This analyzer only runs once. - */ - private boolean analyzed = false; - - /** - * Returns a flag indicating if this analyzer has run. This analyzer only - * runs once. Note this is currently only used in the unit tests. - * - * @return a flag indicating if this analyzer has run. This analyzer only - * runs once - */ - protected synchronized boolean getAnalyzed() { - return analyzed; - } - - // - // /** * The name of the analyzer. */ @@ -106,19 +85,6 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer { public AnalysisPhase getAnalysisPhase() { return ANALYSIS_PHASE; } - // - - /** - * Does not support parallel processing as it only runs once and then - * operates on all dependencies. - * - * @return whether or not parallel processing is enabled - * @see #analyze(Dependency, Engine) - */ - @Override - public boolean supportsParallelProcessing() { - return false; - } /** *

    @@ -132,65 +98,46 @@ public class DependencyBundlingAnalyzer extends AbstractAnalyzer { } /** - * Analyzes a set of dependencies. If they have been found to have the same - * base path and the same set of identifiers they are likely related. The - * related dependencies are bundled into a single reportable item. + * Evaluates the dependencies * - * @param ignore this analyzer ignores the dependency being analyzed - * @param engine the engine that is scanning the dependencies - * @throws AnalysisException is thrown if there is an error reading the JAR - * file. + * @param dependency a dependency to compare + * @param nextDependency a dependency to compare + * @param dependenciesToRemove a set of dependencies that will be removed + * @return true if a dependency is removed; otherwise false */ @Override - protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException { - if (!analyzed) { - analyzed = true; - final Set dependenciesToRemove = new HashSet<>(); - final ListIterator mainIterator = engine.getDependencies().listIterator(); - //for (Dependency nextDependency : engine.getDependencies()) { - while (mainIterator.hasNext()) { - final Dependency dependency = mainIterator.next(); - if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) { - final ListIterator subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); - while (subIterator.hasNext()) { - final Dependency nextDependency = subIterator.next(); - if (hashesMatch(dependency, nextDependency)) { - if (!containedInWar(dependency.getFilePath()) - && !containedInWar(nextDependency.getFilePath())) { - if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { - mergeDependencies(dependency, nextDependency, dependenciesToRemove); - } else { - mergeDependencies(nextDependency, dependency, dependenciesToRemove); - break; //since we merged into the next dependency - skip forward to the next in mainIterator - } - } - } else if (isShadedJar(dependency, nextDependency)) { - if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { - mergeDependencies(nextDependency, dependency, dependenciesToRemove); - nextDependency.getRelatedDependencies().remove(dependency); - break; - } else { - mergeDependencies(dependency, nextDependency, dependenciesToRemove); - dependency.getRelatedDependencies().remove(nextDependency); - } - } else if (cpeIdentifiersMatch(dependency, nextDependency) - && hasSameBasePath(dependency, nextDependency) - && vulnCountMatches(dependency, nextDependency) - && fileNameMatch(dependency, nextDependency)) { - if (isCore(dependency, nextDependency)) { - mergeDependencies(dependency, nextDependency, dependenciesToRemove); - } else { - mergeDependencies(nextDependency, dependency, dependenciesToRemove); - break; //since we merged into the next dependency - skip forward to the next in mainIterator - } - } - } + protected boolean evaluateDependencies(final Dependency dependency, final Dependency nextDependency, final Set dependenciesToRemove) { + if (hashesMatch(dependency, nextDependency)) { + if (!containedInWar(dependency.getFilePath()) + && !containedInWar(nextDependency.getFilePath())) { + if (firstPathIsShortest(dependency.getFilePath(), nextDependency.getFilePath())) { + mergeDependencies(dependency, nextDependency, dependenciesToRemove); + } else { + mergeDependencies(nextDependency, dependency, dependenciesToRemove); + return true; //since we merged into the next dependency - skip forward to the next in mainIterator } } - //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions - // was difficult because of the inner iterator. - engine.getDependencies().removeAll(dependenciesToRemove); + } else if (isShadedJar(dependency, nextDependency)) { + if (dependency.getFileName().toLowerCase().endsWith("pom.xml")) { + mergeDependencies(nextDependency, dependency, dependenciesToRemove); + nextDependency.getRelatedDependencies().remove(dependency); + return true; + } else { + mergeDependencies(dependency, nextDependency, dependenciesToRemove); + dependency.getRelatedDependencies().remove(nextDependency); + } + } else if (cpeIdentifiersMatch(dependency, nextDependency) + && hasSameBasePath(dependency, nextDependency) + && vulnCountMatches(dependency, nextDependency) + && fileNameMatch(dependency, nextDependency)) { + if (isCore(dependency, nextDependency)) { + mergeDependencies(dependency, nextDependency, dependenciesToRemove); + } else { + mergeDependencies(nextDependency, dependency, dependenciesToRemove); + return true; //since we merged into the next dependency - skip forward to the next in mainIterator + } } + return false; } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java index a2f88542e..398d22da8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/DependencyMergingAnalyzer.java @@ -18,12 +18,8 @@ package org.owasp.dependencycheck.analyzer; import java.io.File; -import java.util.HashSet; import java.util.Iterator; -import java.util.ListIterator; import java.util.Set; -import org.owasp.dependencycheck.Engine; -import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.utils.Settings; import org.slf4j.Logger; @@ -36,31 +32,12 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ -public class DependencyMergingAnalyzer extends AbstractAnalyzer { +public class DependencyMergingAnalyzer extends AbstractDependencyComparingAnalyzer { - // /** * The Logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(DependencyMergingAnalyzer.class); - /** - * a flag indicating if this analyzer has run. This analyzer only runs once. - */ - private boolean analyzed = false; - - /** - * Returns a flag indicating if this analyzer has run. This analyzer only - * runs once. Note this is currently only used in the unit tests. - * - * @return a flag indicating if this analyzer has run. This analyzer only - * runs once - */ - protected synchronized boolean getAnalyzed() { - return analyzed; - } - - // - // /** * The name of the analyzer. */ @@ -90,18 +67,6 @@ public class DependencyMergingAnalyzer extends AbstractAnalyzer { return ANALYSIS_PHASE; } - /** - * Does not support parallel processing as it only runs once and then - * operates on all dependencies. - * - * @return whether or not parallel processing is enabled - * @see #analyze(Dependency, Engine) - */ - @Override - public boolean supportsParallelProcessing() { - return false; - } - /** *

    * Returns the setting key to determine if the analyzer is enabled.

    @@ -112,55 +77,34 @@ public class DependencyMergingAnalyzer extends AbstractAnalyzer { protected String getAnalyzerEnabledSettingKey() { return Settings.KEYS.ANALYZER_DEPENDENCY_MERGING_ENABLED; } - //
    /** - * Analyzes a set of dependencies. If they have been found to be the same - * dependency created by more multiple FileTypeAnalyzers (i.e. a gemspec - * dependency and a dependency from the Bundle Audit Analyzer. The - * dependencies are then merged into a single reportable item. + * Evaluates the dependencies * - * @param ignore this analyzer ignores the dependency being analyzed - * @param engine the engine that is scanning the dependencies - * @throws AnalysisException is thrown if there is an error reading the JAR - * file. + * @param dependency a dependency to compare + * @param nextDependency a dependency to compare + * @param dependenciesToRemove a set of dependencies that will be removed + * @return true if a dependency is removed; otherwise false */ @Override - protected synchronized void analyzeDependency(Dependency ignore, Engine engine) throws AnalysisException { - if (!analyzed) { - analyzed = true; - final Set dependenciesToRemove = new HashSet<>(); - final ListIterator mainIterator = engine.getDependencies().listIterator(); - //for (Dependency nextDependency : engine.getDependencies()) { - while (mainIterator.hasNext()) { - final Dependency dependency = mainIterator.next(); - if (mainIterator.hasNext() && !dependenciesToRemove.contains(dependency)) { - final ListIterator subIterator = engine.getDependencies().listIterator(mainIterator.nextIndex()); - while (subIterator.hasNext()) { - final Dependency nextDependency = subIterator.next(); - Dependency main; - if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) { - if (main == dependency) { - mergeDependencies(dependency, nextDependency, dependenciesToRemove); - } else { - mergeDependencies(nextDependency, dependency, dependenciesToRemove); - break; //since we merged into the next dependency - skip forward to the next in mainIterator - } - } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) { - if (main == dependency) { - mergeDependencies(dependency, nextDependency, dependenciesToRemove); - } else { - mergeDependencies(nextDependency, dependency, dependenciesToRemove); - break; //since we merged into the next dependency - skip forward to the next in mainIterator - } - } - } - } + protected boolean evaluateDependencies(final Dependency dependency, final Dependency nextDependency, final Set dependenciesToRemove) { + Dependency main; + if ((main = getMainGemspecDependency(dependency, nextDependency)) != null) { + if (main == dependency) { + mergeDependencies(dependency, nextDependency, dependenciesToRemove); + } else { + mergeDependencies(nextDependency, dependency, dependenciesToRemove); + return true; //since we merged into the next dependency - skip forward to the next in mainIterator + } + } else if ((main = getMainSwiftDependency(dependency, nextDependency)) != null) { + if (main == dependency) { + mergeDependencies(dependency, nextDependency, dependenciesToRemove); + } else { + mergeDependencies(nextDependency, dependency, dependenciesToRemove); + return true; //since we merged into the next dependency - skip forward to the next in mainIterator } - //removing dependencies here as ensuring correctness and avoiding ConcurrentUpdateExceptions - // was difficult because of the inner iterator. - engine.getDependencies().removeAll(dependenciesToRemove); } + return false; } /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java index 90390234c..fb73251fb 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FalsePositiveAnalyzer.java @@ -28,6 +28,7 @@ import java.util.ListIterator; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class FalsePositiveAnalyzer extends AbstractAnalyzer { /** @@ -155,8 +157,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { } } } - if (mustContain - != null) { + if (mustContain != null) { final Iterator itr = dependency.getIdentifiers().iterator(); while (itr.hasNext()) { final Identifier i = itr.next(); @@ -444,7 +445,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { String parentPath = dependency.getFilePath().toLowerCase(); if (parentPath.contains(".jar")) { parentPath = parentPath.substring(0, parentPath.indexOf(".jar") + 4); - final List dependencies = engine.getDependencies(); + final Dependency[] dependencies = engine.getDependencies(); final Dependency parent = findDependency(parentPath, dependencies); if (parent != null) { boolean remove = false; @@ -462,7 +463,7 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { } } if (remove) { - dependencies.remove(dependency); + engine.removeDependency(dependency); } } } @@ -474,10 +475,10 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer { * dependencies. * * @param dependencyPath the path of the dependency to return - * @param dependencies the collection of dependencies to search + * @param dependencies the array of dependencies to search * @return the dependency object for the given path, otherwise null */ - private Dependency findDependency(String dependencyPath, List dependencies) { + private Dependency findDependency(String dependencyPath, Dependency[] dependencies) { for (Dependency d : dependencies) { if (d.getFilePath().equalsIgnoreCase(dependencyPath)) { return d; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java index 709423512..999adc9c7 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/FileNameAnalyzer.java @@ -18,6 +18,7 @@ package org.owasp.dependencycheck.analyzer; import java.io.File; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.filefilter.NameFileFilter; @@ -30,11 +31,11 @@ import org.owasp.dependencycheck.utils.DependencyVersionUtil; import org.owasp.dependencycheck.utils.Settings; /** - * * Takes a dependency and analyzes the filename and determines the hashes. * * @author Jeremy Long */ +@ThreadSafe public class FileNameAnalyzer extends AbstractAnalyzer { /** @@ -76,6 +77,7 @@ public class FileNameAnalyzer extends AbstractAnalyzer { public AnalysisPhase getAnalysisPhase() { return ANALYSIS_PHASE; } + /** *

    * Returns the setting key to determine if the analyzer is enabled.

    diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java index d5d8683d9..edc20a90a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/HintAnalyzer.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; +import org.apache.commons.lang.ArrayUtils; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; @@ -40,7 +42,6 @@ import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule; import org.owasp.dependencycheck.xml.hints.HintParseException; import org.owasp.dependencycheck.xml.hints.HintParser; import org.owasp.dependencycheck.xml.hints.HintRule; -import org.owasp.dependencycheck.xml.hints.Hints; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; @@ -51,6 +52,7 @@ import org.xml.sax.SAXException; * * @author Jeremy Long */ +@ThreadSafe public class HintAnalyzer extends AbstractAnalyzer { /** @@ -62,11 +64,14 @@ public class HintAnalyzer extends AbstractAnalyzer { */ private static final String HINT_RULE_FILE_NAME = "dependencycheck-base-hint.xml"; /** - * The collection of hints. + * The array of hint rules. */ - private Hints hints; + private HintRule[] hints = null; + /** + * The array of vendor duplicating hint rules. + */ + private VendorDuplicatingHintRule[] vendorHints; - // /** * The name of the analyzer. */ @@ -122,7 +127,6 @@ public class HintAnalyzer extends AbstractAnalyzer { throw new InitializationException("Unable to parse the hint file", ex); } } - // /** * The HintAnalyzer uses knowledge about a dependency to add additional @@ -135,7 +139,7 @@ public class HintAnalyzer extends AbstractAnalyzer { */ @Override protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { - for (HintRule hint : hints.getHintRules()) { + for (HintRule hint : hints) { boolean matchFound = false; for (Evidence given : hint.getGivenVendor()) { if (dependency.getVendorEvidence().getEvidence().contains(given)) { @@ -199,7 +203,7 @@ public class HintAnalyzer extends AbstractAnalyzer { final List newEntries = new ArrayList<>(); while (itr.hasNext()) { final Evidence e = itr.next(); - for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) { + for (VendorDuplicatingHintRule dhr : vendorHints) { if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) { newEntries.add(new Evidence(e.getSource() + " (hint)", e.getName(), dhr.getDuplicate(), e.getConfidence())); @@ -217,71 +221,79 @@ public class HintAnalyzer extends AbstractAnalyzer { * @throws HintParseException thrown if the XML cannot be parsed. */ private void loadHintRules() throws HintParseException { - final HintParser parser = new HintParser(); - File file = null; - try { - hints = parser.parseHints(FileUtils.getResourceAsStream(HINT_RULE_FILE_NAME)); - } catch (HintParseException | SAXException ex) { - LOGGER.error("Unable to parse the base hint data file"); - LOGGER.debug("Unable to parse the base hint data file", ex); - } - final String filePath = getSettings().getString(Settings.KEYS.HINTS_FILE); - if (filePath == null) { - return; - } - boolean deleteTempFile = false; - try { - final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); - if (uriRx.matcher(filePath).matches()) { - deleteTempFile = true; - file = getSettings().getTempFile("hint", "xml"); - final URL url = new URL(filePath); - Downloader downloader = new Downloader(getSettings()); - try { - downloader.fetchFile(url, file, false); - } catch (DownloadFailedException ex) { - downloader.fetchFile(url, file, true); - } - } else { - file = new File(filePath); - if (!file.exists()) { - try (InputStream fromClasspath = FileUtils.getResourceAsStream(filePath)) { - if (fromClasspath != null) { - deleteTempFile = true; - file = getSettings().getTempFile("hint", "xml"); - try { - org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); - } catch (IOException ex) { - throw new HintParseException("Unable to locate hints file in classpath", ex); + if (hints == null) { + final HintParser parser = new HintParser(); + File file = null; + try { + parser.parseHints(FileUtils.getResourceAsStream(HINT_RULE_FILE_NAME)); + hints = parser.getHintRules(); + vendorHints = parser.getVendorDuplicatingHintRules(); + } catch (HintParseException | SAXException ex) { + LOGGER.error("Unable to parse the base hint data file"); + LOGGER.debug("Unable to parse the base hint data file", ex); + } + final String filePath = getSettings().getString(Settings.KEYS.HINTS_FILE); + if (filePath == null) { + return; + } + boolean deleteTempFile = false; + try { + final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE); + if (uriRx.matcher(filePath).matches()) { + deleteTempFile = true; + file = getSettings().getTempFile("hint", "xml"); + final URL url = new URL(filePath); + final Downloader downloader = new Downloader(getSettings()); + try { + downloader.fetchFile(url, file, false); + } catch (DownloadFailedException ex) { + downloader.fetchFile(url, file, true); + } + } else { + file = new File(filePath); + if (!file.exists()) { + try (InputStream fromClasspath = FileUtils.getResourceAsStream(filePath)) { + if (fromClasspath != null) { + deleteTempFile = true; + file = getSettings().getTempFile("hint", "xml"); + try { + org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file); + } catch (IOException ex) { + throw new HintParseException("Unable to locate hints file in classpath", ex); + } } } } } - } - if (file != null) { - try { - final Hints newHints = parser.parseHints(file); - hints.getHintRules().addAll(newHints.getHintRules()); - hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules()); - LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size()); - LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size()); - } catch (HintParseException ex) { - LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); - LOGGER.warn(ex.getMessage()); - LOGGER.debug("", ex); - throw ex; + if (file != null) { + try { + parser.parseHints(file); + if (parser.getHintRules() != null && parser.getHintRules().length > 0) { + hints = (HintRule[]) ArrayUtils.addAll(hints, parser.getHintRules()); + } + if (parser.getVendorDuplicatingHintRules() != null && parser.getVendorDuplicatingHintRules().length > 0) { + vendorHints = (VendorDuplicatingHintRule[]) ArrayUtils.addAll(vendorHints, parser.getVendorDuplicatingHintRules()); + } + LOGGER.debug("{} hint rules were loaded.", hints.length); + LOGGER.debug("{} duplicating hint rules were loaded.", vendorHints.length); + } catch (HintParseException ex) { + LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath()); + LOGGER.warn(ex.getMessage()); + LOGGER.debug("", ex); + throw ex; + } + } + } catch (DownloadFailedException ex) { + throw new HintParseException("Unable to fetch the configured hint file", ex); + } catch (MalformedURLException ex) { + throw new HintParseException("Configured hint file has an invalid URL", ex); + } catch (IOException ex) { + throw new HintParseException("Unable to create temp file for hints", ex); + } finally { + if (deleteTempFile && file != null) { + FileUtils.delete(file); } - } - } catch (DownloadFailedException ex) { - throw new HintParseException("Unable to fetch the configured hint file", ex); - } catch (MalformedURLException ex) { - throw new HintParseException("Configured hint file has an invalid URL", ex); - } catch (IOException ex) { - throw new HintParseException("Unable to create temp file for hints", ex); - } finally { - if (deleteTempFile && file != null) { - FileUtils.delete(file); } } } 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 7f91d1b39..30545a8f7 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 @@ -251,7 +251,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { || fileName.endsWith("-doc.jar") || isMacOSMetaDataFile(dependency, engine)) || !isZipFile(dependency)) { - engine.getDependencies().remove(dependency); + engine.removeDependency(dependency); return; } final boolean hasManifest = parseManifest(dependency, classNames); @@ -289,7 +289,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { * @return whether or not the given dependencies contain a dependency with * the given filename */ - private boolean hasDependencyWithFilename(final List dependencies, final String fileName) { + private boolean hasDependencyWithFilename(final Dependency[] dependencies, final String fileName) { for (final Dependency dependency : dependencies) { if (Paths.get(dependency.getActualFilePath()).getFileName().toString().toLowerCase() .equals(fileName.toLowerCase())) { @@ -386,7 +386,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { newDependency.setFileName(displayName); newDependency.setFilePath(displayPath); setPomEvidence(newDependency, pom, null); - engine.getDependencies().add(newDependency); + engine.addDependency(newDependency); } catch (AnalysisException ex) { LOGGER.warn("An error occurred while analyzing '{}'.", dependency.getActualFilePath()); LOGGER.trace("", ex); @@ -700,6 +700,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { value = Jsoup.parse(value).text(); } if (IGNORE_VALUES.contains(value)) { + //noinspection UnnecessaryContinue continue; } else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) { foundSomething = true; @@ -733,6 +734,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer { foundSomething = true; versionEvidence.addEvidence(source, key, value, Confidence.HIGH); } else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) { + //noinspection UnnecessaryContinue continue; //skipping main class as if this has important information to add it will be added during class name analysis... } else { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java index 9dda549ab..a5eac1d6d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NexusAnalyzer.java @@ -35,6 +35,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.exception.InitializationException; import org.owasp.dependencycheck.utils.DownloadFailedException; import org.owasp.dependencycheck.utils.Downloader; @@ -59,6 +60,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author colezlaw */ +@ThreadSafe public class NexusAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -251,7 +253,7 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer { LOGGER.debug("Unable to delete temp file"); } LOGGER.debug("Downloading {}", ma.getPomUrl()); - Downloader downloader = new Downloader(getSettings()); + final Downloader downloader = new Downloader(getSettings()); downloader.fetchFile(new URL(ma.getPomUrl()), pomFile); PomUtils.analyzePOM(dependency, pomFile); } catch (DownloadFailedException ex) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java index 9bda92357..cc1d85f56 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NodePackageAnalyzer.java @@ -32,6 +32,7 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; import javax.json.Json; import javax.json.JsonException; import javax.json.JsonObject; @@ -47,6 +48,7 @@ import org.owasp.dependencycheck.exception.InitializationException; * @author Dale Visser */ @Experimental +@ThreadSafe public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java index 0eb1f3690..7178522bd 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NspAnalyzer.java @@ -37,11 +37,11 @@ import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URL; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonException; @@ -59,6 +59,7 @@ import org.owasp.dependencycheck.utils.URLConnectionFailureException; * * @author Steve Springett */ +@ThreadSafe public class NspAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -284,11 +285,11 @@ public class NspAnalyzer extends AbstractFileTypeAnalyzer { * @param depType the dependency type */ private void processPackage(Dependency dependency, JsonArray jsonArray, String depType) { - JsonObjectBuilder builder = Json.createObjectBuilder(); + final JsonObjectBuilder builder = Json.createObjectBuilder(); for (JsonString str : jsonArray.getValuesAs(JsonString.class)) { builder.add(str.toString(), ""); } - JsonObject jsonObject = builder.build(); + final JsonObject jsonObject = builder.build(); processPackage(dependency, jsonObject, depType); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java index 72f56c47a..5cc0618e7 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java @@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.exception.InitializationException; /** @@ -40,6 +41,7 @@ import org.owasp.dependencycheck.exception.InitializationException; * * @author colezlaw */ +@ThreadSafe public class NuspecAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java index 69da7f193..f1f2c45c3 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NvdCveAnalyzer.java @@ -17,9 +17,8 @@ */ package org.owasp.dependencycheck.analyzer; -import java.io.IOException; -import java.sql.SQLException; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.data.nvdcve.CveDB; @@ -27,9 +26,7 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.dependency.Vulnerability; -import org.owasp.dependencycheck.exception.InitializationException; import org.owasp.dependencycheck.utils.Settings; -import org.slf4j.LoggerFactory; /** * NvdCveAnalyzer is a utility class that takes a project dependency and @@ -38,36 +35,13 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class NvdCveAnalyzer extends AbstractAnalyzer { /** * The Logger for use throughout the class */ - private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(NvdCveAnalyzer.class); - - /** - * The CVE Index. - */ - private CveDB cveDB; - - /** - * Closes the data source. - */ - @Override - public void closeAnalyzer() { - cveDB.close(); - cveDB = null; - } - - /** - * Returns the status of the data source - is the database open. - * - * @return true or false. - */ - public boolean isOpen() { - return cveDB != null; - } - + //private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(NvdCveAnalyzer.class); /** * Analyzes a dependency and attempts to determine if there are any CPE * identifiers for this dependency. @@ -79,6 +53,7 @@ public class NvdCveAnalyzer extends AbstractAnalyzer { */ @Override protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { + final CveDB cveDB = engine.getDatabase(); for (Identifier id : dependency.getIdentifiers()) { if ("cpe".equals(id.getType())) { try { @@ -133,16 +108,4 @@ public class NvdCveAnalyzer extends AbstractAnalyzer { protected String getAnalyzerEnabledSettingKey() { return Settings.KEYS.ANALYZER_NVD_CVE_ENABLED; } - - /** - * Opens the database used to gather NVD CVE data. - * - * @param engine a reference the dependency-check engine - * @throws InitializationException is thrown if there is an issue opening - * the index. - */ - @Override - public void initializeAnalyzer(Engine engine) throws InitializationException { - this.cveDB = engine.getDatabase(); - } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java index 2506b0d66..ffda14743 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/OpenSSLAnalyzer.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.exception.InitializationException; /** @@ -38,6 +39,7 @@ import org.owasp.dependencycheck.exception.InitializationException; * * @author Dale Visser */ +@ThreadSafe public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -143,6 +145,16 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer { return OPENSSLV_FILTER; } + /** + * Returns the setting for the analyzer enabled setting key. + * + * @return the setting for the analyzer enabled setting key + */ + @Override + protected String getAnalyzerEnabledSettingKey() { + return Settings.KEYS.ANALYZER_OPENSSL_ENABLED; + } + /** * No-op initializer implementation. * @@ -182,7 +194,7 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer { dependency.getVendorEvidence().addEvidence(OPENSSLV_H, "Vendor", "OpenSSL", Confidence.HIGHEST); dependency.getProductEvidence().addEvidence(OPENSSLV_H, "Product", "OpenSSL", Confidence.HIGHEST); } else { - engine.getDependencies().remove(dependency); + engine.removeDependency(dependency); } } @@ -202,14 +214,4 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer { "Problem occurred while reading dependency file.", e); } } - - /** - * Returns the setting for the analyzer enabled setting key. - * - * @return the setting for the analyzer enabled setting key - */ - @Override - protected String getAnalyzerEnabledSettingKey() { - return Settings.KEYS.ANALYZER_OPENSSL_ENABLED; - } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.java index b15e304cc..268e21a83 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonDistributionAnalyzer.java @@ -46,6 +46,7 @@ import org.owasp.dependencycheck.utils.FileUtils; import org.owasp.dependencycheck.utils.Settings; import org.owasp.dependencycheck.utils.UrlStringUtils; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.concurrent.ThreadSafe; /** * Used to analyze a Wheel or egg distribution files, or their contents in @@ -55,30 +56,26 @@ import java.util.concurrent.atomic.AtomicInteger; * @author Dale Visser */ @Experimental +@ThreadSafe public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { /** * Name of egg metadata files to analyze. */ private static final String PKG_INFO = "PKG-INFO"; - /** * Name of wheel metadata files to analyze. */ private static final String METADATA = "METADATA"; - /** * The logger. */ - private static final Logger LOGGER = LoggerFactory - .getLogger(PythonDistributionAnalyzer.class); - + private static final Logger LOGGER = LoggerFactory.getLogger(PythonDistributionAnalyzer.class); /** * The count of directories created during analysis. This is used for * creating temporary directories. */ private static final AtomicInteger DIR_COUNT = new AtomicInteger(0); - /** * The name of the analyzer. */ @@ -87,52 +84,39 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { * The phase that this analyzer is intended to run in. */ private static final AnalysisPhase ANALYSIS_PHASE = AnalysisPhase.INFORMATION_COLLECTION; - /** * The set of file extensions supported by this analyzer. */ private static final String[] EXTENSIONS = {"whl", "egg", "zip"}; - /** * Used to match on egg archive candidate extensions. */ private static final FileFilter EGG_OR_ZIP = FileFilterBuilder.newInstance().addExtensions("egg", "zip").build(); - /** * Used to detect files with a .whl extension. */ private static final FileFilter WHL_FILTER = FileFilterBuilder.newInstance().addExtensions("whl").build(); - /** * The parent directory for the individual directories per archive. */ private File tempFileLocation; - /** * Filter that detects *.dist-info files (but doesn't verify they are * directories. */ - private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter( - ".dist-info"); - + private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(".dist-info"); /** * Filter that detects files named "METADATA". */ - private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter( - "EGG-INFO"); - + private static final FilenameFilter EGG_INFO_FILTER = new NameFileFilter("EGG-INFO"); /** * Filter that detects files named "METADATA". */ - private static final NameFileFilter METADATA_FILTER = new NameFileFilter( - METADATA); - + private static final NameFileFilter METADATA_FILTER = new NameFileFilter(METADATA); /** * Filter that detects files named "PKG-INFO". */ - private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter( - PKG_INFO); - + private static final NameFileFilter PKG_INFO_FILTER = new NameFileFilter(PKG_INFO); /** * The file filter used to determine which files this analyzer supports. */ @@ -311,8 +295,7 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer { addPropertyToEvidence(headers, vendorEvidence, "Author", Confidence.LOW); final String summary = headers.getHeader("Summary", null); if (StringUtils.isNotBlank(summary)) { - JarAnalyzer - .addDescription(dependency, summary, METADATA, "summary"); + JarAnalyzer.addDescription(dependency, summary, METADATA, "summary"); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java index 787dd4598..209ecf98e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/PythonPackageAnalyzer.java @@ -35,6 +35,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.exception.InitializationException; /** @@ -44,13 +45,13 @@ import org.owasp.dependencycheck.exception.InitializationException; * @author Dale Visser */ @Experimental +@ThreadSafe public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { /** * Used when compiling file scanning regex patterns. */ - private static final int REGEX_OPTIONS = Pattern.DOTALL - | Pattern.CASE_INSENSITIVE; + private static final int REGEX_OPTIONS = Pattern.DOTALL | Pattern.CASE_INSENSITIVE; /** * Filename extensions for files to be analyzed. @@ -58,16 +59,14 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { private static final String EXTENSIONS = "py"; /** - * Pattern for matching the module docstring in a source file. + * Pattern for matching the module doc string in a source file. */ - private static final Pattern MODULE_DOCSTRING = Pattern.compile( - "^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS); + private static final Pattern MODULE_DOCSTRING = Pattern.compile("^(['\\\"]{3})(.*?)\\1", REGEX_OPTIONS); /** * Matches assignments to version variables in Python source code. */ - private static final Pattern VERSION_PATTERN = Pattern.compile( - "\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3", + private static final Pattern VERSION_PATTERN = Pattern.compile("\\b(__)?version(__)? *= *(['\"]+)(\\d+\\.\\d+.*?)\\3", REGEX_OPTIONS); /** @@ -130,6 +129,16 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { return AnalysisPhase.INFORMATION_COLLECTION; } + /** + * Returns the key name for the analyzers enabled setting. + * + * @return the key name for the analyzers enabled setting + */ + @Override + protected String getAnalyzerEnabledSettingKey() { + return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED; + } + /** * Returns the FileFilter * @@ -192,7 +201,7 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { } } } else { - engine.getDependencies().remove(dependency); + engine.removeDependency(dependency); } } @@ -212,8 +221,7 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { try { contents = FileUtils.readFileToString(file, Charset.defaultCharset()).trim(); } catch (IOException e) { - throw new AnalysisException( - "Problem occurred while reading dependency file.", e); + throw new AnalysisException("Problem occurred while reading dependency file.", e); } boolean found = false; if (!contents.isEmpty()) { @@ -311,9 +319,4 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer { } return found; } - - @Override - protected String getAnalyzerEnabledSettingKey() { - return Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED; - } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java index 7b5bb4301..d097f11ff 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzer.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.FileUtils; import org.owasp.dependencycheck.Engine; @@ -50,6 +51,7 @@ import org.slf4j.LoggerFactory; * * @author Dale Visser */ +@ThreadSafe public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -482,7 +484,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer { dependency.setDisplayFileName(displayFileName); dependency.setFileName(fileName); dependency.setFilePath(filePath); - engine.getDependencies().add(dependency); + engine.addDependency(dependency); return dependency; } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java index 6502d02ab..42e350cb2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyBundlerAnalyzer.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.analyzer; import java.io.File; import java.io.FilenameFilter; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; @@ -47,6 +48,7 @@ import org.owasp.dependencycheck.dependency.Dependency; * @author Bianca Jiang (https://twitter.com/biancajiang) */ @Experimental +@ThreadSafe public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java index b79a0e231..4cdec0e08 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/RubyGemspecAnalyzer.java @@ -25,6 +25,7 @@ import java.nio.charset.Charset; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.FileUtils; import org.owasp.dependencycheck.Engine; @@ -46,6 +47,7 @@ import org.slf4j.LoggerFactory; * @author Dale Visser */ @Experimental +@ThreadSafe public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer { /** @@ -130,8 +132,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer { private static final Pattern GEMSPEC_BLOCK_INIT = Pattern.compile("Gem::Specification\\.new\\s+?do\\s+?\\|(.+?)\\|"); @Override - protected void analyzeDependency(Dependency dependency, Engine engine) - throws AnalysisException { + protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { String contents; try { contents = FileUtils.readFileToString(dependency.getActualFile(), Charset.defaultCharset()); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java index 5dda68202..932b4ce2c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/SwiftPackageManagerAnalyzer.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.nio.charset.Charset; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.FileUtils; import org.owasp.dependencycheck.Engine; @@ -41,6 +42,7 @@ import org.owasp.dependencycheck.utils.Settings; * @author Bianca Jiang (https://twitter.com/biancajiang) */ @Experimental +@ThreadSafe public class SwiftPackageManagerAnalyzer extends AbstractFileTypeAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java index 3c1c1526b..17c47429d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VersionFilterAnalyzer.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.analyzer; import java.util.Iterator; import java.util.Objects; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; @@ -37,8 +38,14 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class VersionFilterAnalyzer extends AbstractAnalyzer { + /** + * The Logger for use throughout the class + */ + private static final Logger LOGGER = LoggerFactory.getLogger(VersionFilterAnalyzer.class); + // /** * Evidence source. @@ -111,11 +118,6 @@ public class VersionFilterAnalyzer extends AbstractAnalyzer { } // - /** - * The Logger for use throughout the class - */ - private static final Logger LOGGER = LoggerFactory.getLogger(VersionFilterAnalyzer.class); - /** * The HintAnalyzer uses knowledge about a dependency to add additional * information to help in identification of identifiers or vulnerabilities. @@ -126,7 +128,7 @@ public class VersionFilterAnalyzer extends AbstractAnalyzer { * the dependency. */ @Override - protected synchronized void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { + protected void analyzeDependency(Dependency dependency, Engine engine) throws AnalysisException { String fileVersion = null; String pomVersion = null; String manifestVersion = null; diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java index 37216e894..9a85815d4 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/VulnerabilitySuppressionAnalyzer.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.analyzer; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.utils.Settings; /** @@ -26,6 +27,7 @@ import org.owasp.dependencycheck.utils.Settings; * * @author Jeremy Long */ +@ThreadSafe public class VulnerabilitySuppressionAnalyzer extends AbstractSuppressionAnalyzer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/AnalysisException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/AnalysisException.java index 2b641e29c..606f341a7 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/AnalysisException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/AnalysisException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.analyzer.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception thrown when the analysis of a dependency fails. * * @author Jeremy Long */ +@ThreadSafe public class AnalysisException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/ArchiveExtractionException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/ArchiveExtractionException.java index 60c98f5c4..fdea55c10 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/ArchiveExtractionException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/exception/ArchiveExtractionException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.analyzer.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception thrown when files in an archive cannot be extracted. * * @author Jeremy Long */ +@ThreadSafe public class ArchiveExtractionException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java index fd81c65f7..8466741ef 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/central/CentralSearch.java @@ -21,9 +21,11 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; +import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; @@ -45,12 +47,13 @@ import org.xml.sax.SAXException; * * @author colezlaw */ +@ThreadSafe public class CentralSearch { /** * The URL for the Central service */ - private final URL rootURL; + private final String rootURL; /** * Whether to use the Proxy when making requests @@ -70,7 +73,7 @@ public class CentralSearch { * Creates a NexusSearch for the given repository URL. * * @param settings the configured settings - * @throws java.net.MalformedURLException thrown if the configured URL is + * @throws MalformedURLException thrown if the configured URL is * invalid */ public CentralSearch(Settings settings) throws MalformedURLException { @@ -78,7 +81,10 @@ public class CentralSearch { final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL); LOGGER.debug("Central Search URL: {}", searchUrl); - this.rootURL = new URL(searchUrl); + if (isInvalidURL(searchUrl)) { + throw new MalformedURLException(String.format("The configured central analyzer URL is invalid: %s", searchUrl)); + } + this.rootURL = searchUrl; if (null != settings.getString(Settings.KEYS.PROXY_SERVER)) { useProxy = true; LOGGER.debug("Using proxy"); @@ -103,7 +109,7 @@ public class CentralSearch { throw new IllegalArgumentException("Invalid SHA1 format"); } List result = null; - final URL url = new URL(rootURL + String.format("?q=1:\"%s\"&wt=xml", sha1)); + final URL url = new URL(String.format("%s?q=1:\"%s\"&wt=xml", rootURL, sha1)); LOGGER.debug("Searching Central url {}", url); @@ -178,4 +184,21 @@ public class CentralSearch { } return result; } + + /** + * Tests to determine if the gien URL is invalid. + * + * @param url the url to evaluate + * @return true if the url is malformed; otherwise false + */ + private boolean isInvalidURL(String url) { + try { + final URL u = new URL(url); + u.toURI(); + } catch (MalformedURLException | URISyntaxException e) { + LOGGER.trace("URL is invalid: {}", url); + return true; + } + return false; + } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java index 2ab329abe..c2d8f2fed 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerDependency.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.composer; +import javax.annotation.concurrent.ThreadSafe; + /** * Represents a dependency (GAV, right now) from a Composer dependency. * * @author colezlaw */ +@ThreadSafe public final class ComposerDependency { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java index 16be04bc5..af215bff5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerException.java @@ -17,11 +17,15 @@ */ package org.owasp.dependencycheck.data.composer; +import javax.annotation.concurrent.ThreadSafe; + /** - * Represents an exception when handling a composer.json or composer.lock file. Generally used to wrap a downstream exception. + * Represents an exception when handling a composer.json or composer.lock file. + * Generally used to wrap a downstream exception. * * @author colezlaw */ +@ThreadSafe public class ComposerException extends RuntimeException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java index 0803276d1..929d8a4db 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/composer/ComposerLockParser.java @@ -29,12 +29,14 @@ import javax.json.stream.JsonParsingException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; /** * Parses a Composer.lock file from an input stream. In a separate class so it can hopefully be injected. * * @author colezlaw */ +@NotThreadSafe public class ComposerLockParser { /** 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 d40b0dd53..e84926af5 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 @@ -21,6 +21,8 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.concurrent.ThreadSafe; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.core.KeywordAnalyzer; import org.apache.lucene.analysis.miscellaneous.PerFieldAnalyzerWrapper; @@ -47,21 +49,29 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + *

    * An in memory Lucene index that contains the vendor/product combinations from - * the CPE (application) identifiers within the NVD CVE data. + * the CPE (application) identifiers within the NVD CVE data.

    + * + * This is the last remaining singleton in dependency-check-core; The use of + * this singleton - while it may not technically be thread-safe (one database + * used to build this index may not have the same entries as another) the risk + * of this is currently believed to be small. As this memory index consumes a + * large amount of memory we will remain using the singleton pattern for now. * * @author Jeremy Long */ +@ThreadSafe public final class CpeMemoryIndex implements AutoCloseable { + /** + * Singleton instance. + */ + private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex(); /** * The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(CpeMemoryIndex.class); - /** - * singleton instance. - */ - private static final CpeMemoryIndex INSTANCE = new CpeMemoryIndex(); /** * The in memory Lucene index. */ @@ -82,19 +92,11 @@ public final class CpeMemoryIndex implements AutoCloseable { * The Lucene QueryParser used for Searching. */ private QueryParser queryParser; - /** - * The search field analyzer for the product field. - */ - private SearchFieldAnalyzer productFieldAnalyzer; - /** - * The search field analyzer for the vendor field. - */ - private SearchFieldAnalyzer vendorFieldAnalyzer; /** * Track the number of current users of the Lucene index; used to track it * it is okay to actually close the index. */ - private int usageCount = 0; + private final AtomicInteger usageCount = new AtomicInteger(0); /** * private constructor for singleton. @@ -118,8 +120,7 @@ public final class CpeMemoryIndex implements AutoCloseable { * @throws IndexException thrown if there is an error creating the index */ public synchronized void open(CveDB cve) throws IndexException { - if (INSTANCE.usageCount <= 0) { - INSTANCE.usageCount = 0; + if (INSTANCE.usageCount.addAndGet(1) == 1) { index = new RAMDirectory(); buildIndex(cve); try { @@ -131,7 +132,6 @@ public final class CpeMemoryIndex implements AutoCloseable { searchingAnalyzer = createSearchingAnalyzer(); queryParser = new QueryParser(LuceneUtils.CURRENT_VERSION, Fields.DOCUMENT_KEY, searchingAnalyzer); } - INSTANCE.usageCount += 1; } /** @@ -140,7 +140,7 @@ public final class CpeMemoryIndex implements AutoCloseable { * @return whether or not the index is open */ public synchronized boolean isOpen() { - return INSTANCE.usageCount > 0; + return INSTANCE.usageCount.get() > 0; } /** @@ -151,8 +151,8 @@ public final class CpeMemoryIndex implements AutoCloseable { private Analyzer createSearchingAnalyzer() { final Map fieldAnalyzers = new HashMap<>(); fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer()); - productFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION); - vendorFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION); + SearchFieldAnalyzer productFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION); + SearchFieldAnalyzer vendorFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION); fieldAnalyzers.put(Fields.PRODUCT, productFieldAnalyzer); fieldAnalyzers.put(Fields.VENDOR, vendorFieldAnalyzer); @@ -164,8 +164,9 @@ public final class CpeMemoryIndex implements AutoCloseable { */ @Override public synchronized void close() { - INSTANCE.usageCount -= 1; - if (INSTANCE.usageCount <= 0) { + final int count = INSTANCE.usageCount.get() - 1; + if (count <= 0) { + INSTANCE.usageCount.set(0); if (searchingAnalyzer != null) { searchingAnalyzer.close(); searchingAnalyzer = null; @@ -218,8 +219,6 @@ public final class CpeMemoryIndex implements AutoCloseable { } catch (DatabaseException ex) { LOGGER.debug("", ex); throw new IndexException("Error reading CPE data", ex); - } catch (CorruptIndexException ex) { - throw new IndexException("Unable to close an in-memory index", ex); } catch (IOException ex) { throw new IndexException("Unable to close an in-memory index", ex); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/Fields.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/Fields.java index 195348249..96666dee5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/Fields.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/Fields.java @@ -17,11 +17,15 @@ */ package org.owasp.dependencycheck.data.cpe; +import javax.annotation.concurrent.ThreadSafe; + /** - * Fields is a collection of field names used within the Lucene index for CPE entries. + * Fields is a collection of field names used within the Lucene index for CPE + * entries. * * @author Jeremy Long */ +@ThreadSafe public final class Fields { /** @@ -38,7 +42,8 @@ public final class Fields { public static final String PRODUCT = "product"; /** - * Private constructor as this is more of an enumeration rather then a full class. + * Private constructor as this is more of an enumeration rather then a full + * class. */ private Fields() { } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java index 54efbafd4..44ad9be1b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexEntry.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.cpe; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang3.StringUtils; /** @@ -27,6 +28,7 @@ import org.apache.commons.lang3.StringUtils; * * @author Jeremy Long */ +@ThreadSafe public class IndexEntry implements Serializable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexException.java index deb0f69e9..f6b41cd4f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cpe/IndexException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.cpe; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception thrown when the there is an issue using the in-memory CPE Index. * * @author Jeremy Long */ +@ThreadSafe public class IndexException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java index d07232282..6b8735050 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweDB.java @@ -26,11 +26,13 @@ import java.io.InputStream; import java.io.ObjectInputStream; import java.util.HashMap; import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; /** * * @author Jeremy Long */ +@ThreadSafe public final class CweDB { /** @@ -59,9 +61,7 @@ public final class CweDB { final String filePath = "data/cwe.hashmap.serialized"; try (InputStream input = FileUtils.getResourceAsStream(filePath); ObjectInputStream oin = new ObjectInputStream(input)) { - - final Map ret = (HashMap) oin.readObject(); - return ret; + return (HashMap) oin.readObject(); } catch (ClassNotFoundException ex) { LOGGER.warn("Unable to load CWE data. This should not be an issue."); LOGGER.debug("", ex); @@ -79,7 +79,7 @@ public final class CweDB { * @param cweId the CWE ID * @return the full name of the CWE */ - public static String getCweName(String cweId) { + public static synchronized String getCweName(String cweId) { if (cweId != null) { return CWE.get(cweId); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweHandler.java index 894aed93a..398670f4d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/cwe/CweHandler.java @@ -18,6 +18,7 @@ package org.owasp.dependencycheck.data.cwe; import java.util.HashMap; +import javax.annotation.concurrent.NotThreadSafe; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; @@ -27,6 +28,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author Jeremy Long */ +@NotThreadSafe public class CweHandler extends DefaultHandler { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AbstractTokenizingFilter.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AbstractTokenizingFilter.java index 25e943378..b8063bac9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AbstractTokenizingFilter.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AbstractTokenizingFilter.java @@ -18,15 +18,18 @@ package org.owasp.dependencycheck.data.lucene; import java.util.LinkedList; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; /** - * An abstract tokenizing filter that can be used as the base for a tokenizing filter. + * An abstract tokenizing filter that can be used as the base for a tokenizing + * filter. * * @author Jeremy Long */ +@NotThreadSafe public abstract class AbstractTokenizingFilter extends TokenFilter { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericTokenizer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericTokenizer.java index 11f0ef562..2cf69f403 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericTokenizer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/AlphaNumericTokenizer.java @@ -18,14 +18,17 @@ package org.owasp.dependencycheck.data.lucene; import java.io.Reader; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.lucene.analysis.util.CharTokenizer; import org.apache.lucene.util.Version; /** - * Tokenizes the input breaking it into tokens when non-alpha/numeric characters are found. + * Tokenizes the input breaking it into tokens when non-alpha/numeric characters + * are found. * * @author Jeremy Long */ +@NotThreadSafe public class AlphaNumericTokenizer extends CharTokenizer { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/DependencySimilarity.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/DependencySimilarity.java index 0201239aa..7518b0eb9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/DependencySimilarity.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/DependencySimilarity.java @@ -17,12 +17,14 @@ */ package org.owasp.dependencycheck.data.lucene; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.lucene.search.similarities.DefaultSimilarity; /** * * @author Jeremy Long */ +@NotThreadSafe public class DependencySimilarity extends DefaultSimilarity { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java index 2fac02e15..614efe6b4 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/LuceneUtils.java @@ -18,19 +18,22 @@ package org.owasp.dependencycheck.data.lucene; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import javax.annotation.concurrent.ThreadSafe; import org.apache.lucene.util.Version; /** *

    - * Lucene utils is a set of utilize written to make constructing Lucene queries simpler.

    + * Lucene utils is a set of utilize written to make constructing Lucene queries + * simpler.

    * * @author Jeremy Long */ +@ThreadSafe public final class LuceneUtils { /** - * The current version of Lucene being used. Declaring this one place so an upgrade doesn't require hunting through the code - * base. + * The current version of Lucene being used. Declaring this one place so an + * upgrade doesn't require hunting through the code base. */ public static final Version CURRENT_VERSION = Version.LUCENE_47; @@ -41,7 +44,8 @@ public final class LuceneUtils { } /** - * Appends the text to the supplied StringBuilder escaping Lucene control characters in the process. + * Appends the text to the supplied StringBuilder escaping Lucene control + * characters in the process. * * @param buf a StringBuilder to append the escaped text to * @param text the data to be escaped @@ -88,7 +92,8 @@ public final class LuceneUtils { } /** - * Escapes the text passed in so that it is treated as data instead of control characters. + * Escapes the text passed in so that it is treated as data instead of + * control characters. * * @param text data to be escaped * @return the escaped text. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/SearchFieldAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/SearchFieldAnalyzer.java index 8b75f4c10..dddd9f535 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/SearchFieldAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/SearchFieldAnalyzer.java @@ -18,8 +18,6 @@ package org.owasp.dependencycheck.data.lucene; import java.io.Reader; -import java.util.Arrays; -import java.util.List; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.Tokenizer; @@ -44,8 +42,8 @@ public class SearchFieldAnalyzer extends Analyzer { /** * The list of additional stop words to use. */ - private static final List ADDITIONAL_STOP_WORDS = Arrays.asList("software", "framework", "inc", - "com", "org", "net", "www", "consulting", "ltd", "foundation", "project"); + private static final String[] ADDITIONAL_STOP_WORDS = {"software", "framework", "inc", + "com", "org", "net", "www", "consulting", "ltd", "foundation", "project"}; /** * The set of stop words to use in the analyzer. */ @@ -57,8 +55,8 @@ public class SearchFieldAnalyzer extends Analyzer { * @return the set of stop words being used */ public static CharArraySet getStopWords() { - CharArraySet words = new CharArraySet(LuceneUtils.CURRENT_VERSION, StopAnalyzer.ENGLISH_STOP_WORDS_SET, true); - words.addAll(ADDITIONAL_STOP_WORDS); + final CharArraySet words = StopFilter.makeStopSet(LuceneUtils.CURRENT_VERSION, ADDITIONAL_STOP_WORDS, true); + words.addAll(StopAnalyzer.ENGLISH_STOP_WORDS_SET); return words; } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/TokenPairConcatenatingFilter.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/TokenPairConcatenatingFilter.java index 0d966b528..7e712ab91 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/TokenPairConcatenatingFilter.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/lucene/TokenPairConcatenatingFilter.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.data.lucene; import java.io.IOException; import java.util.LinkedList; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; @@ -33,6 +34,7 @@ import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; * * @author Jeremy Long */ +@NotThreadSafe public final class TokenPairConcatenatingFilter extends TokenFilter { /** 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 db157f784..57bcfe729 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 @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.MalformedURLException; import java.util.LinkedList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.owasp.dependencycheck.utils.UrlStringUtils; @@ -28,13 +29,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - *

    - * Takes a TokenStream and splits or adds tokens to correctly index version numbers.

    - *

    - * Example: "3.0.0.RELEASE" -> "3 3.0 3.0.0 RELEASE 3.0.0.RELEASE".

    + * + * Takes a TokenStream, looks for URLs, and breaks them into separate tokens. * * @author Jeremy Long */ +@NotThreadSafe public final class UrlTokenizingFilter extends AbstractTokenizingFilter { /** @@ -52,8 +52,9 @@ public final class UrlTokenizingFilter extends AbstractTokenizingFilter { } /** - * Increments the underlying TokenStream and sets CharTermAttributes to construct an expanded set of tokens by concatenating - * tokens with the previous token. + * Increments the underlying TokenStream and sets CharTermAttributes to + * construct an expanded set of tokens by concatenating tokens with the + * previous token. * * @return whether or not we have hit the end of the TokenStream * @throws IOException is thrown when an IOException occurs diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java index e69ee8d76..d9fa706b2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/MavenArtifact.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.nexus; +import javax.annotation.concurrent.ThreadSafe; + /** * Simple bean representing a Maven Artifact. * * @author colezlaw */ +@ThreadSafe public class MavenArtifact { /** @@ -45,7 +48,8 @@ public class MavenArtifact { private String version; /** - * The artifact url. This may change depending on which Nexus server the search took place. + * The artifact url. This may change depending on which Nexus server the + * search took place. */ private String artifactUrl; /** @@ -80,7 +84,8 @@ public class MavenArtifact { * @param version the version * @param jarAvailable if the jar file is available from central * @param pomAvailable if the pom file is available from central - * @param secureDownload if the jar and pom files should be downloaded using HTTPS. + * @param secureDownload if the jar and pom files should be downloaded using + * HTTPS. */ public MavenArtifact(String groupId, String artifactId, String version, boolean jarAvailable, boolean pomAvailable, boolean secureDownload) { this.groupId = groupId; @@ -220,5 +225,3 @@ public class MavenArtifact { } } - -// vim: cc=120:sw=4:ts=4:sts=4 diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java index 07c0b23ac..0f4eac34c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nexus/NexusSearch.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; @@ -41,6 +42,7 @@ import org.xml.sax.SAXException; * * @author colezlaw */ +@ThreadSafe public class NexusSearch { /** @@ -66,16 +68,17 @@ public class NexusSearch { * * @param settings the configured settings * @param useProxy flag indicating if the proxy settings should be used - * @throws java.net.MalformedURLException thrown if the configured URL is invalid + * @throws java.net.MalformedURLException thrown if the configured URL is + * invalid */ public NexusSearch(Settings settings, boolean useProxy) throws MalformedURLException { this.settings = settings; this.useProxy = useProxy; - + final String searchUrl = settings.getString(Settings.KEYS.ANALYZER_NEXUS_URL); LOGGER.debug("Nexus Search URL: {}", searchUrl); this.rootURL = new URL(searchUrl); - + } /** @@ -103,7 +106,7 @@ public class NexusSearch { // 2) Otherwise, don't use the proxy (either the proxy isn't configured, // or proxy is specifically set to false HttpURLConnection conn; - URLConnectionFactory factory = new URLConnectionFactory(settings); + final URLConnectionFactory factory = new URLConnectionFactory(settings); conn = factory.createHttpURLConnection(url, useProxy); conn.setDoOutput(true); @@ -169,7 +172,7 @@ public class NexusSearch { HttpURLConnection conn; try { final URL url = new URL(rootURL, "status"); - URLConnectionFactory factory = new URLConnectionFactory(settings); + final URLConnectionFactory factory = new URLConnectionFactory(settings); conn = factory.createHttpURLConnection(url, useProxy); conn.addRequestProperty("Accept", "application/xml"); conn.connect(); @@ -187,9 +190,6 @@ public class NexusSearch { } catch (IOException | ParserConfigurationException | SAXException e) { return false; } - return true; } } - -// vim: cc=120:sw=4:ts=4:sts=4 diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java index 8736db13c..f6ec6a978 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/Advisory.java @@ -18,6 +18,7 @@ package org.owasp.dependencycheck.data.nsp; import java.util.Arrays; +import javax.annotation.concurrent.ThreadSafe; /** * The response from NSP check API will respond with 0 or more advisories. This @@ -25,6 +26,7 @@ import java.util.Arrays; * * @author Steve Springett */ +@ThreadSafe public class Advisory { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java index afc747c38..a40fd4ca5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/NspSearch.java @@ -28,6 +28,7 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.utils.Settings; import org.owasp.dependencycheck.utils.URLConnectionFactory; @@ -45,6 +46,7 @@ import org.owasp.dependencycheck.utils.URLConnectionFailureException; * * @author Steve Springett */ +@ThreadSafe public class NspSearch { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java index 26ac4dd16..4bee31ceb 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nsp/SanitizePackage.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; /** * Class used to create a Sanitized version of package.json suitable for @@ -32,6 +33,7 @@ import java.util.Map; * * @author Steve Springett */ +@ThreadSafe public final class SanitizePackage { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java index 3897b3416..50c329654 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java @@ -17,12 +17,16 @@ */ package org.owasp.dependencycheck.data.nuget; +import javax.annotation.concurrent.ThreadSafe; + /** * Represents the contents of a Nuspec manifest. * * @author colezlaw */ +@ThreadSafe public class NugetPackage { + /** * The id. */ @@ -55,6 +59,7 @@ public class NugetPackage { /** * Sets the id. + * * @param id the id */ public void setId(String id) { @@ -63,6 +68,7 @@ public class NugetPackage { /** * Gets the id. + * * @return the id */ public String getId() { @@ -71,6 +77,7 @@ public class NugetPackage { /** * Sets the version. + * * @param version the version */ public void setVersion(String version) { @@ -79,6 +86,7 @@ public class NugetPackage { /** * Gets the version. + * * @return the version */ public String getVersion() { @@ -87,6 +95,7 @@ public class NugetPackage { /** * Sets the title. + * * @param title the title */ public void setTitle(String title) { @@ -95,6 +104,7 @@ public class NugetPackage { /** * Gets the title. + * * @return the title */ public String getTitle() { @@ -103,6 +113,7 @@ public class NugetPackage { /** * Sets the authors. + * * @param authors the authors */ public void setAuthors(String authors) { @@ -111,6 +122,7 @@ public class NugetPackage { /** * Gets the authors. + * * @return the authors */ public String getAuthors() { @@ -119,6 +131,7 @@ public class NugetPackage { /** * Sets the owners. + * * @param owners the owners */ public void setOwners(String owners) { @@ -127,6 +140,7 @@ public class NugetPackage { /** * Gets the owners. + * * @return the owners */ public String getOwners() { @@ -135,6 +149,7 @@ public class NugetPackage { /** * Sets the licenseUrl. + * * @param licenseUrl the licenseUrl */ public void setLicenseUrl(String licenseUrl) { @@ -143,6 +158,7 @@ public class NugetPackage { /** * Gets the licenseUrl. + * * @return the licenseUrl */ public String getLicenseUrl() { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java index 5ab31ddb5..8156e35d6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.nuget; +import javax.annotation.concurrent.ThreadSafe; + /** * Exception during the parsing of a Nuspec file. * * @author colezlaw */ +@ThreadSafe public class NuspecParseException extends Exception { /** @@ -32,19 +35,20 @@ public class NuspecParseException extends Exception { /** * Constructs a new exception with null as its detail message. * - * The cause is not initialized, and may subsequently be initialized by a call to - * {@link java.lang.Throwable#initCause(java.lang.Throwable)}. + * The cause is not initialized, and may subsequently be initialized by a + * call to {@link java.lang.Throwable#initCause(java.lang.Throwable)}. */ public NuspecParseException() { super(); } /** - * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently - * be initialized by a call to {@link java.lang.Throwable#initCause(java.lang.Throwable)}. + * Constructs a new exception with the specified detail message. The cause + * is not initialized, and may subsequently be initialized by a call to + * {@link java.lang.Throwable#initCause(java.lang.Throwable)}. * - * @param message the detail message. The detail message is saved for later retrieval by the - * {@link java.lang.Throwable#getMessage()} method. + * @param message the detail message. The detail message is saved for later + * retrieval by the {@link java.lang.Throwable#getMessage()} method. */ public NuspecParseException(String message) { super(message); @@ -53,13 +57,16 @@ public class NuspecParseException extends Exception { /** * Constructs a new exception with the specified detail message and cause. * - * Note that the detail message associated with cause is not + * Note that the detail message associated with cause is + * not * automatically incorporated in this exception's detail message. * - * @param message the detail message (which is saved for later retrieval by the - * {@link java.lang.Throwable#getMessage()} method. - * @param cause the cause (which is saved for later retrieval by the {@link java.lang.Throwable#getCause()} method). - * (A null value is permitted, and indicates that the cause is nonexistent or unknown). + * @param message the detail message (which is saved for later retrieval by + * the {@link java.lang.Throwable#getMessage()} method. + * @param cause the cause (which is saved for later retrieval by the + * {@link java.lang.Throwable#getCause()} method). (A null + * value is permitted, and indicates that the cause is nonexistent or + * unknown). */ public NuspecParseException(String message, Throwable cause) { super(message, cause); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java index 04a6f8362..13bacd45a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java @@ -26,6 +26,7 @@ import java.io.InputStream; * */ public interface NuspecParser { + /** * Parse an input stream and return the resulting {@link NugetPackage}. * diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java index fa91cb73f..1a7e2ab18 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.data.nuget; import java.io.IOException; import java.io.InputStream; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPath; @@ -35,6 +36,7 @@ import org.xml.sax.SAXException; * * @author colezlaw */ +@ThreadSafe public class XPathNuspecParser implements NuspecParser { /** 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 942bb3b3d..fc5958194 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 @@ -27,6 +27,7 @@ import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.IOUtils; import org.owasp.dependencycheck.utils.DBUtils; import org.owasp.dependencycheck.utils.DependencyVersion; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public final class ConnectionFactory { /** @@ -245,6 +247,7 @@ public final class ConnectionFactory { public boolean h2DataFileExists() throws IOException { return h2DataFileExists(settings); } + /** * Determines if the H2 database file exists. If it does not exist then the * data structure will need to be created. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CorruptDatabaseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CorruptDatabaseException.java index 7dbdd6adb..a504485ef 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CorruptDatabaseException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/CorruptDatabaseException.java @@ -17,11 +17,15 @@ */ package org.owasp.dependencycheck.data.nvdcve; +import javax.annotation.concurrent.ThreadSafe; + /** - * An exception used to indicate the db4o database is corrupt. This could be due to invalid data or a complete failure of the db. + * An exception used to indicate the db4o database is corrupt. This could be due + * to invalid data or a complete failure of the db. * * @author Jeremy Long */ +@ThreadSafe public class CorruptDatabaseException extends DatabaseException { /** 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 7d4baa35b..e1fd4623b 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 @@ -17,7 +17,6 @@ */ package org.owasp.dependencycheck.data.nvdcve; -import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.sql.Connection; @@ -354,6 +353,7 @@ public final class CveDB implements AutoCloseable { * * @throws SQLException thrown if a SQL Exception occurs */ + @SuppressWarnings("EmptyMethod") public synchronized void commit() throws SQLException { //temporary remove this as autocommit is on. //if (isOpen()) { @@ -514,7 +514,7 @@ public final class CveDB implements AutoCloseable { * * It should be also called when DB is closed. */ - private void clearCache() { + private synchronized void clearCache() { vulnerabilitiesForCpeCache.clear(); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseException.java index 474664302..50af8d496 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.nvdcve; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception thrown if an operation against the database fails. * * @author Jeremy Long */ +@ThreadSafe public class DatabaseException extends RuntimeException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java index ea690ba75..d8f97865b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DatabaseProperties.java @@ -97,7 +97,7 @@ public class DatabaseProperties { * * @return whether or not any properties are set */ - public boolean isEmpty() { + public synchronized boolean isEmpty() { return properties == null || properties.isEmpty(); } @@ -107,7 +107,7 @@ public class DatabaseProperties { * @param updatedValue the updated NVD CVE entry * @throws UpdateException is thrown if there is an update exception */ - public void save(NvdCveInfo updatedValue) throws UpdateException { + public synchronized void save(NvdCveInfo updatedValue) throws UpdateException { if (updatedValue == null) { return; } @@ -121,7 +121,7 @@ public class DatabaseProperties { * @param value the property value * @throws UpdateException is thrown if there is an update exception */ - public void save(String key, String value) throws UpdateException { + public synchronized void save(String key, String value) throws UpdateException { properties.put(key, value); cveDB.saveProperty(key, value); } @@ -133,7 +133,7 @@ public class DatabaseProperties { * @param key the property key * @return the value of the property */ - public String getProperty(String key) { + public synchronized String getProperty(String key) { return properties.getProperty(key); } @@ -145,7 +145,7 @@ public class DatabaseProperties { * @param defaultValue the default value * @return the value of the property */ - public String getProperty(String key, String defaultValue) { + public synchronized String getProperty(String key, String defaultValue) { return properties.getProperty(key, defaultValue); } @@ -154,7 +154,7 @@ public class DatabaseProperties { * * @return the collection of Database Properties */ - public Properties getProperties() { + public synchronized Properties getProperties() { return properties; } @@ -165,7 +165,7 @@ public class DatabaseProperties { * * @return a map of the database meta data */ - public Map getMetaData() { + public synchronized Map getMetaData() { final Map map = new TreeMap<>(); for (Entry entry : properties.entrySet()) { final String key = (String) entry.getKey(); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoadException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoadException.java index cf8c0e1d0..37a7df201 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoadException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverLoadException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.nvdcve; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception thrown the database driver is unable to be loaded. * * @author Jeremy Long */ +@ThreadSafe public class DriverLoadException extends Exception { /** 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 ac8d49e17..643974b4d 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 @@ -31,12 +31,14 @@ import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; /** * DriverLoader is a utility class that is used to load database drivers. * * @author Jeremy Long */ +@ThreadSafe public final class DriverLoader { /** @@ -148,8 +150,6 @@ public final class DriverLoader { final Driver driver = (Driver) c.newInstance(); //TODO add usage count so we don't de-register a driver that is in use. - - 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(shim); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverShim.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverShim.java index 9d5f04ff0..f98fec30c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverShim.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nvdcve/DriverShim.java @@ -28,16 +28,19 @@ import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; +import javax.annotation.concurrent.ThreadSafe; /** *

    - * Driver shim to get around the class loader issue with the DriverManager. The following code is a nearly identical - * copy (with more comments and a few more methods implemented) of the DriverShim from:

    + * Driver shim to get around the class loader issue with the DriverManager. The + * following code is a nearly identical copy (with more comments and a few more + * methods implemented) of the DriverShim from:

    *
    http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
    * * @author Jeremy Long * @see java.sql.Driver */ +@ThreadSafe class DriverShim implements Driver { /** @@ -59,12 +62,13 @@ class DriverShim implements Driver { } /** - * Wraps the underlying driver's call to acceptsURL. Returns whether or not the driver can open a connection to the - * given URL. + * Wraps the underlying driver's call to acceptsURL. Returns whether or not + * the driver can open a connection to the given URL. * * @param url the URL of the database * @return true if the wrapped driver can connect to the specified URL - * @throws SQLException thrown if there is an error connecting to the database + * @throws SQLException thrown if there is an error connecting to the + * database * @see java.sql.Driver#acceptsURL(java.lang.String) */ @Override @@ -78,7 +82,8 @@ class DriverShim implements Driver { * @param url the URL of the database * @param info a collection of string/value pairs * @return a Connection object - * @throws SQLException thrown if there is an error connecting to the database + * @throws SQLException thrown if there is an error connecting to the + * database * @see java.sql.Driver#connect(java.lang.String, java.util.Properties) */ @Override @@ -112,7 +117,8 @@ class DriverShim implements Driver { * Wraps the call to the underlying driver's getParentLogger method. * * @return the parent's Logger - * @throws SQLFeatureNotSupportedException thrown if the feature is not supported + * @throws SQLFeatureNotSupportedException thrown if the feature is not + * supported * @see java.sql.Driver#getParentLogger() */ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { @@ -140,7 +146,8 @@ class DriverShim implements Driver { * @param info a collection of string/value pairs * @return an array of DriverPropertyInfo objects * @throws SQLException thrown if there is an error accessing the database - * @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties) + * @see java.sql.Driver#getPropertyInfo(java.lang.String, + * java.util.Properties) */ @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/EngineVersionCheck.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/EngineVersionCheck.java index fb1c5f101..ac9c33bf2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/EngineVersionCheck.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/EngineVersionCheck.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.io.IOUtils; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.data.nvdcve.CveDB; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class EngineVersionCheck implements CachedWebDataSource { /** @@ -115,7 +117,7 @@ public class EngineVersionCheck implements CachedWebDataSource { public void update(Engine engine) throws UpdateException { this.settings = engine.getSettings(); try { - CveDB db = engine.getDatabase(); + final CveDB db = engine.getDatabase(); final boolean autoupdate = settings.getBoolean(Settings.KEYS.AUTO_UPDATE, 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); @@ -208,7 +210,7 @@ public class EngineVersionCheck implements CachedWebDataSource { try { final String str = settings.getString(Settings.KEYS.ENGINE_VERSION_CHECK_URL, "http://jeremylong.github.io/DependencyCheck/current.txt"); final URL url = new URL(str); - URLConnectionFactory factory = new URLConnectionFactory(settings); + final URLConnectionFactory factory = new URLConnectionFactory(settings); conn = factory.createHttpURLConnection(url); conn.connect(); if (conn.getResponseCode() != 200) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java index ceee65cd8..d677428c0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/NvdCveUpdater.java @@ -17,9 +17,6 @@ */ package org.owasp.dependencycheck.data.update; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; import java.net.MalformedURLException; import java.util.Calendar; import java.util.HashMap; @@ -27,8 +24,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; import java.net.URL; -import java.nio.channels.FileLock; -import java.util.Date; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -36,6 +31,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.Engine; import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; import org.owasp.dependencycheck.data.nvdcve.CveDB; @@ -63,6 +59,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class NvdCveUpdater implements CachedWebDataSource { /** @@ -116,9 +113,12 @@ public class NvdCveUpdater implements CachedWebDataSource { if (isUpdateConfiguredFalse()) { return; } - H2DBLock dbupdate = new H2DBLock(settings, ConnectionFactory.isH2Connection(settings)); + H2DBLock dbupdate = null; try { - dbupdate.lock(); + if (ConnectionFactory.isH2Connection(settings)) { + dbupdate = new H2DBLock(settings); + dbupdate.lock(); + } initializeExecutorServices(); dbProperties = cveDb.getDatabaseProperties(); @@ -142,7 +142,9 @@ public class NvdCveUpdater implements CachedWebDataSource { } catch (H2DBLockException ex) { throw new UpdateException("Unable to obtain an exclusive lock on the H2 database to perform updates", ex); } finally { - dbupdate.release(); + if (dbupdate != null) { + dbupdate.release(); + } shutdownExecutorServices(); } } @@ -480,7 +482,7 @@ public class NvdCveUpdater implements CachedWebDataSource { * * @param settings the configured settings */ - protected void setSettings(Settings settings) { + protected synchronized void setSettings(Settings settings) { this.settings = settings; } @@ -513,7 +515,7 @@ public class NvdCveUpdater implements CachedWebDataSource { public Long call() throws Exception { LOGGER.debug("Checking for updates from: {}", url); try { - Downloader downloader = new Downloader(settings); + final Downloader downloader = new Downloader(settings); return downloader.getLastModified(new URL(url)); } finally { settings.cleanup(false); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/UpdateService.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/UpdateService.java index 8720b3539..c4cd75f68 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/UpdateService.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/UpdateService.java @@ -19,13 +19,15 @@ package org.owasp.dependencycheck.data.update; import java.util.Iterator; import java.util.ServiceLoader; +import javax.annotation.concurrent.NotThreadSafe; /** - * The CachedWebDataSource Service Loader. This class loads all services that implement - * org.owasp.dependencycheck.data.update.CachedWebDataSource. + * The CachedWebDataSource Service Loader. This class loads all services that + * implement {@link org.owasp.dependencycheck.data.update.CachedWebDataSource}. * * @author Jeremy Long */ +@NotThreadSafe public class UpdateService { /** @@ -36,14 +38,16 @@ public class UpdateService { /** * Creates a new instance of UpdateService. * - * @param classLoader the ClassLoader to use when dynamically loading Analyzer and Update services + * @param classLoader the ClassLoader to use when dynamically loading + * Analyzer and Update services */ public UpdateService(ClassLoader classLoader) { loader = ServiceLoader.load(CachedWebDataSource.class, classLoader); } /** - * Returns an Iterator for all instances of the CachedWebDataSource interface. + * Returns an Iterator for all instances of the CachedWebDataSource + * interface. * * @return an iterator of CachedWebDataSource. */ diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java index 63cd30d53..4b1b5111d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/CPEHandler.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.update.cpe; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.data.update.NvdCveUpdater; import org.owasp.dependencycheck.data.update.exception.InvalidDataException; import org.owasp.dependencycheck.utils.Settings; @@ -34,6 +35,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author Jeremy Long */ +@NotThreadSafe public class CPEHandler extends DefaultHandler { /** @@ -62,6 +64,11 @@ public class CPEHandler extends DefaultHandler { */ private final List data = new ArrayList<>(); + /** + * Constructs a new CPE Handler object with the configured settings. + * + * @param settings the configured settings + */ public CPEHandler(Settings settings) { cpeStartsWith = settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER, "cpe:/a:"); } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/Cpe.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/Cpe.java index 980552df1..8d037b9d6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/Cpe.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/cpe/Cpe.java @@ -20,14 +20,30 @@ package org.owasp.dependencycheck.data.update.cpe; import org.apache.commons.lang3.StringUtils; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.data.update.exception.InvalidDataException; /** * * @author Jeremy Long */ +@ThreadSafe public class Cpe { + /** + * The CPE identifier string (cpe:/a:vendor:product:version). + */ + private String value; + /** + * The vendor portion of the identifier. + */ + private String vendor; + + /** + * The product portion of the identifier. + */ + private String product; + /** * Constructs a new Cpe Object by parsing the vendor and product from the CPE identifier value. * @@ -47,11 +63,6 @@ public class Cpe { } } - /** - * The CPE identifier string (cpe:/a:vendor:product:version). - */ - private String value; - /** * Get the value of value. * @@ -69,10 +80,6 @@ public class Cpe { public void setValue(String value) { this.value = value; } - /** - * The vendor portion of the identifier. - */ - private String vendor; /** * Get the value of vendor. @@ -92,11 +99,6 @@ public class Cpe { this.vendor = vendor; } - /** - * The product portion of the identifier. - */ - private String product; - /** * Get the value of product. * diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/InvalidDataException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/InvalidDataException.java index e5398720f..90ac58186 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/InvalidDataException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/InvalidDataException.java @@ -17,11 +17,15 @@ */ package org.owasp.dependencycheck.data.update.exception; +import javax.annotation.concurrent.ThreadSafe; + /** - * An InvalidDataDataException is a generic exception used when trying to load the NVD CVE meta data. + * An InvalidDataDataException is a generic exception used when trying to load + * the NVD CVE meta data. * * @author Jeremy Long */ +@ThreadSafe public class InvalidDataException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/UpdateException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/UpdateException.java index a09c17040..2c4e53f18 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/UpdateException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/exception/UpdateException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.data.update.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception used when an error occurs reading a setting. * * @author Jeremy Long */ +@ThreadSafe public class UpdateException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java index cdf0eac80..743c8185b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/DownloadTask.java @@ -25,6 +25,7 @@ import java.net.URL; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.data.nvdcve.CveDB; import org.owasp.dependencycheck.data.update.exception.UpdateException; import org.owasp.dependencycheck.utils.DownloadFailedException; @@ -39,6 +40,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class DownloadTask implements Callable> { /** @@ -128,15 +130,6 @@ public class DownloadTask implements Callable> { return first; } - /** - * Set the value of first. - * - * @param first new value of first - */ - public void setFirst(File first) { - this.first = first; - } - /** * Get the value of second. * @@ -146,15 +139,6 @@ public class DownloadTask implements Callable> { return second; } - /** - * Set the value of second. - * - * @param second new value of second - */ - public void setSecond(File second) { - this.second = second; - } - @Override public Future call() throws Exception { try { @@ -163,7 +147,7 @@ public class DownloadTask implements Callable> { LOGGER.info("Download Started for NVD CVE - {}", nvdCveInfo.getId()); final long startDownload = System.currentTimeMillis(); try { - Downloader downloader = new Downloader(settings); + final Downloader downloader = new Downloader(settings); downloader.fetchFile(url1, first); downloader.fetchFile(url2, second); } catch (DownloadFailedException ex) { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java index 7adfbb18c..b30c9bbe2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve12Handler.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.dependency.VulnerableSoftware; import org.xml.sax.Attributes; import org.xml.sax.SAXException; @@ -34,6 +35,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author Jeremy Long */ +@NotThreadSafe public class NvdCve12Handler extends DefaultHandler { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve20Handler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve20Handler.java index 2a5b8bf80..4e715c32b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve20Handler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCve20Handler.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.update.nvd; import java.io.IOException; import java.util.List; import java.util.Map; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.lucene.index.CorruptIndexException; import org.owasp.dependencycheck.data.nvdcve.CveDB; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; @@ -40,6 +41,7 @@ import static org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.Attribut * * @author Jeremy Long */ +@NotThreadSafe public class NvdCve20Handler extends DefaultHandler { /** @@ -184,9 +186,7 @@ public class NvdCve20Handler extends DefaultHandler { totalNumberOfApplicationEntries += 1; try { saveEntry(vulnerability); - } catch (DatabaseException | CorruptIndexException ex) { - throw new SAXException(ex); - } catch (IOException ex) { + } catch (DatabaseException | IOException ex) { throw new SAXException(ex); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCveInfo.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCveInfo.java index a143000a8..bdeb8f1b8 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCveInfo.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/NvdCveInfo.java @@ -17,17 +17,36 @@ */ package org.owasp.dependencycheck.data.update.nvd; +import javax.annotation.concurrent.ThreadSafe; + /** * A pojo that contains the Url and timestamp of the current NvdCve XML files. * * @author Jeremy Long */ +@ThreadSafe public class NvdCveInfo { /** * an id. */ private String id; + /** + * a url. + */ + private String url; + /** + * The 1.2 schema URL. + */ + private String oldSchemaVersionUrl; + /** + * a timestamp - epoch time. + */ + private long timestamp; + /** + * indicates whether or not this item should be updated. + */ + private boolean needsUpdate = true; /** * Get the value of id. @@ -46,10 +65,6 @@ public class NvdCveInfo { public void setId(String id) { this.id = id; } - /** - * a url. - */ - private String url; /** * Get the value of url. @@ -68,10 +83,6 @@ public class NvdCveInfo { public void setUrl(String url) { this.url = url; } - /** - * The 1.2 schema URL. - */ - private String oldSchemaVersionUrl; /** * Get the value of oldSchemaVersionUrl. @@ -90,10 +101,6 @@ public class NvdCveInfo { public void setOldSchemaVersionUrl(String oldSchemaVersionUrl) { this.oldSchemaVersionUrl = oldSchemaVersionUrl; } - /** - * a timestamp - epoch time. - */ - private long timestamp; /** * Get the value of timestamp - epoch time. @@ -112,10 +119,6 @@ public class NvdCveInfo { public void setTimestamp(long timestamp) { this.timestamp = timestamp; } - /** - * indicates whether or not this item should be updated. - */ - private boolean needsUpdate = true; /** * Get the value of needsUpdate. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java index 240b98873..3f4e0cbbb 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/ProcessTask.java @@ -23,6 +23,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import org.owasp.dependencycheck.data.nvdcve.CveDB; @@ -42,6 +43,7 @@ import org.xml.sax.SAXException; * * @author Jeremy Long */ +@ThreadSafe public class ProcessTask implements Callable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java index e086f2fae..34074a54f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/update/nvd/UpdateableNvdCve.java @@ -21,13 +21,15 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; +import javax.annotation.concurrent.NotThreadSafe; /** - * Contains a collection of updateable NvdCveInfo objects. This is used to determine which files need to be downloaded and - * processed. + * Contains a collection of updateable NvdCveInfo objects. This is used to + * determine which files need to be downloaded and processed. * * @author Jeremy Long */ +@NotThreadSafe public class UpdateableNvdCve implements Iterable, Iterator { /** @@ -36,7 +38,13 @@ public class UpdateableNvdCve implements Iterable, Iterator collection = new TreeMap<>(); /** - * Returns the collection of NvdCveInfo objects. This method is mainly used for testing. + * An internal iterator used to implement iterable. + */ + private Iterator> iterableContent = null; + + /** + * Returns the collection of NvdCveInfo objects. This method is mainly used + * for testing. * * @return the collection of NvdCveInfo objects */ @@ -63,7 +71,8 @@ public class UpdateableNvdCve implements Iterable, Iterator, Iterator> iterableContent = null; /** *

    @@ -118,7 +123,8 @@ public class UpdateableNvdCve implements Iterable, Iterator * This method is not thread safe.

    * - * @return true or false depending on whether or not another item exists in the collection + * @return true or false depending on whether or not another item exists in + * the collection */ @Override public boolean hasNext() { diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java index 08705b62d..9080a02ce 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Dependency.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -43,6 +44,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@NotThreadSafe public class Dependency implements Serializable, Comparable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Evidence.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Evidence.java index 0c33e7c1d..1130a3c06 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Evidence.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Evidence.java @@ -22,12 +22,14 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.HashCodeBuilder; import java.io.Serializable; +import javax.annotation.concurrent.ThreadSafe; /** * Evidence is a piece of information about a Dependency. * * @author Jeremy Long */ +@ThreadSafe public class Evidence implements Serializable, Comparable { /** @@ -44,6 +46,31 @@ public class Evidence implements Serializable, Comparable { */ private static final int MAGIC_HASH_MULTIPLIER = 67; + /** + * The name of the evidence. + */ + private String name; + + /** + * The source of the evidence. + */ + private String source; + + /** + * The value of the evidence. + */ + private String value; + + /** + * A value indicating if the Evidence has been "used" (aka read). + */ + private boolean used; + + /** + * The confidence level for the evidence. + */ + private Confidence confidence; + /** * Creates a new Evidence object. */ @@ -65,11 +92,6 @@ public class Evidence implements Serializable, Comparable { this.confidence = confidence; } - /** - * The name of the evidence. - */ - private String name; - /** * Get the value of name. * @@ -88,11 +110,6 @@ public class Evidence implements Serializable, Comparable { this.name = name; } - /** - * The source of the evidence. - */ - private String source; - /** * Get the value of source. * @@ -111,11 +128,6 @@ public class Evidence implements Serializable, Comparable { this.source = source; } - /** - * The value of the evidence. - */ - private String value; - /** * Get the value of value. * @@ -148,11 +160,6 @@ public class Evidence implements Serializable, Comparable { this.value = value; } - /** - * A value indicating if the Evidence has been "used" (aka read). - */ - private boolean used; - /** * Get the value of used. * @@ -171,11 +178,6 @@ public class Evidence implements Serializable, Comparable { this.used = used; } - /** - * The confidence level for the evidence. - */ - private Confidence confidence; - /** * Get the value of confidence. * 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 80283bd75..a7a2d6f7e 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 @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.commons.lang3.StringUtils; import org.owasp.dependencycheck.utils.DependencyVersion; import org.owasp.dependencycheck.utils.DependencyVersionUtil; @@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@NotThreadSafe public class EvidenceCollection implements Serializable, Iterable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Identifier.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Identifier.java index a9ff9ca41..35c50d168 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Identifier.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Identifier.java @@ -18,12 +18,14 @@ package org.owasp.dependencycheck.dependency; import java.io.Serializable; +import javax.annotation.concurrent.ThreadSafe; /** * In identifier such as a CPE or dependency coordinates (i.e. GAV). * * @author Jeremy Long */ +@ThreadSafe public class Identifier implements Serializable, Comparable { // diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Reference.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Reference.java index a3ebdc582..8c44bf566 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Reference.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Reference.java @@ -18,6 +18,7 @@ package org.owasp.dependencycheck.dependency; import java.io.Serializable; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang3.builder.CompareToBuilder; /** @@ -26,6 +27,7 @@ import org.apache.commons.lang3.builder.CompareToBuilder; * * @author Jeremy Long */ +@ThreadSafe public class Reference implements Serializable, Comparable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java index 3574fba1a..394b9d2f5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/Vulnerability.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.commons.lang3.builder.CompareToBuilder; /** @@ -30,6 +31,7 @@ import org.apache.commons.lang3.builder.CompareToBuilder; * * @author Jeremy Long */ +@NotThreadSafe public class Vulnerability implements Serializable, Comparable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerabilityComparator.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerabilityComparator.java index 3ce8e5a32..5432559a0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerabilityComparator.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerabilityComparator.java @@ -19,12 +19,14 @@ package org.owasp.dependencycheck.dependency; import java.io.Serializable; import java.util.Comparator; +import javax.annotation.concurrent.ThreadSafe; /** * Comparator for Vulnerability objects. * * @author Jeremy Long */ +@ThreadSafe public class VulnerabilityComparator implements Comparator, Serializable { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerableSoftware.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerableSoftware.java index 9c3570914..11eaefc6a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerableSoftware.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/dependency/VulnerableSoftware.java @@ -20,16 +20,19 @@ package org.owasp.dependencycheck.dependency; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang3.StringUtils; import org.owasp.dependencycheck.data.cpe.IndexEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * A record containing information about vulnerable software. This is referenced from a vulnerability. + * A record containing information about vulnerable software. This is referenced + * from a vulnerability. * * @author Jeremy Long */ +@ThreadSafe public class VulnerableSoftware extends IndexEntry implements Serializable, Comparable { /** @@ -41,6 +44,26 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp */ private static final long serialVersionUID = 307319490326651052L; + /** + * If present, indicates that previous version are vulnerable. + */ + private String previousVersion; + + /** + * The name of the cpe. + */ + private String name; + + /** + * The product version number. + */ + private String version; + + /** + * The product update version. + */ + private String update; + /** * Parse a CPE entry from the cpe string representation. * @@ -58,7 +81,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp /** *

    - * Parses a name attribute value, from the cpe.xml, into its corresponding parts: vendor, product, version, update.

    + * Parses a name attribute value, from the cpe.xml, into its corresponding + * parts: vendor, product, version, update.

    *

    * Example:

    *    cpe:/a:apache:struts:1.1:rc2 @@ -93,10 +117,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } } } - /** - * If present, indicates that previous version are vulnerable. - */ - private String previousVersion; /** * Indicates if previous versions of this software are vulnerable. @@ -126,7 +146,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } /** - * Standard equals implementation to compare this VulnerableSoftware to another object. + * Standard equals implementation to compare this VulnerableSoftware to + * another object. * * @param obj the object to compare * @return whether or not the objects are equal @@ -156,7 +177,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } /** - * Standard toString() implementation display the name and whether or not previous versions are also affected. + * Standard toString() implementation display the name and whether or not + * previous versions are also affected. * * @return a string representation of the object */ @@ -224,10 +246,9 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } /** - * Determines if the string passed in is a positive integer. - * To be counted as a positive integer, the string must only contain 0-9 - * and must not have any leading zeros (though "0" is a valid positive - * integer). + * Determines if the string passed in is a positive integer. To be counted + * as a positive integer, the string must only contain 0-9 and must not have + * any leading zeros (though "0" is a valid positive integer). * * @param str the string to test * @return true if the string only contains 0-9, otherwise false. @@ -251,10 +272,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } return true; } - /** - * The name of the cpe. - */ - private String name; /** * Get the value of name. @@ -273,10 +290,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp public void setName(String name) { this.name = name; } - /** - * The product version number. - */ - private String version; /** * Get the value of version. @@ -295,10 +308,6 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp public void setVersion(String version) { this.version = version; } - /** - * The product update version. - */ - private String update; /** * Get the value of update. @@ -341,7 +350,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } /** - * Replaces '+' with '%2B' and then URL Decodes the string attempting first UTF-8, then ASCII, then default. + * Replaces '+' with '%2B' and then URL Decodes the string attempting first + * UTF-8, then ASCII, then default. * * @param string the string to URL Decode * @return the URL Decoded string @@ -362,7 +372,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp } /** - * Call {@link java.net.URLDecoder#decode(String)} to URL decode using the default encoding. + * Call {@link java.net.URLDecoder#decode(String)} to URL decode using the + * default encoding. * * @param text www-form-encoded URL to decode * @return the newly decoded String diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java index 3406b9900..4e0f00ead 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/DependencyNotFoundException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception used when a dependency could not be found. * * @author Jeremy Long */ +@ThreadSafe public class DependencyNotFoundException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java index e7bf7e9dd..2c662ac98 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ExceptionCollection.java @@ -21,12 +21,14 @@ import java.io.PrintStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; /** * A collection of several exceptions. * * @author Jeremy Long */ +@NotThreadSafe public class ExceptionCollection extends Exception { /** * The serial version uid. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/H2DBLockException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/H2DBLockException.java index 55e496592..5b4ae2dc9 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/H2DBLockException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/H2DBLockException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception used when trying to obtain a lock on the H2 database. * * @author Jeremy Long */ +@ThreadSafe public class H2DBLockException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/InitializationException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/InitializationException.java index f818ebff6..0e36540f5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/InitializationException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/InitializationException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception used when initializing analyzers. * * @author Jeremy Long */ +@ThreadSafe public class InitializationException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/NoDataException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/NoDataException.java index 2e6c7d94c..5e0e11a88 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/NoDataException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/NoDataException.java @@ -18,12 +18,14 @@ package org.owasp.dependencycheck.exception; import java.io.IOException; +import javax.annotation.concurrent.ThreadSafe; /** * An exception used when the data needed does not exist to perform analysis. * * @author Jeremy Long */ +@ThreadSafe public class NoDataException extends IOException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java index 7199b3520..7942ac008 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ReportException.java @@ -17,11 +17,14 @@ */ package org.owasp.dependencycheck.exception; +import javax.annotation.concurrent.ThreadSafe; + /** * An exception used when generating reports. * * @author Jeremy Long */ +@ThreadSafe public class ReportException extends Exception { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ScanAgentException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ScanAgentException.java index 5f4c5dce9..2e742f31f 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ScanAgentException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/exception/ScanAgentException.java @@ -18,12 +18,15 @@ package org.owasp.dependencycheck.exception; import java.io.IOException; +import javax.annotation.concurrent.ThreadSafe; /** - * An exception used when using @{link DependencyCheckScanAgent} to conduct a scan and the scan fails. + * An exception used when using @{link DependencyCheckScanAgent} to conduct a + * scan and the scan fails. * * @author Steve Springett */ +@ThreadSafe public class ScanAgentException extends IOException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java index 4eb456176..adf89bfcb 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/EscapeTool.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.reporting; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Set; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.lang3.StringEscapeUtils; import org.owasp.dependencycheck.dependency.Identifier; import org.slf4j.Logger; @@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public class EscapeTool { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java index 66a4540b9..70208794e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java @@ -19,7 +19,6 @@ package org.owasp.dependencycheck.reporting; import java.util.List; -import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; @@ -35,6 +34,7 @@ import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; @@ -59,6 +59,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@NotThreadSafe public class ReportGenerator { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java index 73a05ee31..fc6bf446c 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.reporting; +import javax.annotation.concurrent.ThreadSafe; import org.apache.velocity.runtime.RuntimeServices; import org.apache.velocity.runtime.log.LogChute; import org.slf4j.Logger; @@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory; * * @author Steve Springett */ +@ThreadSafe public class VelocityLoggerRedirect implements LogChute { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DBUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DBUtils.java index 3dd1042fc..bdc23442b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DBUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DBUtils.java @@ -21,14 +21,17 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.data.nvdcve.DatabaseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + * Collection of utility methods for working with database objects. * * @author Jeremy Long */ +@ThreadSafe public final class DBUtils { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java index 782b32379..415793681 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DateUtil.java @@ -17,10 +17,13 @@ */ package org.owasp.dependencycheck.utils; +import javax.annotation.concurrent.ThreadSafe; + /** * * @author Jeremy Long */ +@ThreadSafe public final class DateUtil { /** @@ -30,9 +33,10 @@ public final class DateUtil { } /** - * Determines if the epoch date is within the range specified of the compareTo epoch time. This takes the - * (compareTo-date)/1000/60/60/24 to get the number of days. If the calculated days is less then the range the date - * is considered valid. + * Determines if the epoch date is within the range specified of the + * compareTo epoch time. This takes the (compareTo-date)/1000/60/60/24 to + * get the number of days. If the calculated days is less then the range the + * date is considered valid. * * @param date the date to be checked. * @param compareTo the date to compare to. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java index ff8bf15c8..1d5756468 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersion.java @@ -22,6 +22,7 @@ import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.commons.lang3.StringUtils; /** @@ -38,8 +39,14 @@ import org.apache.commons.lang3.StringUtils; * * @author Jeremy Long */ +@NotThreadSafe public class DependencyVersion implements Iterable, Comparable { + /** + * A list of the version parts. + */ + private List versionParts; + /** * Constructor for a empty DependencyVersion. */ @@ -78,10 +85,6 @@ public class DependencyVersion implements Iterable, Comparable versionParts; /** * Get the value of versionParts. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java index b4ac9cbd6..4bf15f62b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/DependencyVersionUtil.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; /** *

    @@ -29,6 +30,7 @@ import java.util.regex.Pattern; * * @author Jeremy Long */ +@ThreadSafe public final class DependencyVersionUtil { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/ExtractionUtil.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/ExtractionUtil.java index fe4b07666..8f925f858 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/ExtractionUtil.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/ExtractionUtil.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import javax.annotation.concurrent.ThreadSafe; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveInputStream; @@ -43,6 +44,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@ThreadSafe public final class ExtractionUtil { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileFilterBuilder.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileFilterBuilder.java index f320e0604..36c1ef4c0 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileFilterBuilder.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/FileFilterBuilder.java @@ -29,6 +29,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.annotation.concurrent.NotThreadSafe; /** *

    @@ -43,6 +44,7 @@ import java.util.Set; * @author Dale Visser * @see Builder pattern */ +@NotThreadSafe public class FileFilterBuilder { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Filter.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Filter.java index 554a70dc1..3a303d1c2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Filter.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/Filter.java @@ -2,6 +2,7 @@ package org.owasp.dependencycheck.utils; import java.util.Iterator; import java.util.NoSuchElementException; +import javax.annotation.concurrent.NotThreadSafe; /** * This is an abstract filter that can be used to filter iterable list. @@ -14,6 +15,7 @@ import java.util.NoSuchElementException; * * @param the type to filter */ +@NotThreadSafe public abstract class Filter { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java index 8f8929bc0..88afce929 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java @@ -22,8 +22,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileLock; import java.util.Date; -import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory; -import org.owasp.dependencycheck.data.nvdcve.CveDB; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.exception.H2DBLockException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +31,7 @@ import org.slf4j.LoggerFactory; * * @author Jeremy Long */ +@NotThreadSafe public class H2DBLock { /** @@ -54,14 +54,14 @@ public class H2DBLock { * The configured settings. */ private final Settings settings; - /** - * Whether the database connection is using H2. - */ - private final boolean isH2Connection; - public H2DBLock(Settings settings, boolean isH2Connection) { + /** + * Constructs a new H2DB Lock object with the configured settings. + * + * @param settings the configured settings + */ + public H2DBLock(Settings settings) { this.settings = settings; - this.isH2Connection = isH2Connection; } /** @@ -79,49 +79,47 @@ public class H2DBLock { * @throws H2DBLockException thrown if a lock could not be obtained */ public void lock() throws H2DBLockException { - if (isH2Connection) { - try { - final File dir = settings.getDataDirectory(); - lockFile = new File(dir, "dc.update.lock"); - if (lockFile.isFile() && getFileAge(lockFile) > 5 && !lockFile.delete()) { - LOGGER.warn("An old db update lock file was found but the system was unable to delete " - + "the file. Consider manually deleting {}", lockFile.getAbsolutePath()); - } - int ctr = 0; - do { - try { - if (!lockFile.exists() && lockFile.createNewFile()) { - file = new RandomAccessFile(lockFile, "rw"); - lock = file.getChannel().lock(); - } - } catch (IOException ex) { - LOGGER.trace("Expected error as another thread has likely locked the file", ex); - } finally { - if (lock == null && file != null) { - try { - file.close(); - } catch (IOException ex) { - LOGGER.trace("Unable to close the ulFile", ex); - } - } - } - if (lock == null || !lock.isValid()) { - try { - LOGGER.debug("Sleeping thread {} for 5 seconds because we could not obtain the update lock.", - Thread.currentThread().getName()); - Thread.sleep(5000); - } catch (InterruptedException ex) { - LOGGER.trace("ignorable error, sleep was interrupted.", ex); - Thread.currentThread().interrupt(); - } - } - } while (++ctr < 60 && (lock == null || !lock.isValid())); - if (lock == null || !lock.isValid()) { - throw new H2DBLockException("Unable to obtain the update lock, skipping the database update. Skippinig the database update."); - } - } catch (IOException ex) { - throw new H2DBLockException(ex.getMessage(), ex); + try { + final File dir = settings.getDataDirectory(); + lockFile = new File(dir, "dc.update.lock"); + if (lockFile.isFile() && getFileAge(lockFile) > 5 && !lockFile.delete()) { + LOGGER.warn("An old db update lock file was found but the system was unable to delete " + + "the file. Consider manually deleting {}", lockFile.getAbsolutePath()); } + int ctr = 0; + do { + try { + if (!lockFile.exists() && lockFile.createNewFile()) { + file = new RandomAccessFile(lockFile, "rw"); + lock = file.getChannel().lock(); + } + } catch (IOException ex) { + LOGGER.trace("Expected error as another thread has likely locked the file", ex); + } finally { + if (lock == null && file != null) { + try { + file.close(); + } catch (IOException ex) { + LOGGER.trace("Unable to close the ulFile", ex); + } + } + } + if (lock == null || !lock.isValid()) { + try { + LOGGER.debug("Sleeping thread {} for 5 seconds because we could not obtain the update lock.", + Thread.currentThread().getName()); + Thread.sleep(5000); + } catch (InterruptedException ex) { + LOGGER.trace("ignorable error, sleep was interrupted.", ex); + Thread.currentThread().interrupt(); + } + } + } while (++ctr < 60 && (lock == null || !lock.isValid())); + if (lock == null || !lock.isValid()) { + throw new H2DBLockException("Unable to obtain the update lock, skipping the database update. Skippinig the database update."); + } + } catch (IOException ex) { + throw new H2DBLockException(ex.getMessage(), ex); } } 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 index 49f42570e..90a2eb3dd 100644 --- 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 @@ -17,6 +17,8 @@ */ package org.owasp.dependencycheck.utils; +import javax.annotation.concurrent.ThreadSafe; + /** * A generic pair of elements. * @@ -25,6 +27,7 @@ package org.owasp.dependencycheck.utils; * * @author Jeremy Long */ +@ThreadSafe public class Pair { /** * The left element of the pair. diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/UrlStringUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/UrlStringUtils.java index 6e2e63dbb..d96819a4d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/UrlStringUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/UrlStringUtils.java @@ -21,15 +21,15 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; /** * * @author Jeremy Long */ +@ThreadSafe public final class UrlStringUtils { /** @@ -44,8 +44,11 @@ public final class UrlStringUtils { * A listing of domain parts that should not be used as evidence. Yes, this * is an incomplete list. */ - private static final Set IGNORE_LIST = new HashSet<>( - Arrays.asList("www", "com", "org", "gov", "info", "name", "net", "pro", "tel", "mobi", "xxx")); + private static final String[] IGNORE_LIST = {"www", "com", "org", "gov", "info", "name", "net", "pro", "tel", "mobi", "xxx"}; + + static { + Arrays.sort(IGNORE_LIST); + } /** * Private constructor for a utility class. @@ -96,7 +99,7 @@ public final class UrlStringUtils { //add the domain except www and the tld. for (int i = 0; i < domain.length - 1; i++) { final String sub = domain[i]; - if (!IGNORE_LIST.contains(sub.toLowerCase())) { + if (Arrays.binarySearch(IGNORE_LIST, sub.toLowerCase()) < 0) { importantParts.add(sub); } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java index 9e436d9bc..341ebd558 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlEntity.java @@ -3,6 +3,7 @@ package org.owasp.dependencycheck.xml; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import javax.annotation.concurrent.ThreadSafe; /** * This is a utility class to convert named XML Entities (such as ø) into @@ -12,6 +13,7 @@ import java.util.Map; * * @author https://stackoverflow.com/users/823393/oldcurmudgeon */ +@ThreadSafe public final class XmlEntity { /** @@ -20,7 +22,7 @@ public final class XmlEntity { private static final Map SPECIALS; // - /** + /* * Create a map HTML Named Entities to their numeric equivalent. Derived * from Wikipedia * http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java index cec6f0407..c089cec1b 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/XmlInputStream.java @@ -3,6 +3,7 @@ package org.owasp.dependencycheck.xml; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; +import javax.annotation.concurrent.NotThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +22,7 @@ import org.slf4j.LoggerFactory; * * @author https://stackoverflow.com/users/823393/oldcurmudgeon */ +@NotThreadSafe public class XmlInputStream extends FilterInputStream { /** @@ -34,11 +36,11 @@ public class XmlInputStream extends FilterInputStream { /** * Holder for everything we've read. */ - private StringBuilder red = new StringBuilder(); + private final StringBuilder red = new StringBuilder(); /** * Data that needs to be pushed back. */ - private StringBuilder pushBack = new StringBuilder(); + private final StringBuilder pushBack = new StringBuilder(); /** * How much we've given them. */ diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java index f73dc4382..15a041d7e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintErrorHandler.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.xml.hints; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,6 +30,7 @@ import org.xml.sax.SAXParseException; * * @author Jeremy Long */ +@ThreadSafe public class HintErrorHandler implements ErrorHandler { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java index 676067c5e..6fef7de80 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintHandler.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.xml.hints; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.xml.suppression.PropertyType; import org.xml.sax.Attributes; @@ -30,6 +31,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author Jeremy Long */ +@NotThreadSafe public class HintHandler extends DefaultHandler { // diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java index 4b5b19c6e..ec9267ed5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParseException.java @@ -18,12 +18,14 @@ package org.owasp.dependencycheck.xml.hints; import java.io.IOException; +import javax.annotation.concurrent.ThreadSafe; /** * An exception used when parsing a suppression rule file fails. * * @author Jeremy Long */ +@ThreadSafe public class HintParseException extends IOException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java index 7f440049a..eed43c680 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintParser.java @@ -24,6 +24,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; @@ -41,6 +43,7 @@ import org.xml.sax.XMLReader; * * @author Jeremy Long */ +@ThreadSafe public class HintParser { /** @@ -73,25 +76,52 @@ public class HintParser { */ private static final String HINT_SCHEMA_OLD = "schema/dependency-hint.1.1.xsd"; + /** + * The hint rules. + */ + private HintRule[] hintRules; + /** + * The vendor duplicating hint rules. + */ + private VendorDuplicatingHintRule[] vendorDuplicatingHintRules; + + /** + * Returns the hint rules. + * + * @return the hint rules + */ + @SuppressWarnings({"EI_EXPOSE_REP", "EI_EXPOSE_REP2"}) + public HintRule[] getHintRules() { + return hintRules; + } + + /** + * Returns the vendor duplicating hint rules. + * + * @return the vendor duplicating hint rules + */ + public VendorDuplicatingHintRule[] getVendorDuplicatingHintRules() { + return vendorDuplicatingHintRules; + } + /** * Parses the given XML file and returns a list of the hints contained. * * @param file an XML file containing hints - * @return a list of hint rules * @throws HintParseException thrown if the XML file cannot be parsed */ - public Hints parseHints(File file) throws HintParseException { + public void parseHints(File file) throws HintParseException { //TODO there must be a better way to determine which schema to use for validation. try { try (FileInputStream fis = new FileInputStream(file)) { - return parseHints(fis); + parseHints(fis); } catch (IOException ex) { LOGGER.debug("", ex); throw new HintParseException(ex); } } catch (SAXException ex) { try (FileInputStream fis = new FileInputStream(file)) { - return parseHints(fis, HINT_SCHEMA_OLD); + parseHints(fis, HINT_SCHEMA_OLD); } catch (SAXException | IOException ex1) { throw new HintParseException(ex); } @@ -103,12 +133,11 @@ public class HintParser { * contained. * * @param inputStream an InputStream containing hint rules - * @return a list of hint rules * @throws HintParseException thrown if the XML cannot be parsed * @throws SAXException thrown if the XML cannot be parsed */ - public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException { - return parseHints(inputStream, HINT_SCHEMA); + public void parseHints(InputStream inputStream) throws HintParseException, SAXException { + parseHints(inputStream, HINT_SCHEMA); } /** @@ -117,11 +146,10 @@ public class HintParser { * * @param inputStream an InputStream containing hint rules * @param schema the XSD to use to validate the XML against - * @return a list of hint rules * @throws HintParseException thrown if the XML cannot be parsed * @throws SAXException thrown if the XML cannot be parsed */ - private Hints parseHints(InputStream inputStream, String schema) throws HintParseException, SAXException { + private void parseHints(InputStream inputStream, String schema) throws HintParseException, SAXException { try (InputStream schemaStream = FileUtils.getResourceAsStream(schema)) { final HintHandler handler = new HintHandler(); final SAXParser saxParser = XmlUtils.buildSecureSaxParser(schemaStream); @@ -131,10 +159,10 @@ public class HintParser { try (Reader reader = new InputStreamReader(inputStream, "UTF-8")) { final InputSource in = new InputSource(reader); xmlReader.parse(in); - final Hints hints = new Hints(); - hints.setHintRules(handler.getHintRules()); - hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules()); - return hints; + final List tmpRules = handler.getHintRules(); + this.hintRules = tmpRules.toArray(new HintRule[tmpRules.size()]); + final List tmpVDR = handler.getVendorDuplicatingHintRules(); + this.vendorDuplicatingHintRules = tmpVDR.toArray(new VendorDuplicatingHintRule[tmpVDR.size()]); } } catch (ParserConfigurationException | FileNotFoundException ex) { LOGGER.debug("", ex); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java index e92cbdda9..1cf7e560d 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/HintRule.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.xml.hints; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Evidence; import org.owasp.dependencycheck.xml.suppression.PropertyType; @@ -30,6 +31,7 @@ import org.owasp.dependencycheck.xml.suppression.PropertyType; * * @author Jeremy Long */ +@NotThreadSafe public class HintRule { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java deleted file mode 100644 index d44ed7984..000000000 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/Hints.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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) 2016 Jeremy Long. All Rights Reserved. - */ -package org.owasp.dependencycheck.xml.hints; - -import java.util.List; - -/** - * A collection of hint rules. - * - * @author Jeremy Long - */ -public class Hints { - - /** - * The list of hint rules. - */ - private List hintRules; - - /** - * The duplicating hint rules. - */ - private List vendorDuplicatingHintRules; - - /** - * Get the value of hintRules. - * - * @return the value of hintRules - */ - public List getHintRules() { - return hintRules; - } - - /** - * Set the value of hintRules. - * - * @param hintRules new value of hintRules - */ - public void setHintRules(List hintRules) { - this.hintRules = hintRules; - } - - /** - * Get the value of vendorDuplicatingHintRules. - * - * @return the value of vendorDuplicatingHintRules - */ - public List getVendorDuplicatingHintRules() { - return vendorDuplicatingHintRules; - } - - /** - * Set the value of vendorDuplicatingHintRules. - * - * @param vendorDuplicatingHintRules new value of vendorDuplicatingHintRules - */ - public void setVendorDuplicatingHintRules(List vendorDuplicatingHintRules) { - this.vendorDuplicatingHintRules = vendorDuplicatingHintRules; - } -} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/VendorDuplicatingHintRule.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/VendorDuplicatingHintRule.java index c9a02a7bb..4918eb8ea 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/VendorDuplicatingHintRule.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/hints/VendorDuplicatingHintRule.java @@ -17,6 +17,8 @@ */ package org.owasp.dependencycheck.xml.hints; +import javax.annotation.concurrent.ThreadSafe; + /** * Used to duplicate vendor evidence within a collection. The intent is if any * evidence is found in a collection that matches the value given the evidence @@ -24,6 +26,7 @@ package org.owasp.dependencycheck.xml.hints; * * @author Jeremy Long */ +@ThreadSafe public class VendorDuplicatingHintRule { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/License.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/License.java index 108a94824..17a4ddfc7 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/License.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/License.java @@ -17,10 +17,13 @@ */ package org.owasp.dependencycheck.xml.pom; +import javax.annotation.concurrent.ThreadSafe; + /** * * @author jeremy */ +@ThreadSafe public class License { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java index 2168ec950..4759121b5 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/Model.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.xml.pom; import java.util.ArrayList; import java.util.List; import java.util.Properties; +import javax.annotation.concurrent.NotThreadSafe; import org.apache.commons.lang3.text.StrLookup; import org.apache.commons.lang3.text.StrSubstitutor; @@ -29,6 +30,7 @@ import org.apache.commons.lang3.text.StrSubstitutor; * * @author jeremy */ +@NotThreadSafe public class Model { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java index a073b5ff6..91b2cc9bc 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomHandler.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.xml.pom; import java.util.ArrayDeque; import java.util.Deque; +import javax.annotation.concurrent.NotThreadSafe; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; @@ -28,6 +29,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author Jeremy Long */ +@NotThreadSafe public class PomHandler extends DefaultHandler { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParseException.java index be98e127c..6accd94fa 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParseException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParseException.java @@ -18,12 +18,14 @@ package org.owasp.dependencycheck.xml.pom; import java.io.IOException; +import javax.annotation.concurrent.ThreadSafe; /** * An exception used when parsing a suppression rule file fails. * * @author Jeremy Long */ +@ThreadSafe public class PomParseException extends IOException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java index 155b0048a..6bc9469d2 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomParser.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import org.apache.commons.io.ByteOrderMark; @@ -42,6 +43,7 @@ import org.xml.sax.XMLReader; * * @author Jeremy Long */ +@ThreadSafe public class PomParser { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java index 4a6d2e8fc..969974490 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/pom/PomUtils.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.IOException; import java.util.jar.JarFile; import java.util.zip.ZipEntry; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.analyzer.JarAnalyzer; import org.owasp.dependencycheck.analyzer.exception.AnalysisException; import org.owasp.dependencycheck.dependency.Dependency; @@ -31,6 +32,7 @@ import org.slf4j.LoggerFactory; * * @author jeremy */ +@ThreadSafe public final class PomUtils { /** @@ -52,6 +54,7 @@ public final class PomUtils { * or parsing the POM {@link Model} object */ public static Model readPom(File file) throws AnalysisException { + //noinspection CaughtExceptionImmediatelyRethrown try { final PomParser parser = new PomParser(); final Model model = parser.parse(file); @@ -85,6 +88,7 @@ public final class PomUtils { final ZipEntry entry = jar.getEntry(path); Model model = null; if (entry != null) { //should never be null + //noinspection CaughtExceptionImmediatelyRethrown try { final PomParser parser = new PomParser(); model = parser.parse(jar.getInputStream(entry)); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/PropertyType.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/PropertyType.java index 8c1fb794f..381a58962 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/PropertyType.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/PropertyType.java @@ -18,6 +18,7 @@ package org.owasp.dependencycheck.xml.suppression; import java.util.regex.Pattern; +import javax.annotation.concurrent.ThreadSafe; /** * A simple PropertyType used to represent a string value that could be used as a regular expression or could be case @@ -25,6 +26,7 @@ import java.util.regex.Pattern; * * @author Jeremy Long */ +@ThreadSafe public class PropertyType { // diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java index d476f1aaa..6647759b6 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionErrorHandler.java @@ -17,6 +17,7 @@ */ package org.owasp.dependencycheck.xml.suppression; +import javax.annotation.concurrent.ThreadSafe; import org.owasp.dependencycheck.utils.XmlUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,6 +30,7 @@ import org.xml.sax.SAXParseException; * * @author Jeremy Long */ +@ThreadSafe public class SuppressionErrorHandler implements ErrorHandler { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandler.java index ec1b7b1c2..b8d457f88 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandler.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionHandler.java @@ -19,6 +19,7 @@ package org.owasp.dependencycheck.xml.suppression; import java.util.ArrayList; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; @@ -28,6 +29,7 @@ import org.xml.sax.helpers.DefaultHandler; * * @author Jeremy Long */ +@NotThreadSafe public class SuppressionHandler extends DefaultHandler { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParseException.java index d0d5c87df..7a56add3a 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParseException.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParseException.java @@ -18,12 +18,14 @@ package org.owasp.dependencycheck.xml.suppression; import java.io.IOException; +import javax.annotation.concurrent.ThreadSafe; /** * An exception used when parsing a suppression rule file fails. * * @author Jeremy Long */ +@ThreadSafe public class SuppressionParseException extends IOException { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java index a2f039a07..984c9468e 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionParser.java @@ -25,6 +25,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.List; +import javax.annotation.concurrent.ThreadSafe; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; @@ -42,6 +43,7 @@ import org.xml.sax.XMLReader; * * @author Jeremy Long */ +@ThreadSafe public class SuppressionParser { /** diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionRule.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionRule.java index ca6c7ab05..875d33126 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionRule.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/xml/suppression/SuppressionRule.java @@ -20,6 +20,7 @@ package org.owasp.dependencycheck.xml.suppression; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; import org.owasp.dependencycheck.dependency.Dependency; import org.owasp.dependencycheck.dependency.Identifier; import org.owasp.dependencycheck.dependency.Vulnerability; @@ -28,6 +29,7 @@ import org.owasp.dependencycheck.dependency.Vulnerability; * * @author Jeremy Long */ +@NotThreadSafe public class SuppressionRule { /** diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/AnalysisTaskTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/AnalysisTaskTest.java index d54c16dd4..d66b5c98b 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/AnalysisTaskTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/AnalysisTaskTest.java @@ -28,7 +28,7 @@ public class AnalysisTaskTest extends BaseTest { @Test public void shouldAnalyzeReturnsTrueForNonFileTypeAnalyzers() { - AnalysisTask instance = new AnalysisTask(new HintAnalyzer(), null, null, null, null); + AnalysisTask instance = new AnalysisTask(new HintAnalyzer(), null, null, null); boolean shouldAnalyze = instance.shouldAnalyze(); assertTrue(shouldAnalyze); } @@ -44,7 +44,7 @@ public class AnalysisTaskTest extends BaseTest { result = true; }}; - AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, null, null, getSettings()); + AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, null, null); boolean shouldAnalyze = analysisTask.shouldAnalyze(); assertTrue(shouldAnalyze); @@ -61,7 +61,7 @@ public class AnalysisTaskTest extends BaseTest { result = false; }}; - AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, null, null, getSettings()); + AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, null, null); boolean shouldAnalyze = analysisTask.shouldAnalyze(); assertFalse(shouldAnalyze); @@ -69,7 +69,7 @@ public class AnalysisTaskTest extends BaseTest { @Test public void taskAnalyzes() throws Exception { - final AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, engine, null, getSettings()); + final AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, engine, null); new Expectations(analysisTask) {{ analysisTask.shouldAnalyze(); result = true; @@ -85,7 +85,7 @@ public class AnalysisTaskTest extends BaseTest { @Test public void taskDoesNothingIfItShouldNotAnalyze() throws Exception { - final AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, engine, null, getSettings()); + final AnalysisTask analysisTask = new AnalysisTask(fileTypeAnalyzer, dependency, engine, null); new Expectations(analysisTask) {{ analysisTask.shouldAnalyze(); result = false; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java index 03dcf1e91..e32e28ab4 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineIT.java @@ -53,7 +53,7 @@ public class EngineIT extends BaseDBTestCase { Engine instance = new Engine(getSettings()); getSettings().setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); instance.scan(testClasses); - assertTrue(instance.getDependencies().size() > 0); + assertTrue(instance.getDependencies().length > 0); try { instance.analyzeDependencies(); } catch (ExceptionCollection ex) { diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineModeIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineModeIT.java index ad63a608f..a749eaec7 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineModeIT.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineModeIT.java @@ -64,7 +64,7 @@ public class EngineModeIT extends BaseTest { @Test public void testEvidenceCollectionAndEvidenceProcessingModes() throws Exception { - List dependencies; + Dependency[] dependencies; try (Engine engine = new Engine(Engine.Mode.EVIDENCE_COLLECTION, getSettings())) { engine.openDatabase(); //does nothing in the current mode assertDatabase(false); @@ -78,8 +78,8 @@ public class EngineModeIT extends BaseTest { engine.scan(file); engine.analyzeDependencies(); dependencies = engine.getDependencies(); - assertThat(dependencies.size(), is(1)); - Dependency dependency = dependencies.get(0); + assertThat(dependencies.length, is(1)); + Dependency dependency = dependencies[0]; assertTrue(dependency.getVendorEvidence().toString().toLowerCase().contains("apache")); assertTrue(dependency.getVendorEvidence().getWeighting().contains("apache")); assertTrue(dependency.getVulnerabilities().isEmpty()); @@ -94,9 +94,9 @@ public class EngineModeIT extends BaseTest { for (AnalysisPhase phase : Engine.Mode.EVIDENCE_COLLECTION.getPhases()) { assertThat(engine.getAnalyzers(phase), is(nullValue())); } - engine.setDependencies(dependencies); + engine.addDependency(dependencies[0]); engine.analyzeDependencies(); - Dependency dependency = dependencies.get(0); + Dependency dependency = dependencies[0]; assertFalse(dependency.getVulnerabilities().isEmpty()); } } @@ -112,9 +112,9 @@ public class EngineModeIT extends BaseTest { File file = BaseTest.getResourceAsFile(this, "struts2-core-2.1.2.jar"); engine.scan(file); engine.analyzeDependencies(); - List dependencies = engine.getDependencies(); - assertThat(dependencies.size(), is(1)); - Dependency dependency = dependencies.get(0); + Dependency[] dependencies = engine.getDependencies(); + assertThat(dependencies.length, is(1)); + Dependency dependency = dependencies[0]; assertTrue(dependency.getVendorEvidence().toString().toLowerCase().contains("apache")); assertTrue(dependency.getVendorEvidence().getWeighting().contains("apache")); assertFalse(dependency.getVulnerabilities().isEmpty()); diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineTest.java index 3934d8b3c..fff73addb 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/EngineTest.java @@ -60,12 +60,12 @@ public class EngineTest extends BaseDBTestCase { Dependency dwr = instance.scanFile(file); file = BaseTest.getResourceAsFile(this, "org.mortbay.jmx.jar"); instance.scanFile(file); - assertEquals(2, instance.getDependencies().size()); + assertEquals(2, instance.getDependencies().length); file = BaseTest.getResourceAsFile(this, "dwr.jar"); Dependency secondDwr = instance.scanFile(file); - assertEquals(2, instance.getDependencies().size()); + assertEquals(2, instance.getDependencies().length); assertEquals(dwr, secondDwr); } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIT.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIT.java index 0f8d8a82c..22ae8f9f0 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIT.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/ArchiveAnalyzerIT.java @@ -138,9 +138,9 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { File file = BaseTest.getResourceAsFile(this, "daytrader-ear-2.1.7.ear"); Dependency dependency = new Dependency(file); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; instance.analyze(dependency, engine); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); @@ -169,9 +169,9 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; instance.analyze(dependency, engine); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); @@ -203,9 +203,9 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; instance.analyze(dependency, engine); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); assertTrue(initial_size < ending_size); @@ -234,11 +234,11 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; //instance.analyze(dependency, engine); engine.scan(file); engine.analyzeDependencies(); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); assertTrue(initial_size < ending_size); @@ -262,10 +262,10 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false); getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; engine.scan(file); engine.analyzeDependencies(); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); assertTrue(initial_size < ending_size); } finally { @@ -291,10 +291,10 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; engine.scan(file); engine.analyzeDependencies(); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); assertTrue(initial_size < ending_size); @@ -318,10 +318,10 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false); getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; engine.scan(file); engine.analyzeDependencies(); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); assertTrue(initial_size < ending_size); } finally { @@ -346,7 +346,7 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { getSettings().setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false); getSettings().setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false); Engine engine = new Engine(getSettings()); - int initial_size = engine.getDependencies().size(); + int initial_size = engine.getDependencies().length; // boolean failed = false; // try { instance.analyze(dependency, engine); @@ -354,7 +354,7 @@ public class ArchiveAnalyzerIT extends BaseDBTestCase { // failed = true; // } // assertTrue(failed); - int ending_size = engine.getDependencies().size(); + int ending_size = engine.getDependencies().length; engine.cleanup(); assertEquals(initial_size, ending_size); } finally { 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 9afbfbf44..8e1a902b5 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 @@ -58,7 +58,7 @@ public class ArchiveAnalyzerTest extends BaseTest { private boolean isPreviouslyLoaded(String className) { try { - Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", new Class[]{String.class}); + Method m = ClassLoader.class.getDeclaredMethod("findLoadedClass", String.class); m.setAccessible(true); Object t = m.invoke(Thread.currentThread().getContextClassLoader(), className); return t != null; diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java index 4163bc728..e7de753bf 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/CMakeAnalyzerTest.java @@ -154,9 +154,9 @@ public class CMakeAnalyzerTest extends BaseDBTestCase { assertVersionEvidence(result, "55.18.102"); assertFalse("ALIASOF_ prefix shouldn't be present.", Pattern.compile("\\bALIASOF_\\w+").matcher(result.getProductEvidence().toString()).find()); - final List dependencies = engine.getDependencies(); - assertEquals("Number of additional dependencies should be 4.", 4, dependencies.size()); - final Dependency last = dependencies.get(3); + final Dependency[] dependencies = engine.getDependencies(); + assertEquals("Number of additional dependencies should be 4.", 4, dependencies.length); + final Dependency last = dependencies[3]; assertProductEvidence(last, "libavresample"); assertVersionEvidence(last, "1.0.1"); } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.java index 9125f6d28..ee6c5ddfe 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/DependencyBundlingAnalyzerTest.java @@ -79,7 +79,7 @@ public class DependencyBundlingAnalyzerTest extends BaseTest { new Verifications() {{ engineMock.getDependencies(); - times = 2; + times = 1; }}; } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java index 55ef90163..23d582266 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/HintAnalyzerTest.java @@ -76,7 +76,7 @@ public class HintAnalyzerTest extends BaseDBTestCase { engine.scan(guice); engine.scan(spring); - engine.analyzeDependencies(); + engine.analyzeDependencies(); Dependency gdep = null; Dependency sdep = null; for (Dependency d : engine.getDependencies()) { diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java index e3d880e59..92f8b73ad 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/analyzer/RubyBundleAuditAnalyzerTest.java @@ -17,12 +17,14 @@ */ package org.owasp.dependencycheck.analyzer; +import edu.emory.mathcs.backport.java.util.Arrays; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.io.File; +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -125,10 +127,11 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase { final String resource = "ruby/vulnerable/gems/rails-4.1.15/Gemfile.lock"; final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, resource)); analyzer.analyze(result, engine); - int size = engine.getDependencies().size(); + final Dependency[] dependencies = engine.getDependencies(); + final int size = dependencies.length; assertTrue(size >= 1); boolean found = false; - for (Dependency dependency : engine.getDependencies()) { + for (Dependency dependency : dependencies) { found = dependency.getProductEvidence().toString().toLowerCase().contains("redcarpet"); found &= dependency.getVersionEvidence().toString().toLowerCase().contains("2.2.2"); found &= dependency.getFilePath().endsWith(resource); @@ -157,7 +160,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase { final Dependency result = new Dependency(BaseTest.getResourceAsFile(this, "ruby/vulnerable/gems/sinatra/Gemfile.lock")); analyzer.analyze(result, engine); - Dependency dependency = engine.getDependencies().get(0); + Dependency dependency = engine.getDependencies()[0]; Vulnerability vulnerability = dependency.getVulnerabilities().first(); assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0); @@ -211,39 +214,40 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase { Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex); return; } - List dependencies = engine.getDependencies(); + List dependencies = new ArrayList<>(Arrays.asList(engine.getDependencies())); LOGGER.info("{} dependencies found.", dependencies.size()); - Iterator dIterator = dependencies.iterator(); - while (dIterator.hasNext()) { - Dependency dept = dIterator.next(); - LOGGER.info("dept path: {}", dept.getActualFilePath()); - - Set identifiers = dept.getIdentifiers(); - Iterator idIterator = identifiers.iterator(); - while (idIterator.hasNext()) { - Identifier id = idIterator.next(); - LOGGER.info(" Identifier: {}, type={}, url={}, conf={}", id.getValue(), id.getType(), id.getUrl(), id.getConfidence()); - } - - Set prodEv = dept.getProductEvidence().getEvidence(); - Iterator it = prodEv.iterator(); - while (it.hasNext()) { - Evidence e = it.next(); - LOGGER.info(" prod: name={}, value={}, source={}, confidence={}", e.getName(), e.getValue(), e.getSource(), e.getConfidence()); - } - Set versionEv = dept.getVersionEvidence().getEvidence(); - Iterator vIt = versionEv.iterator(); - while (vIt.hasNext()) { - Evidence e = vIt.next(); - LOGGER.info(" version: name={}, value={}, source={}, confidence={}", e.getName(), e.getValue(), e.getSource(), e.getConfidence()); - } - - Set vendorEv = dept.getVendorEvidence().getEvidence(); - Iterator vendorIt = vendorEv.iterator(); - while (vendorIt.hasNext()) { - Evidence e = vendorIt.next(); - LOGGER.info(" vendor: name={}, value={}, source={}, confidence={}", e.getName(), e.getValue(), e.getSource(), e.getConfidence()); - } - } + //TODO before re-enablign the following add actual assertions. +// Iterator dIterator = dependencies.iterator(); +// while (dIterator.hasNext()) { +// Dependency dept = dIterator.next(); +// LOGGER.info("dept path: {}", dept.getActualFilePath()); +// +// Set identifiers = dept.getIdentifiers(); +// Iterator idIterator = identifiers.iterator(); +// while (idIterator.hasNext()) { +// Identifier id = idIterator.next(); +// LOGGER.info(" Identifier: {}, type={}, url={}, conf={}", id.getValue(), id.getType(), id.getUrl(), id.getConfidence()); +// } +// +// Set prodEv = dept.getProductEvidence().getEvidence(); +// Iterator it = prodEv.iterator(); +// while (it.hasNext()) { +// Evidence e = it.next(); +// LOGGER.info(" prod: name={}, value={}, source={}, confidence={}", e.getName(), e.getValue(), e.getSource(), e.getConfidence()); +// } +// Set versionEv = dept.getVersionEvidence().getEvidence(); +// Iterator vIt = versionEv.iterator(); +// while (vIt.hasNext()) { +// Evidence e = vIt.next(); +// LOGGER.info(" version: name={}, value={}, source={}, confidence={}", e.getName(), e.getValue(), e.getSource(), e.getConfidence()); +// } +// +// Set vendorEv = dept.getVendorEvidence().getEvidence(); +// Iterator vendorIt = vendorEv.iterator(); +// while (vendorIt.hasNext()) { +// Evidence e = vendorIt.next(); +// LOGGER.info(" vendor: name={}, value={}, source={}, confidence={}", e.getName(), e.getValue(), e.getSource(), e.getConfidence()); +// } +// } } } diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/hints/HintParserTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/hints/HintParserTest.java index 7c6432cc4..f993ac7b6 100644 --- a/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/hints/HintParserTest.java +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/xml/hints/HintParserTest.java @@ -36,27 +36,29 @@ public class HintParserTest extends BaseTest { public void testParseHints_File() throws Exception { File file = BaseTest.getResourceAsFile(this, "hints.xml"); HintParser instance = new HintParser(); - Hints results = instance.parseHints(file); - assertEquals("Two duplicating hints should have been read", 2, results.getVendorDuplicatingHintRules().size()); - assertEquals("Two hint rules should have been read", 2, results.getHintRules().size()); + instance.parseHints(file); + HintRule[] hintRules = instance.getHintRules(); + VendorDuplicatingHintRule[] vendorRules = instance.getVendorDuplicatingHintRules(); + assertEquals("Two duplicating hints should have been read", 2, vendorRules.length); + assertEquals("Two hint rules should have been read", 2, hintRules.length); - assertEquals("One add product should have been read", 1, results.getHintRules().get(0).getAddProduct().size()); - assertEquals("One add vendor should have been read", 1, results.getHintRules().get(0).getAddVendor().size()); - assertEquals("Two file name should have been read", 2, results.getHintRules().get(1).getFilenames().size()); + assertEquals("One add product should have been read", 1, hintRules[0].getAddProduct().size()); + assertEquals("One add vendor should have been read", 1, hintRules[0].getAddVendor().size()); + assertEquals("Two file name should have been read", 2, hintRules[1].getFilenames().size()); - assertEquals("add product name not found", "add product name", results.getHintRules().get(0).getAddProduct().get(0).getName()); - assertEquals("add vendor name not found", "add vendor name", results.getHintRules().get(0).getAddVendor().get(0).getName()); - assertEquals("given product name not found", "given product name", results.getHintRules().get(0).getGivenProduct().get(0).getName()); - assertEquals("given vendor name not found", "given vendor name", results.getHintRules().get(0).getGivenVendor().get(0).getName()); + assertEquals("add product name not found", "add product name", hintRules[0].getAddProduct().get(0).getName()); + assertEquals("add vendor name not found", "add vendor name", hintRules[0].getAddVendor().get(0).getName()); + assertEquals("given product name not found", "given product name", hintRules[0].getGivenProduct().get(0).getName()); + assertEquals("given vendor name not found", "given vendor name", hintRules[0].getGivenVendor().get(0).getName()); - assertEquals("spring file name not found", "spring", results.getHintRules().get(1).getFilenames().get(0).getValue()); - assertEquals("file name 1 should not be case sensitive", false, results.getHintRules().get(1).getFilenames().get(0).isCaseSensitive()); - assertEquals("file name 1 should not be a regex", false, results.getHintRules().get(1).getFilenames().get(0).isRegex()); - assertEquals("file name 2 should be case sensitive", true, results.getHintRules().get(1).getFilenames().get(1).isCaseSensitive()); - assertEquals("file name 2 should be a regex", true, results.getHintRules().get(1).getFilenames().get(1).isRegex()); + assertEquals("spring file name not found", "spring", hintRules[1].getFilenames().get(0).getValue()); + assertEquals("file name 1 should not be case sensitive", false, hintRules[1].getFilenames().get(0).isCaseSensitive()); + assertEquals("file name 1 should not be a regex", false, hintRules[1].getFilenames().get(0).isRegex()); + assertEquals("file name 2 should be case sensitive", true, hintRules[1].getFilenames().get(1).isCaseSensitive()); + assertEquals("file name 2 should be a regex", true, hintRules[1].getFilenames().get(1).isRegex()); - assertEquals("sun duplicating vendor", "sun", results.getVendorDuplicatingHintRules().get(0).getValue()); - assertEquals("sun duplicates vendor oracle", "oracle", results.getVendorDuplicatingHintRules().get(0).getDuplicate()); + assertEquals("sun duplicating vendor", "sun", vendorRules[0].getValue()); + assertEquals("sun duplicates vendor oracle", "oracle", vendorRules[0].getDuplicate()); } /** @@ -66,45 +68,47 @@ public class HintParserTest extends BaseTest { public void testParseHints_InputStream() throws Exception { InputStream ins = BaseTest.getResourceAsStream(this, "hints_12.xml"); HintParser instance = new HintParser(); - Hints results = instance.parseHints(ins); - assertEquals("Zero duplicating hints should have been read", 0, results.getVendorDuplicatingHintRules().size()); - assertEquals("Two hint rules should have been read", 2, results.getHintRules().size()); + instance.parseHints(ins); + HintRule[] hintRules = instance.getHintRules(); + VendorDuplicatingHintRule[] vendorRules = instance.getVendorDuplicatingHintRules(); + assertEquals("Zero duplicating hints should have been read", 0, vendorRules.length); + assertEquals("Two hint rules should have been read", 2, hintRules.length); - assertEquals("One given product should have been read in hint 0", 1, results.getHintRules().get(0).getGivenProduct().size()); - assertEquals("One given vendor should have been read in hint 0", 1, results.getHintRules().get(0).getGivenVendor().size()); - assertEquals("One given version should have been read in hint 0", 1, results.getHintRules().get(0).getGivenVersion().size()); + assertEquals("One given product should have been read in hint 0", 1, hintRules[0].getGivenProduct().size()); + assertEquals("One given vendor should have been read in hint 0", 1, hintRules[0].getGivenVendor().size()); + assertEquals("One given version should have been read in hint 0", 1, hintRules[0].getGivenVersion().size()); - assertEquals("One add product should have been read in hint 0", 1, results.getHintRules().get(0).getAddProduct().size()); - assertEquals("One add vendor should have been read in hint 0", 1, results.getHintRules().get(0).getAddVendor().size()); - assertEquals("One add version should have been read in hint 0", 1, results.getHintRules().get(0).getAddVersion().size()); - assertEquals("Zero remove product should have been read in hint 0", 0, results.getHintRules().get(0).getRemoveProduct().size()); - assertEquals("Zero remove vendor should have been read in hint 0", 0, results.getHintRules().get(0).getRemoveVendor().size()); - assertEquals("Zero remove version should have been read in hint 0", 0, results.getHintRules().get(0).getRemoveVersion().size()); + assertEquals("One add product should have been read in hint 0", 1, hintRules[0].getAddProduct().size()); + assertEquals("One add vendor should have been read in hint 0", 1, hintRules[0].getAddVendor().size()); + assertEquals("One add version should have been read in hint 0", 1, hintRules[0].getAddVersion().size()); + assertEquals("Zero remove product should have been read in hint 0", 0, hintRules[0].getRemoveProduct().size()); + assertEquals("Zero remove vendor should have been read in hint 0", 0, hintRules[0].getRemoveVendor().size()); + assertEquals("Zero remove version should have been read in hint 0", 0, hintRules[0].getRemoveVersion().size()); - assertEquals("Zero given product should have been read in hint 1", 0, results.getHintRules().get(1).getGivenProduct().size()); - assertEquals("Zero given vendor should have been read in hint 1", 0, results.getHintRules().get(1).getGivenVendor().size()); - assertEquals("One given version should have been read in hint 1", 1, results.getHintRules().get(1).getGivenVersion().size()); + assertEquals("Zero given product should have been read in hint 1", 0, hintRules[1].getGivenProduct().size()); + assertEquals("Zero given vendor should have been read in hint 1", 0, hintRules[1].getGivenVendor().size()); + assertEquals("One given version should have been read in hint 1", 1, hintRules[1].getGivenVersion().size()); - assertEquals("One remove product should have been read in hint 1", 1, results.getHintRules().get(1).getRemoveProduct().size()); - assertEquals("One remove vendor should have been read in hint 1", 1, results.getHintRules().get(1).getRemoveVendor().size()); - assertEquals("One remove version should have been read in hint 1", 1, results.getHintRules().get(1).getRemoveVersion().size()); - assertEquals("Zero add product should have been read in hint 1", 0, results.getHintRules().get(1).getAddProduct().size()); - assertEquals("Zero add vendor should have been read in hint 1", 0, results.getHintRules().get(1).getAddVendor().size()); - assertEquals("Zero add version should have been read in hint 1", 0, results.getHintRules().get(1).getAddVersion().size()); + assertEquals("One remove product should have been read in hint 1", 1, hintRules[1].getRemoveProduct().size()); + assertEquals("One remove vendor should have been read in hint 1", 1, hintRules[1].getRemoveVendor().size()); + assertEquals("One remove version should have been read in hint 1", 1, hintRules[1].getRemoveVersion().size()); + assertEquals("Zero add product should have been read in hint 1", 0, hintRules[1].getAddProduct().size()); + assertEquals("Zero add vendor should have been read in hint 1", 0, hintRules[1].getAddVendor().size()); + assertEquals("Zero add version should have been read in hint 1", 0, hintRules[1].getAddVersion().size()); - assertEquals("add product name not found in hint 0", "add product name", results.getHintRules().get(0).getAddProduct().get(0).getName()); - assertEquals("add vendor name not found in hint 0", "add vendor name", results.getHintRules().get(0).getAddVendor().get(0).getName()); - assertEquals("add version name not found in hint 0", "add version name", results.getHintRules().get(0).getAddVersion().get(0).getName()); + assertEquals("add product name not found in hint 0", "add product name", hintRules[0].getAddProduct().get(0).getName()); + assertEquals("add vendor name not found in hint 0", "add vendor name", hintRules[0].getAddVendor().get(0).getName()); + assertEquals("add version name not found in hint 0", "add version name", hintRules[0].getAddVersion().get(0).getName()); - assertEquals("given product name not found in hint 0", "given product name", results.getHintRules().get(0).getGivenProduct().get(0).getName()); - assertEquals("given vendor name not found in hint 0", "given vendor name", results.getHintRules().get(0).getGivenVendor().get(0).getName()); - assertEquals("given version name not found in hint 0", "given version name", results.getHintRules().get(0).getGivenVersion().get(0).getName()); + assertEquals("given product name not found in hint 0", "given product name", hintRules[0].getGivenProduct().get(0).getName()); + assertEquals("given vendor name not found in hint 0", "given vendor name", hintRules[0].getGivenVendor().get(0).getName()); + assertEquals("given version name not found in hint 0", "given version name", hintRules[0].getGivenVersion().get(0).getName()); - assertEquals("given version name not found in hint 1", "given version name", results.getHintRules().get(1).getGivenVersion().get(0).getName()); + assertEquals("given version name not found in hint 1", "given version name", hintRules[1].getGivenVersion().get(0).getName()); - assertEquals("add product name not found in hint 1", "remove product name", results.getHintRules().get(1).getRemoveProduct().get(0).getName()); - assertEquals("add vendor name not found in hint 1", "remove vendor name", results.getHintRules().get(1).getRemoveVendor().get(0).getName()); - assertEquals("add version name not found in hint 1", "remove version name", results.getHintRules().get(1).getRemoveVersion().get(0).getName()); + assertEquals("add product name not found in hint 1", "remove product name", hintRules[1].getRemoveProduct().get(0).getName()); + assertEquals("add vendor name not found in hint 1", "remove vendor name", hintRules[1].getRemoveVendor().get(0).getName()); + assertEquals("add version name not found in hint 1", "remove version name", hintRules[1].getRemoveVersion().get(0).getName()); } } diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java index 55199165e..c4353dd84 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java @@ -93,22 +93,26 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Sets whether or not the external report format should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true) private String dataFileName; /** * Sets whether or not the external report format should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "failOnError", defaultValue = "true", required = true) private boolean failOnError; /** * The Maven Project Object. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "project", required = true, readonly = true) private MavenProject project; /** * List of Maven project of the current build */ + @SuppressWarnings("CanBeFinal") @Parameter(readonly = true, required = true, property = "reactorProjects") private List reactorProjects; /** @@ -116,18 +120,21 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * artifacts (handles both Maven 3.0 Sonatype and Maven 3.1+ eclipse Aether * implementations). */ + @SuppressWarnings("CanBeFinal") @Component private ArtifactResolver artifactResolver; /** * The Maven Session. */ + @SuppressWarnings("CanBeFinal") @Parameter(defaultValue = "${session}", readonly = true, required = true) private MavenSession session; /** * Remote repositories which will be searched for artifacts. */ + @SuppressWarnings("CanBeFinal") @Parameter(defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true) private List remoteRepositories; @@ -140,6 +147,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * The output directory. This generally maps to "target". */ + @SuppressWarnings("CanBeFinal") @Parameter(defaultValue = "${project.build.directory}", required = true) private File outputDirectory; /** @@ -166,11 +174,13 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not * recommended that this be turned to false. Default is true. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "autoUpdate") private Boolean autoUpdate; /** * Sets whether Experimental analyzers are enabled. Default is false. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "enableExperimental") private Boolean enableExperimental; /** @@ -192,33 +202,39 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * The Maven settings. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "mavenSettings", defaultValue = "${settings}", required = false) private org.apache.maven.settings.Settings mavenSettings; /** * The maven settings proxy id. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "mavenSettingsProxyId", required = false) private String mavenSettingsProxyId; /** * The Connection Timeout. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "connectionTimeout", defaultValue = "", required = false) private String connectionTimeout; /** * The paths to the suppression files. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "suppressionFiles", required = false) private String[] suppressionFiles; /** * The paths to the suppression file. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "suppressionFile", required = false) private String suppressionFile; /** * The path to the hints file. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "hintsFile", defaultValue = "", required = false) private String hintsFile; @@ -232,18 +248,21 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Whether or not the Jar Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "jarAnalyzerEnabled", required = false) private Boolean jarAnalyzerEnabled; /** * Whether or not the Archive Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "archiveAnalyzerEnabled", required = false) private Boolean archiveAnalyzerEnabled; /** * Sets whether the Python Distribution Analyzer will be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "pyDistributionAnalyzerEnabled", required = false) private Boolean pyDistributionAnalyzerEnabled; /** @@ -254,21 +273,25 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Sets whether the Ruby Gemspec Analyzer will be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "rubygemsAnalyzerEnabled", required = false) private Boolean rubygemsAnalyzerEnabled; /** * Sets whether or not the openssl Analyzer should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "opensslAnalyzerEnabled", required = false) private Boolean opensslAnalyzerEnabled; /** * Sets whether or not the CMake Analyzer should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cmakeAnalyzerEnabled", required = false) private Boolean cmakeAnalyzerEnabled; /** * Sets whether or not the autoconf Analyzer should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "autoconfAnalyzerEnabled", required = false) private Boolean autoconfAnalyzerEnabled; /** @@ -279,11 +302,13 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Sets whether or not the Node.js Analyzer should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "nodeAnalyzerEnabled", required = false) private Boolean nodeAnalyzerEnabled; /** * Sets whether or not the Node Security Project Analyzer should be used. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "nspAnalyzerEnabled", required = false) private Boolean nspAnalyzerEnabled; @@ -296,18 +321,21 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Whether or not the .NET Nuspec Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "nuspecAnalyzerEnabled", required = false) private Boolean nuspecAnalyzerEnabled; /** * Whether or not the Central Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "centralAnalyzerEnabled", required = false) private Boolean centralAnalyzerEnabled; /** * Whether or not the Nexus Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "nexusAnalyzerEnabled", required = false) private Boolean nexusAnalyzerEnabled; @@ -320,18 +348,21 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * Sets the path for the bundle-audit binary. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "bundleAuditPath", defaultValue = "", required = false) private String bundleAuditPath; /** * Whether or not the CocoaPods Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cocoapodsAnalyzerEnabled", required = false) private Boolean cocoapodsAnalyzerEnabled; /** * Whether or not the Swift package Analyzer is enabled. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "swiftPackageManagerAnalyzerEnabled", required = false) private Boolean swiftPackageManagerAnalyzerEnabled; @@ -339,38 +370,45 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * The URL of a Nexus server's REST API end point * (http://domain/nexus/service/local). */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "nexusUrl", required = false) private String nexusUrl; /** * Whether or not the configured proxy is used to connect to Nexus. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "nexusUsesProxy", required = false) private Boolean nexusUsesProxy; /** * The database connection string. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "connectionString", defaultValue = "", required = false) private String connectionString; /** * The database driver name. An example would be org.h2.Driver. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "databaseDriverName", defaultValue = "", required = false) private String databaseDriverName; /** * The path to the database driver if it is not on the class path. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "databaseDriverPath", defaultValue = "", required = false) private String databaseDriverPath; /** * The server id in the settings.xml; used to retrieve encrypted passwords * from the settings.xml. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "serverId", defaultValue = "", required = false) private String serverId; /** * A reference to the settings.xml settings. */ + @SuppressWarnings("CanBeFinal") @Parameter(defaultValue = "${settings}", readonly = true, required = true) private org.apache.maven.settings.Settings settingsXml; /** @@ -392,6 +430,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * A comma-separated list of file extensions to add to analysis next to jar, * zip, .... */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "zipExtensions", required = false) private String zipExtensions; /** @@ -437,38 +476,45 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma /** * The data directory, hold DC SQL DB. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "dataDirectory", defaultValue = "", required = false) private String dataDirectory; /** * Data Mirror URL for CVE 1.2. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cveUrl12Modified", defaultValue = "", required = false) private String cveUrl12Modified; /** * Data Mirror URL for CVE 2.0. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cveUrl20Modified", defaultValue = "", required = false) private String cveUrl20Modified; /** * Base Data Mirror URL for CVE 1.2. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cveUrl12Base", defaultValue = "", required = false) private String cveUrl12Base; /** * Data Mirror URL for CVE 2.0. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cveUrl20Base", defaultValue = "", required = false) private String cveUrl20Base; /** * Optionally skip excessive CVE update checks for a designated duration in * hours. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "cveValidForHours", defaultValue = "", required = false) private Integer cveValidForHours; /** * The path to mono for .NET Assembly analysis on non-windows systems. */ + @SuppressWarnings("CanBeFinal") @Parameter(property = "pathToMono", defaultValue = "", required = false) private String pathToMono; @@ -1183,7 +1229,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * @throws MojoFailureException thrown if a CVSS score is found that is * higher then the threshold set */ - protected void checkForFailure(List dependencies) throws MojoFailureException { + protected void checkForFailure(Dependency[] dependencies) throws MojoFailureException { final StringBuilder ids = new StringBuilder(); for (Dependency d : dependencies) { boolean addName = true; @@ -1220,7 +1266,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma * @param mp the Maven project for which the summary is shown * @param dependencies a list of dependency objects */ - protected void showSummary(MavenProject mp, List dependencies) { + protected void showSummary(MavenProject mp, Dependency[] dependencies) { if (showSummary) { final StringBuilder summary = new StringBuilder(); for (Dependency d : dependencies) { diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java index 02cc39947..e409aa8a1 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/CheckMojo.java @@ -99,7 +99,7 @@ public class CheckMojo extends BaseDependencyCheckMojo { } if (engine != null) { ExceptionCollection exCol = scanArtifacts(getProject(), engine); - if (engine.getDependencies().isEmpty()) { + if (engine.getDependencies().length == 0) { getLog().info("No dependencies were identified that could be analyzed by dependency-check"); } try { diff --git a/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java b/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java index da3b0015a..01a2f0233 100644 --- a/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java +++ b/dependency-check-maven/src/test/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojoTest.java @@ -95,14 +95,14 @@ public class BaseDependencyCheckMojoTest extends BaseTest { Engine engine = new Engine(getSettings()); getSettings().setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate); - assertTrue(engine.getDependencies().isEmpty()); + assertTrue(engine.getDependencies().length == 0); BaseDependencyCheckMojoImpl instance = new BaseDependencyCheckMojoImpl(); try { //the mock above fails under some JDKs instance.scanArtifacts(project, engine); } catch (NullPointerException ex) { Assume.assumeNoException(ex); } - assertFalse(engine.getDependencies().isEmpty()); + assertFalse(engine.getDependencies().length == 0); engine.cleanup(); } } diff --git a/dependency-check-utils/pom.xml b/dependency-check-utils/pom.xml index 68a8d46a1..846049af4 100644 --- a/dependency-check-utils/pom.xml +++ b/dependency-check-utils/pom.xml @@ -94,10 +94,5 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved. logback-classic test - - com.google.code.findbugs - annotations - provided - diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStream.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStream.java index abd10d4e6..8840b7c8e 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStream.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStream.java @@ -25,12 +25,14 @@ import java.io.ObjectStreamClass; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import javax.annotation.concurrent.NotThreadSafe; /** * An ObjectInputStream that will only deserialize expected classes. * * @author Jeremy Long */ +@NotThreadSafe public class ExpectedObjectInputStream extends ObjectInputStream { /** diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java index 91148f23c..a009dd1af 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java @@ -445,12 +445,15 @@ public final class Settings { } // + /** + * Initialize the settings object. + */ public Settings() { initialize(PROPERTIES_FILE); } /** - * This class loads the settings from the given properties file. + * Initialize the settings object using the given properties file. * * @param propertiesFilePath the path to the base properties file to load */ @@ -463,7 +466,7 @@ public final class Settings { * * @param propertiesFilePath the path to the settings property file */ - private final void initialize(String propertiesFilePath) { + private void initialize(String propertiesFilePath) { props = new Properties(); try (InputStream in = FileUtils.getResourceAsStream(propertiesFilePath)) { props.load(in); @@ -970,8 +973,7 @@ public final class Settings { throw new IOException(String.format("Unable to create the data directory '%s'", (path == null) ? "unknown" : path.getAbsolutePath())); } - - + /** * Generates a new temporary file name that is guaranteed to be unique. * diff --git a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStreamTest.java b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStreamTest.java index 0907da9bb..b7e0cc8bf 100644 --- a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStreamTest.java +++ b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/ExpectedObjectInputStreamTest.java @@ -46,7 +46,6 @@ public class ExpectedObjectInputStreamTest { out.writeObject(data); out.flush(); byte[] buf = mem.toByteArray(); - out.close(); ByteArrayInputStream in = new ByteArrayInputStream(buf); ExpectedObjectInputStream instance = new ExpectedObjectInputStream(in, "java.util.ArrayList", "org.owasp.dependencycheck.utils.SimplePojo", "java.lang.Integer", "java.lang.Number"); instance.readObject(); diff --git a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SimplePojo.java b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SimplePojo.java index b3b5e2504..9926322f6 100644 --- a/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SimplePojo.java +++ b/dependency-check-utils/src/test/java/org/owasp/dependencycheck/utils/SimplePojo.java @@ -23,6 +23,10 @@ import java.io.Serializable; * @author jeremy */ public class SimplePojo implements Serializable { + /** + * The serial version UID for serialization. + */ + private static final long serialVersionUID = 1L; public String s = "3"; public Integer i = 3;