View Javadoc
1   /*
2    * This file is part of dependency-check-maven.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Copyright (c) 2014 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.maven;
19  
20  import com.github.packageurl.MalformedPackageURLException;
21  import com.github.packageurl.PackageURL;
22  import com.github.packageurl.PackageURL.StandardTypes;
23  import org.apache.commons.lang3.StringUtils;
24  import org.apache.maven.artifact.Artifact;
25  import org.apache.maven.artifact.DefaultArtifact;
26  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
27  import org.apache.maven.artifact.repository.ArtifactRepository;
28  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
29  import org.apache.maven.artifact.versioning.ArtifactVersion;
30  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
31  import org.apache.maven.artifact.versioning.Restriction;
32  import org.apache.maven.artifact.versioning.VersionRange;
33  import org.apache.maven.doxia.sink.Sink;
34  import org.apache.maven.execution.MavenSession;
35  import org.apache.maven.model.License;
36  import org.apache.maven.plugin.AbstractMojo;
37  import org.apache.maven.plugin.MojoExecution;
38  import org.apache.maven.plugin.MojoExecutionException;
39  import org.apache.maven.plugin.MojoFailureException;
40  import org.apache.maven.plugins.annotations.Component;
41  import org.apache.maven.plugins.annotations.Parameter;
42  import org.apache.maven.project.DefaultProjectBuildingRequest;
43  import org.apache.maven.project.MavenProject;
44  import org.apache.maven.project.ProjectBuildingRequest;
45  import org.apache.maven.reporting.MavenReport;
46  import org.apache.maven.reporting.MavenReportException;
47  import org.apache.maven.settings.Proxy;
48  import org.apache.maven.settings.Server;
49  import org.apache.maven.settings.building.SettingsProblem;
50  import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
51  import org.apache.maven.settings.crypto.SettingsDecrypter;
52  import org.apache.maven.settings.crypto.SettingsDecryptionResult;
53  import org.apache.maven.shared.artifact.filter.PatternExcludesArtifactFilter;
54  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
55  import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
56  import org.apache.maven.shared.dependency.graph.DependencyNode;
57  import org.apache.maven.shared.dependency.graph.filter.ArtifactDependencyNodeFilter;
58  import org.apache.maven.shared.dependency.graph.internal.DefaultDependencyNode;
59  import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor;
60  import org.apache.maven.shared.dependency.graph.traversal.FilteringDependencyNodeVisitor;
61  import org.apache.maven.shared.model.fileset.FileSet;
62  import org.apache.maven.shared.model.fileset.util.FileSetManager;
63  import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
64  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
65  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
66  import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
67  import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
68  import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
69  import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
70  import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
71  import org.eclipse.aether.artifact.ArtifactType;
72  import org.owasp.dependencycheck.Engine;
73  import org.owasp.dependencycheck.agent.DependencyCheckScanAgent;
74  import org.owasp.dependencycheck.analyzer.JarAnalyzer;
75  import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
76  import org.owasp.dependencycheck.data.nexus.MavenArtifact;
77  import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
78  import org.owasp.dependencycheck.dependency.Confidence;
79  import org.owasp.dependencycheck.dependency.Dependency;
80  import org.owasp.dependencycheck.dependency.EvidenceType;
81  import org.owasp.dependencycheck.dependency.Vulnerability;
82  import org.owasp.dependencycheck.dependency.naming.GenericIdentifier;
83  import org.owasp.dependencycheck.dependency.naming.Identifier;
84  import org.owasp.dependencycheck.dependency.naming.PurlIdentifier;
85  import org.owasp.dependencycheck.exception.DependencyNotFoundException;
86  import org.owasp.dependencycheck.exception.ExceptionCollection;
87  import org.owasp.dependencycheck.exception.InitializationException;
88  import org.owasp.dependencycheck.exception.ReportException;
89  import org.owasp.dependencycheck.reporting.ReportGenerator;
90  import org.owasp.dependencycheck.utils.Checksum;
91  import org.owasp.dependencycheck.utils.Downloader;
92  import org.owasp.dependencycheck.utils.Filter;
93  import org.owasp.dependencycheck.utils.InvalidSettingException;
94  import org.owasp.dependencycheck.utils.Settings;
95  import org.owasp.dependencycheck.utils.SeverityUtil;
96  import org.owasp.dependencycheck.xml.pom.Model;
97  import org.owasp.dependencycheck.xml.pom.PomUtils;
98  
99  import java.io.File;
100 import java.io.IOException;
101 import java.io.InputStream;
102 import java.util.ArrayList;
103 import java.util.Arrays;
104 import java.util.Collections;
105 import java.util.HashSet;
106 import java.util.List;
107 import java.util.Locale;
108 import java.util.Map;
109 import java.util.Objects;
110 import java.util.Optional;
111 import java.util.Set;
112 import java.util.stream.Collectors;
113 import java.util.stream.Stream;
114 
115 //CSOFF: FileLength
116 
117 /**
118  * @author Jeremy Long
119  */
120 public abstract class BaseDependencyCheckMojo extends AbstractMojo implements MavenReport {
121 
122     //<editor-fold defaultstate="collapsed" desc="Private fields">
123     /**
124      * The properties file location.
125      */
126     private static final String PROPERTIES_FILE = "mojo.properties";
127     /**
128      * System specific new line character.
129      */
130     private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
131     /**
132      * Pattern to include all files in a FileSet.
133      */
134     private static final String INCLUDE_ALL = "**/*";
135     /**
136      * Constant for the HTTPS protocol string.
137      */
138     public static final String PROTOCOL_HTTPS = "https";
139     /**
140      * Constant for the HTTP protocol string.
141      */
142     public static final String PROTOCOL_HTTP = "http";
143     /**
144      * A flag indicating whether or not the Maven site is being generated.
145      */
146     private boolean generatingSite = false;
147     /**
148      * The configured settings.
149      */
150     private Settings settings = null;
151     /**
152      * The list of files that have been scanned.
153      */
154     private final List<File> scannedFiles = new ArrayList<>();
155     //</editor-fold>
156     // <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
157     /**
158      * Sets whether or not the mojo should fail if an error occurs.
159      */
160     @SuppressWarnings("CanBeFinal")
161     @Parameter(property = "failOnError", defaultValue = "true", required = true)
162     private boolean failOnError;
163 
164     /**
165      * The Maven Project Object.
166      */
167     @SuppressWarnings("CanBeFinal")
168     @Parameter(property = "project", required = true, readonly = true)
169     private MavenProject project;
170     /**
171      * The Maven Mojo Execution Object.
172      */
173     @Parameter(defaultValue = "${mojoExecution}", readonly = true)
174     private MojoExecution mojoExecution;
175     /**
176      * List of Maven project of the current build
177      */
178     @SuppressWarnings("CanBeFinal")
179     @Parameter(readonly = true, required = true, property = "reactorProjects")
180     private List<MavenProject> reactorProjects;
181     /**
182      * The entry point towards a Maven version independent way of resolving
183      * artifacts (handles both Maven 3.0 Sonatype and Maven 3.1+ eclipse Aether
184      * implementations).
185      */
186     @SuppressWarnings("CanBeFinal")
187     @Component
188     private ArtifactResolver artifactResolver;
189     /**
190      * The entry point towards a Maven version independent way of resolving
191      * dependencies (handles both Maven 3.0 Sonatype and Maven 3.1+ eclipse
192      * Aether implementations). Contrary to the ArtifactResolver this resolver
193      * also takes into account the additional repositories defined in the
194      * dependency-path towards transitive dependencies.
195      */
196     @SuppressWarnings("CanBeFinal")
197     @Component
198     private DependencyResolver dependencyResolver;
199 
200     /**
201      * The Maven Session.
202      */
203     @SuppressWarnings("CanBeFinal")
204     @Parameter(defaultValue = "${session}", readonly = true, required = true)
205     private MavenSession session;
206 
207     /**
208      * Component within Maven to build the dependency graph.
209      */
210     @Component
211     private DependencyGraphBuilder dependencyGraphBuilder;
212 
213     /**
214      * The output directory. This generally maps to "target".
215      */
216     @SuppressWarnings("CanBeFinal")
217     @Parameter(defaultValue = "${project.build.directory}", required = true, property = "odc.outputDirectory")
218     private File outputDirectory;
219     /**
220      * This is a reference to the &gt;reporting&lt; sections
221      * <code>outputDirectory</code>. This cannot be configured in the
222      * dependency-check mojo directly. This generally maps to "target/site".
223      */
224     @Parameter(property = "project.reporting.outputDirectory", readonly = true)
225     private File reportOutputDirectory;
226     /**
227      * Specifies if the build should be failed if a CVSS score above a specified
228      * level is identified. The default is 11 which means since the CVSS scores
229      * are 0-10, by default the build will never fail.
230      */
231     @SuppressWarnings("CanBeFinal")
232     @Parameter(property = "failBuildOnCVSS", defaultValue = "11", required = true)
233     private float failBuildOnCVSS = 11f;
234     /**
235      * Specifies the CVSS score that is considered a "test" failure when
236      * generating a jUnit style report. The default value is 0 - all
237      * vulnerabilities are considered a failure.
238      */
239     @SuppressWarnings("CanBeFinal")
240     @Parameter(property = "junitFailOnCVSS", defaultValue = "0", required = true)
241     private float junitFailOnCVSS = 0;
242     /**
243      * Fail the build if any dependency has a vulnerability listed.
244      *
245      * @deprecated use {@link BaseDependencyCheckMojo#failBuildOnCVSS} with a
246      * value of 0 instead
247      */
248     @SuppressWarnings("CanBeFinal")
249     @Parameter(property = "failBuildOnAnyVulnerability", defaultValue = "false", required = true)
250     @Deprecated
251     private boolean failBuildOnAnyVulnerability = false;
252     /**
253      * Sets whether auto-updating of the NVD CVE data is enabled. It is not
254      * recommended that this be turned to false. Default is true.
255      */
256     @SuppressWarnings("CanBeFinal")
257     @Parameter(property = "autoUpdate")
258     private Boolean autoUpdate;
259     /**
260      * Sets whether Experimental analyzers are enabled. Default is false.
261      */
262     @SuppressWarnings("CanBeFinal")
263     @Parameter(property = "enableExperimental")
264     private Boolean enableExperimental;
265     /**
266      * Sets whether retired analyzers are enabled. Default is false.
267      */
268     @SuppressWarnings("CanBeFinal")
269     @Parameter(property = "enableRetired")
270     private Boolean enableRetired;
271     /**
272      * Sets whether the Golang Dependency analyzer is enabled. Default is true.
273      */
274     @SuppressWarnings("CanBeFinal")
275     @Parameter(property = "golangDepEnabled")
276     private Boolean golangDepEnabled;
277     /**
278      * Sets whether Golang Module Analyzer is enabled; this requires `go` to be
279      * installed. Default is true.
280      */
281     @SuppressWarnings("CanBeFinal")
282     @Parameter(property = "golangModEnabled")
283     private Boolean golangModEnabled;
284     /**
285      * Sets the path to `go`.
286      */
287     @SuppressWarnings("CanBeFinal")
288     @Parameter(property = "pathToGo")
289     private String pathToGo;
290 
291     /**
292      * Sets the path to `yarn`.
293      */
294     @SuppressWarnings("CanBeFinal")
295     @Parameter(property = "pathToYarn")
296     private String pathToYarn;
297     /**
298      * Sets the path to `pnpm`.
299      */
300     @SuppressWarnings("CanBeFinal")
301     @Parameter(property = "pathToPnpm")
302     private String pathToPnpm;
303     /**
304      * Use pom dependency information for snapshot dependencies that are part of
305      * the Maven reactor while aggregate scanning a multi-module project.
306      */
307     @Parameter(property = "dependency-check.virtualSnapshotsFromReactor", defaultValue = "true")
308     private Boolean virtualSnapshotsFromReactor;
309     /**
310      * The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF,
311      * JENKINS, GITLAB, ALL). Multiple formats can be selected using a comma
312      * delineated list.
313      */
314     @SuppressWarnings("CanBeFinal")
315     @Parameter(property = "format", defaultValue = "HTML", required = true)
316     private String format = "HTML";
317 
318     /**
319      * Whether or not the XML and JSON report formats should be pretty printed.
320      * The default is false.
321      */
322     @Parameter(property = "prettyPrint")
323     private Boolean prettyPrint;
324     /**
325      * The report format to be generated (HTML, XML, CSV, JSON, JUNIT, SARIF,
326      * JENKINS, GITLAB, ALL). Multiple formats can be selected using a comma
327      * delineated list.
328      */
329     @Parameter(property = "formats", required = true)
330     private String[] formats;
331     /**
332      * The Maven settings.
333      */
334     @SuppressWarnings("CanBeFinal")
335     @Parameter(property = "mavenSettings", defaultValue = "${settings}")
336     private org.apache.maven.settings.Settings mavenSettings;
337 
338     /**
339      * The maven settings proxy id.
340      */
341     @SuppressWarnings("CanBeFinal")
342     @Parameter(property = "mavenSettingsProxyId")
343     private String mavenSettingsProxyId;
344 
345     /**
346      * The Connection Timeout.
347      */
348     @SuppressWarnings("CanBeFinal")
349     @Parameter(property = "connectionTimeout")
350     private String connectionTimeout;
351     /**
352      * The Read Timeout.
353      */
354     @SuppressWarnings("CanBeFinal")
355     @Parameter(property = "readTimeout")
356     private String readTimeout;
357     /**
358      * Sets whether dependency-check should check if there is a new version
359      * available.
360      */
361     @SuppressWarnings("CanBeFinal")
362     @Parameter(property = "versionCheckEnabled", defaultValue = "true")
363     private boolean versionCheckEnabled;
364     /**
365      * The paths to the suppression files. The parameter value can be a local
366      * file path, a URL to a suppression file, or even a reference to a file on
367      * the class path (see
368      * https://github.com/dependency-check/DependencyCheck/issues/1878#issuecomment-487533799)
369      */
370     @SuppressWarnings("CanBeFinal")
371     @Parameter(property = "suppressionFiles")
372     private String[] suppressionFiles;
373     /**
374      * The paths to the suppression file. The parameter value can be a local
375      * file path, a URL to a suppression file, or even a reference to a file on
376      * the class path (see
377      * https://github.com/dependency-check/DependencyCheck/issues/1878#issuecomment-487533799)
378      */
379     @SuppressWarnings("CanBeFinal")
380     @Parameter(property = "suppressionFile")
381     private String suppressionFile;
382     /**
383      * The username used when connecting to the suppressionFiles.
384      */
385     @Parameter(property = "suppressionFileUser")
386     private String suppressionFileUser;
387     /**
388      * The password used for Basic auth to the suppressionFiles. The `suppressionFileServerId` with user/password should
389      * be used instead otherwise maven debug logging could expose the password.
390      */
391     @Parameter(property = "suppressionFilePassword")
392     private String suppressionFilePassword;
393     /**
394      * The token used for Bearer auth to the suppressionFiles. The `suppressionFileServerId` with only password should
395      * be used instead otherwise maven debug logging could expose the token.
396      */
397     @Parameter(property = "suppressionFileBearerToken")
398     private String suppressionFileBearerToken;
399     /**
400      * The server id in the settings.xml; used to retrieve encrypted passwords
401      * from the settings.xml for suppressionFile(s).
402      */
403     @SuppressWarnings("CanBeFinal")
404     @Parameter(property = "suppressionFileServerId")
405     private String suppressionFileServerId;
406     /**
407      * The path to the hints file.
408      */
409     @SuppressWarnings("CanBeFinal")
410     @Parameter(property = "hintsFile")
411     private String hintsFile;
412 
413     /**
414      * Flag indicating whether or not to show a summary in the output.
415      */
416     @SuppressWarnings("CanBeFinal")
417     @Parameter(property = "showSummary", defaultValue = "true")
418     private boolean showSummary = true;
419 
420     /**
421      * Whether or not the Jar Analyzer is enabled.
422      */
423     @SuppressWarnings("CanBeFinal")
424     @Parameter(property = "jarAnalyzerEnabled")
425     private Boolean jarAnalyzerEnabled;
426 
427     /**
428      * Sets whether the Dart analyzer is enabled. Default is true.
429      */
430     @SuppressWarnings("CanBeFinal")
431     @Parameter(property = "dartAnalyzerEnabled")
432     private Boolean dartAnalyzerEnabled;
433 
434     /**
435      * Whether or not the Archive Analyzer is enabled.
436      */
437     @SuppressWarnings("CanBeFinal")
438     @Parameter(property = "archiveAnalyzerEnabled")
439     private Boolean archiveAnalyzerEnabled;
440     /**
441      * Whether or not the Known Exploited Vulnerability Analyzer is enabled.
442      */
443     @SuppressWarnings("CanBeFinal")
444     @Parameter(property = "knownExploitedEnabled")
445     private Boolean knownExploitedEnabled;
446     /**
447      * The URL to the CISA Known Exploited Vulnerabilities JSON datafeed.
448      */
449     @SuppressWarnings("CanBeFinal")
450     @Parameter(property = "knownExploitedUrl")
451     private String knownExploitedUrl;
452     /**
453      * The server id in the settings.xml; used to retrieve encrypted passwords
454      * from the settings.xml for mirror of CISA Known Exploited Vulnerabilities JSON datafeed.
455      * Credentials with only a password will be used for Bearer auth, credentials with both user and password for Basic auth.
456      */
457     @SuppressWarnings("CanBeFinal")
458     @Parameter(property = "knownExploitedServerId")
459     private String knownExploitedServerId;
460     /**
461      * The username for basic auth mirror of CISA Known Exploited Vulnerabilities JSON datafeed. A `knownExploitedServerId`
462      * with user/password set should be used instead otherwise maven debug logging could expose the password.
463      */
464     @SuppressWarnings("CanBeFinal")
465     @Parameter(property = "knownExploitedUser")
466     private String knownExploitedUser;
467     /**
468      * The password for basic auth mirror of CISA Known Exploited Vulnerabilities JSON datafeed. A `knownExploitedServerId`
469      * with user/password set should be used instead otherwise maven debug logging could expose the password.
470      */
471     @SuppressWarnings("CanBeFinal")
472     @Parameter(property = "knownExploitedPassword")
473     private String knownExploitedPassword;
474     /**
475      * The token for bearer auth mirror of CISA Known Exploited Vulnerabilities JSON datafeed. A `knownExploitedServerId`
476      * with only password set should be used instead otherwise maven debug logging could expose the token.
477      */
478     @SuppressWarnings("CanBeFinal")
479     @Parameter(property = "knownExploitedBearerToken")
480     private String knownExploitedBearerToken;
481     /**
482      * Sets whether the Python Distribution Analyzer will be used.
483      */
484     @SuppressWarnings("CanBeFinal")
485     @Parameter(property = "pyDistributionAnalyzerEnabled")
486     private Boolean pyDistributionAnalyzerEnabled;
487     /**
488      * Sets whether the Python Package Analyzer will be used.
489      */
490     @Parameter(property = "pyPackageAnalyzerEnabled")
491     private Boolean pyPackageAnalyzerEnabled;
492     /**
493      * Sets whether the Ruby Gemspec Analyzer will be used.
494      */
495     @SuppressWarnings("CanBeFinal")
496     @Parameter(property = "rubygemsAnalyzerEnabled")
497     private Boolean rubygemsAnalyzerEnabled;
498     /**
499      * Sets whether or not the openssl Analyzer should be used.
500      */
501     @SuppressWarnings("CanBeFinal")
502     @Parameter(property = "opensslAnalyzerEnabled")
503     private Boolean opensslAnalyzerEnabled;
504     /**
505      * Sets whether or not the CMake Analyzer should be used.
506      */
507     @SuppressWarnings("CanBeFinal")
508     @Parameter(property = "cmakeAnalyzerEnabled")
509     private Boolean cmakeAnalyzerEnabled;
510     /**
511      * Sets whether or not the autoconf Analyzer should be used.
512      */
513     @SuppressWarnings("CanBeFinal")
514     @Parameter(property = "autoconfAnalyzerEnabled")
515     private Boolean autoconfAnalyzerEnabled;
516     /**
517      * Sets whether or not the Maven install Analyzer should be used.
518      */
519     @SuppressWarnings("CanBeFinal")
520     @Parameter(property = "mavenInstallAnalyzerEnabled")
521     private Boolean mavenInstallAnalyzerEnabled;
522     /**
523      * Sets whether or not the pip Analyzer should be used.
524      */
525     @SuppressWarnings("CanBeFinal")
526     @Parameter(property = "pipAnalyzerEnabled")
527     private Boolean pipAnalyzerEnabled;
528     /**
529      * Sets whether or not the pipfile Analyzer should be used.
530      */
531     @SuppressWarnings("CanBeFinal")
532     @Parameter(property = "pipfileAnalyzerEnabled")
533     private Boolean pipfileAnalyzerEnabled;
534     /**
535      * Sets whether or not the poetry Analyzer should be used.
536      */
537     @SuppressWarnings("CanBeFinal")
538     @Parameter(property = "poetryAnalyzerEnabled")
539     private Boolean poetryAnalyzerEnabled;
540     /**
541      * Sets whether or not the PHP Composer Lock File Analyzer should be used.
542      */
543     @Parameter(property = "composerAnalyzerEnabled")
544     private Boolean composerAnalyzerEnabled;
545     /**
546      * Sets whether or not the PHP Composer Lock File Analyzer will scan "packages-dev".
547      */
548     @Parameter(property = "composerAnalyzerSkipDev")
549     private boolean composerAnalyzerSkipDev;
550     /**
551      * Whether or not the Perl CPAN File Analyzer is enabled.
552      */
553     @Parameter(property = "cpanfileAnalyzerEnabled")
554     private Boolean cpanfileAnalyzerEnabled;
555     /**
556      * Sets whether or not the Node Package Analyzer should be used.
557      */
558     @SuppressWarnings("CanBeFinal")
559     @Parameter(property = "nodeAnalyzerEnabled")
560     private Boolean nodeAnalyzerEnabled;
561     /**
562      * Sets whether or not the Node Audit Analyzer should be used.
563      */
564     @SuppressWarnings("CanBeFinal")
565     @Parameter(property = "nodeAuditAnalyzerEnabled")
566     private Boolean nodeAuditAnalyzerEnabled;
567 
568     /**
569      * The Node Audit API URL for the Node Audit Analyzer.
570      */
571     @SuppressWarnings("CanBeFinal")
572     @Parameter(property = "nodeAuditAnalyzerUrl")
573     private String nodeAuditAnalyzerUrl;
574 
575     /**
576      * Sets whether or not the Yarn Audit Analyzer should be used.
577      */
578     @SuppressWarnings("CanBeFinal")
579     @Parameter(property = "yarnAuditAnalyzerEnabled")
580     private Boolean yarnAuditAnalyzerEnabled;
581 
582     /**
583      * Sets whether or not the Pnpm Audit Analyzer should be used.
584      */
585     @SuppressWarnings("CanBeFinal")
586     @Parameter(property = "pnpmAuditAnalyzerEnabled")
587     private Boolean pnpmAuditAnalyzerEnabled;
588 
589     /**
590      * Sets whether or not the Node Audit Analyzer should use a local cache.
591      */
592     @SuppressWarnings("CanBeFinal")
593     @Parameter(property = "nodeAuditAnalyzerUseCache")
594     private Boolean nodeAuditAnalyzerUseCache;
595     /**
596      * Sets whether or not the Node Audit Analyzer should skip devDependencies.
597      */
598     @SuppressWarnings("CanBeFinal")
599     @Parameter(property = "nodeAuditSkipDevDependencies")
600     private Boolean nodeAuditSkipDevDependencies;
601     /**
602      * Sets whether or not the Node Package Analyzer should skip devDependencies.
603      */
604     @SuppressWarnings("CanBeFinal")
605     @Parameter(property = "nodePackageSkipDevDependencies")
606     private Boolean nodePackageSkipDevDependencies;
607     /**
608      * Sets whether or not the Retirejs Analyzer should be used.
609      */
610     @SuppressWarnings("CanBeFinal")
611     @Parameter(property = "retireJsAnalyzerEnabled")
612     private Boolean retireJsAnalyzerEnabled;
613     /**
614      * The Retire JS repository URL.
615      */
616     @SuppressWarnings("CanBeFinal")
617     @Parameter(property = "retireJsUrl")
618     private String retireJsUrl;
619     /**
620      * The username for Basic auth to the retireJsUrl.
621      */
622     @Parameter(property = "retireJsUser")
623     private String retireJsUser;
624     /**
625      * The password for Basic auth to the retireJsUrl. The `retireJsUrlServerId` with user/password set should be used instead otherwise maven debug logging could expose the password.
626      */
627     @Parameter(property = "retireJsPassword")
628     private String retireJsPassword;
629     /**
630      * The token for Bearer auth to the retireJsUrl. The `retireJsUrlServerId` with only password set should be used instead
631      * otherwise maven debug logging could expose the token.
632      */
633     @Parameter(property = "retireJsBearerToken")
634     private String retireJsBearerToken;
635     /**
636      * The server id in the settings.xml; used to retrieve encrypted passwords
637      * from the settings.xml for retireJsUrl.
638      */
639     @SuppressWarnings("CanBeFinal")
640     @Parameter(property = "retireJsUrlServerId")
641     private String retireJsUrlServerId;
642     /**
643      * Whether the Retire JS repository will be updated regardless of the
644      * `autoupdate` settings.
645      */
646     @SuppressWarnings("CanBeFinal")
647     @Parameter(property = "retireJsForceUpdate")
648     private Boolean retireJsForceUpdate;
649     /**
650      * Whether or not the .NET Assembly Analyzer is enabled.
651      */
652     @Parameter(property = "assemblyAnalyzerEnabled")
653     private Boolean assemblyAnalyzerEnabled;
654     /**
655      * Whether or not the MS Build Analyzer is enabled.
656      */
657     @Parameter(property = "msbuildAnalyzerEnabled")
658     private Boolean msbuildAnalyzerEnabled;
659     /**
660      * Whether or not the .NET Nuspec Analyzer is enabled.
661      */
662     @SuppressWarnings("CanBeFinal")
663     @Parameter(property = "nuspecAnalyzerEnabled")
664     private Boolean nuspecAnalyzerEnabled;
665 
666     /**
667      * Whether or not the .NET packages.config Analyzer is enabled.
668      */
669     @SuppressWarnings("CanBeFinal")
670     @Parameter(property = "nugetconfAnalyzerEnabled")
671     private Boolean nugetconfAnalyzerEnabled;
672 
673     /**
674      * Whether or not the Libman Analyzer is enabled.
675      */
676     @SuppressWarnings("CanBeFinal")
677     @Parameter(property = "libmanAnalyzerEnabled")
678     private Boolean libmanAnalyzerEnabled;
679 
680     /**
681      * Whether or not the Central Analyzer is enabled.
682      */
683     @SuppressWarnings("CanBeFinal")
684     @Parameter(property = "centralAnalyzerEnabled")
685     private Boolean centralAnalyzerEnabled;
686 
687     /**
688      * Whether or not the Central Analyzer should use a local cache.
689      */
690     @SuppressWarnings("CanBeFinal")
691     @Parameter(property = "centralAnalyzerUseCache")
692     private Boolean centralAnalyzerUseCache;
693 
694     /**
695      * Whether or not the Artifactory Analyzer is enabled.
696      */
697     @SuppressWarnings("CanBeFinal")
698     @Parameter(property = "artifactoryAnalyzerEnabled")
699     private Boolean artifactoryAnalyzerEnabled;
700     /**
701      * The serverId inside the settings.xml containing the username and token to
702      * access artifactory
703      */
704     @SuppressWarnings("CanBeFinal")
705     @Parameter(property = "artifactoryAnalyzerServerId")
706     private String artifactoryAnalyzerServerId;
707     /**
708      * The username (only used with API token) to connect to Artifactory
709      * instance
710      */
711     @SuppressWarnings("CanBeFinal")
712     @Parameter(property = "artifactoryAnalyzerUsername")
713     private String artifactoryAnalyzerUsername;
714     /**
715      * The API token to connect to Artifactory instance
716      */
717     @SuppressWarnings("CanBeFinal")
718     @Parameter(property = "artifactoryAnalyzerApiToken")
719     private String artifactoryAnalyzerApiToken;
720     /**
721      * The bearer token to connect to Artifactory instance
722      */
723     @SuppressWarnings("CanBeFinal")
724     @Parameter(property = "artifactoryAnalyzerBearerToken")
725     private String artifactoryAnalyzerBearerToken;
726     /**
727      * The Artifactory URL for the Artifactory analyzer.
728      */
729     @SuppressWarnings("CanBeFinal")
730     @Parameter(property = "artifactoryAnalyzerUrl")
731     private String artifactoryAnalyzerUrl;
732     /**
733      * Whether Artifactory should be accessed through a proxy or not
734      */
735     @SuppressWarnings("CanBeFinal")
736     @Parameter(property = "artifactoryAnalyzerUseProxy")
737     private Boolean artifactoryAnalyzerUseProxy;
738     /**
739      * Whether the Artifactory analyzer should be run in parallel or not.
740      */
741     @SuppressWarnings("CanBeFinal")
742     @Parameter(property = "artifactoryAnalyzerParallelAnalysis", defaultValue = "true")
743     private Boolean artifactoryAnalyzerParallelAnalysis;
744     /**
745      * Whether the Unused Suppression Rule analyzer should fail if there are unused rules.
746      */
747     @SuppressWarnings("CanBeFinal")
748     @Parameter(property = "failBuildOnUnusedSuppressionRule", defaultValue = "false")
749     private Boolean failBuildOnUnusedSuppressionRule;
750     /**
751      * Whether or not the Nexus Analyzer is enabled.
752      */
753     @SuppressWarnings("CanBeFinal")
754     @Parameter(property = "nexusAnalyzerEnabled")
755     private Boolean nexusAnalyzerEnabled;
756 
757     /**
758      * Whether or not the Sonatype OSS Index analyzer is enabled.
759      */
760     @SuppressWarnings("CanBeFinal")
761     @Parameter(property = "ossIndexAnalyzerEnabled", alias = "ossindexAnalyzerEnabled")
762     private Boolean ossIndexAnalyzerEnabled;
763 
764     /**
765      * Whether or not the Sonatype OSS Index analyzer should cache results.
766      */
767     @SuppressWarnings("CanBeFinal")
768     @Parameter(property = "ossIndexAnalyzerUseCache", alias = "ossindexAnalyzerUseCache")
769     private Boolean ossIndexAnalyzerUseCache;
770 
771     /**
772      * The number of hours to wait before checking for new updates on individual packages/components from Sonatype OSS Index
773      */
774     @SuppressWarnings("CanBeFinal")
775     @Parameter(property = "ossIndexAnalyzerCacheValidForHours")
776     private Integer ossIndexAnalyzerCacheValidForHours;
777 
778     /**
779      * URL of the Sonatype OSS Index service.
780      */
781     @SuppressWarnings("CanBeFinal")
782     @Parameter(property = "ossIndexAnalyzerUrl", alias = "ossindexAnalyzerUrl")
783     private String ossIndexAnalyzerUrl;
784 
785     /**
786      * The id of a server defined in the settings.xml to authenticate Sonatype
787      * OSS Index requests and profit from higher rate limits. Provide the OSS
788      * account email address as username and password or API token as password.
789      */
790     @SuppressWarnings("CanBeFinal")
791     @Parameter(property = "ossIndexServerId")
792     private String ossIndexServerId;
793 
794     /**
795      * OSS account email address as an alternative to the indirection through
796      * the ossIndexServerId (see above). Both ossIndexUsername and
797      * ossIndexPassword must be set to use this approach instead of the server
798      * ID.
799      */
800     @SuppressWarnings("CanBeFinal")
801     @Parameter(property = "ossIndexUsername")
802     private String ossIndexUsername;
803 
804     /**
805      * OSS password or API token as an alternative to the indirection through
806      * the ossIndexServerId (see above). Both ossIndexUsername and
807      * ossIndexPassword must be set to use this approach instead of the server
808      * ID.
809      */
810     @SuppressWarnings("CanBeFinal")
811     @Parameter(property = "ossIndexPassword")
812     private String ossIndexPassword;
813 
814     /**
815      * Whether we should only warn about Sonatype OSS Index remote errors
816      * instead of failing the goal completely.
817      */
818     @SuppressWarnings("CanBeFinal")
819     @Parameter(property = "ossIndexWarnOnlyOnRemoteErrors")
820     private Boolean ossIndexWarnOnlyOnRemoteErrors;
821 
822     /**
823      * Whether or not the Elixir Mix Audit Analyzer is enabled.
824      */
825     @Parameter(property = "mixAuditAnalyzerEnabled")
826     private Boolean mixAuditAnalyzerEnabled;
827 
828     /**
829      * Sets the path for the mix_audit binary.
830      */
831     @SuppressWarnings("CanBeFinal")
832     @Parameter(property = "mixAuditPath")
833     private String mixAuditPath;
834 
835     /**
836      * Whether or not the Ruby Bundle Audit Analyzer is enabled.
837      */
838     @Parameter(property = "bundleAuditAnalyzerEnabled")
839     private Boolean bundleAuditAnalyzerEnabled;
840 
841     /**
842      * Sets the path for the bundle-audit binary.
843      */
844     @SuppressWarnings("CanBeFinal")
845     @Parameter(property = "bundleAuditPath")
846     private String bundleAuditPath;
847 
848     /**
849      * Sets the path for the working directory that the bundle-audit binary
850      * should be executed from.
851      */
852     @SuppressWarnings("CanBeFinal")
853     @Parameter(property = "bundleAuditWorkingDirectory")
854     private String bundleAuditWorkingDirectory;
855 
856     /**
857      * Whether or not the CocoaPods Analyzer is enabled.
858      */
859     @SuppressWarnings("CanBeFinal")
860     @Parameter(property = "cocoapodsAnalyzerEnabled")
861     private Boolean cocoapodsAnalyzerEnabled;
862 
863     /**
864      * Whether or not the Carthage Analyzer is enabled.
865      */
866     @SuppressWarnings("CanBeFinal")
867     @Parameter(property = "carthageAnalyzerEnabled")
868     private Boolean carthageAnalyzerEnabled;
869 
870     /**
871      * Whether or not the Swift package Analyzer is enabled.
872      */
873     @SuppressWarnings("CanBeFinal")
874     @Parameter(property = "swiftPackageManagerAnalyzerEnabled")
875     private Boolean swiftPackageManagerAnalyzerEnabled;
876     /**
877      * Whether or not the Swift package resolved Analyzer is enabled.
878      */
879     @SuppressWarnings("CanBeFinal")
880     @Parameter(property = "swiftPackageResolvedAnalyzerEnabled")
881     private Boolean swiftPackageResolvedAnalyzerEnabled;
882     /**
883      * The URL of a Nexus server's REST API end point
884      * (http://domain/nexus/service/local).
885      */
886     @SuppressWarnings("CanBeFinal")
887     @Parameter(property = "nexusUrl")
888     private String nexusUrl;
889     /**
890      * The id of a server defined in the settings.xml that configures the
891      * credentials (username and password) for a Nexus server's REST API end
892      * point. When not specified the communication with the Nexus server's REST
893      * API will be unauthenticated.
894      */
895     @SuppressWarnings("CanBeFinal")
896     @Parameter(property = "nexusServerId")
897     private String nexusServerId;
898     /**
899      * Whether or not the configured proxy is used to connect to Nexus.
900      */
901     @SuppressWarnings("CanBeFinal")
902     @Parameter(property = "nexusUsesProxy")
903     private Boolean nexusUsesProxy;
904     /**
905      * The database connection string.
906      */
907     @SuppressWarnings("CanBeFinal")
908     @Parameter(property = "connectionString")
909     private String connectionString;
910 
911     /**
912      * The database driver name. An example would be org.h2.Driver.
913      */
914     @SuppressWarnings("CanBeFinal")
915     @Parameter(property = "databaseDriverName")
916     private String databaseDriverName;
917     /**
918      * The path to the database driver if it is not on the class path.
919      */
920     @SuppressWarnings("CanBeFinal")
921     @Parameter(property = "databaseDriverPath")
922     private String databaseDriverPath;
923     /**
924      * A reference to the settings.xml settings.
925      */
926     @SuppressWarnings("CanBeFinal")
927     @Parameter(defaultValue = "${settings}", readonly = true, required = true)
928     private org.apache.maven.settings.Settings settingsXml;
929 
930     /**
931      * The settingsDecryptor from Maven to decrypt passwords from Settings.xml servers section
932      */
933     @Component
934     private SettingsDecrypter settingsDecrypter;
935 
936     /**
937      * The database user name.
938      */
939     @Parameter(property = "databaseUser")
940     private String databaseUser;
941     /**
942      * The password to use when connecting to the database. The `serverId` should be used instead otherwise maven debug logging could expose the password.
943      */
944     @Parameter(property = "databasePassword")
945     private String databasePassword;
946     /**
947      * A comma-separated list of file extensions to add to analysis next to jar,
948      * zip, ....
949      */
950     @SuppressWarnings("CanBeFinal")
951     @Parameter(property = "zipExtensions")
952     private String zipExtensions;
953     /**
954      * Skip Dependency Check altogether.
955      */
956     @SuppressWarnings("CanBeFinal")
957     @Parameter(property = "dependency-check.skip", defaultValue = "false")
958     private boolean skip = false;
959     /**
960      * Skip Analysis for Test Scope Dependencies.
961      */
962     @SuppressWarnings("CanBeFinal")
963     @Parameter(property = "skipTestScope", defaultValue = "true")
964     private boolean skipTestScope = true;
965     /**
966      * Skip Analysis for Runtime Scope Dependencies.
967      */
968     @SuppressWarnings("CanBeFinal")
969     @Parameter(property = "skipRuntimeScope", defaultValue = "false")
970     private boolean skipRuntimeScope = false;
971     /**
972      * Skip Analysis for Provided Scope Dependencies.
973      */
974     @SuppressWarnings("CanBeFinal")
975     @Parameter(property = "skipProvidedScope", defaultValue = "false")
976     private boolean skipProvidedScope = false;
977 
978     /**
979      * Skip Analysis for System Scope Dependencies.
980      */
981     @SuppressWarnings("CanBeFinal")
982     @Parameter(property = "skipSystemScope", defaultValue = "false")
983     private boolean skipSystemScope = false;
984 
985     /**
986      * Skip Analysis for dependencyManagement section.
987      */
988     @SuppressWarnings("CanBeFinal")
989     @Parameter(property = "skipDependencyManagement", defaultValue = "true")
990     private boolean skipDependencyManagement = true;
991 
992     /**
993      * Skip analysis for dependencies which type matches this regular
994      * expression. This filters on the `type` of dependency as defined in the
995      * dependency section: jar, pom, test-jar, etc.
996      */
997     @SuppressWarnings("CanBeFinal")
998     @Parameter(property = "skipArtifactType")
999     private String skipArtifactType;
1000 
1001     /**
1002      * The data directory, hold DC SQL DB.
1003      */
1004     @SuppressWarnings("CanBeFinal")
1005     @Parameter(property = "dataDirectory")
1006     private String dataDirectory;
1007 
1008     /**
1009      * The name of the DC DB.
1010      */
1011     @SuppressWarnings("CanBeFinal")
1012     @Parameter(property = "dbFilename")
1013     private String dbFilename;
1014     /**
1015      * The server id in the settings.xml; used to retrieve encrypted passwords
1016      * from the settings.xml. This is used for the database username and
1017      * password.
1018      */
1019     @SuppressWarnings("CanBeFinal")
1020     @Parameter(property = "serverId")
1021     private String serverId;
1022     /**
1023      * The NVD API Key. The parameters {@link #nvdApiKeyEnvironmentVariable} or {@link #nvdApiServerId} should be used instead otherwise
1024      * Maven debug logging could expose the API Key (see <a href="https://github.com/advisories/GHSA-qqhq-8r2c-c3f5">GHSA-qqhq-8r2c-c3f5</a>).
1025      * This takes precedence over {@link #nvdApiServerId} and {@link #nvdApiKeyEnvironmentVariable}.
1026      */
1027     @SuppressWarnings("CanBeFinal")
1028     @Parameter(property = "nvdApiKey")
1029     private String nvdApiKey;
1030     /**
1031      * The maximum number of retry requests for a single call to the NVD API.
1032      */
1033     @SuppressWarnings("CanBeFinal")
1034     @Parameter(property = "nvdMaxRetryCount")
1035     private Integer nvdMaxRetryCount;
1036     /**
1037      * The server id in the settings.xml; used to retrieve encrypted API Key
1038      * from the settings.xml for the NVD API Key. Note that the password is used
1039      * as the API Key.
1040      * Is potentially overwritten by {@link #nvdApiKeyEnvironmentVariable} or {@link #nvdApiKey}.
1041      */
1042     @SuppressWarnings("CanBeFinal")
1043     @Parameter(property = "nvdApiServerId")
1044     private String nvdApiServerId;
1045     /**
1046      * The environment variable from which to retrieve the API key for the NVD API.
1047      * Takes precedence over {@link #nvdApiServerId} but is potentially overwritten by {@link #nvdApiKey}.
1048      * This is the recommended option to pass the API key in CI builds.
1049      */
1050     @SuppressWarnings("CanBeFinal")
1051     @Parameter(property = "nvdApiKeyEnvironmentVariable")
1052     private String nvdApiKeyEnvironmentVariable;
1053     /**
1054      * The number of hours to wait before checking for new updates from the NVD.
1055      */
1056     @SuppressWarnings("CanBeFinal")
1057     @Parameter(property = "nvdValidForHours")
1058     private Integer nvdValidForHours;
1059     /**
1060      * The NVD API Endpoint; setting this is uncommon.
1061      */
1062     @SuppressWarnings("CanBeFinal")
1063     @Parameter(property = "nvdApiEndpoint")
1064     private String nvdApiEndpoint;
1065     /**
1066      * The NVD API Data Feed URL.
1067      */
1068     @SuppressWarnings("CanBeFinal")
1069     @Parameter(property = "nvdDatafeedUrl")
1070     private String nvdDatafeedUrl;
1071 
1072     /**
1073      * The server id in the settings.xml; used to retrieve encrypted credentials
1074      * from the settings.xml for the NVD Data Feed.<br/>
1075      * Credentials with only a password will be used for Bearer auth, credentials with both user and password for Basic auth.
1076      */
1077     @SuppressWarnings("CanBeFinal")
1078     @Parameter(property = "nvdDatafeedServerId")
1079     private String nvdDatafeedServerId;
1080     /**
1081      * The username for basic auth to the NVD Data Feed. A `nvdDatafeedServerId` with user/password set should be used
1082      * instead otherwise maven debug logging could expose the password.
1083      */
1084     @SuppressWarnings("CanBeFinal")
1085     @Parameter(property = "nvdUser")
1086     private String nvdUser;
1087     /**
1088      * The password for basic auth to the NVD Data Feed. A `nvdDatafeedServerId` with user/password set should be used
1089      * instead otherwise maven debug logging could expose the password.
1090      */
1091     @SuppressWarnings("CanBeFinal")
1092     @Parameter(property = "nvdPassword")
1093     private String nvdPassword;
1094     /**
1095      * The token for bearer auth to the NVD Data Feed. A `nvdDatafeedServerId` with only password set should be used
1096      * instead otherwise maven debug logging could expose the token.
1097      */
1098     @SuppressWarnings("CanBeFinal")
1099     @Parameter(property = "nvdBearerToken")
1100     private String nvdBearerToken;
1101     /**
1102      * The time in milliseconds to wait between downloading NVD API data.
1103      */
1104     @SuppressWarnings("CanBeFinal")
1105     @Parameter(property = "nvdApiDelay")
1106     private Integer nvdApiDelay;
1107 
1108     /**
1109      * The number records for a single page from NVD API (must be <=2000).
1110      */
1111     @SuppressWarnings("CanBeFinal")
1112     @Parameter(property = "nvdApiResultsPerPage")
1113     private Integer nvdApiResultsPerPage;
1114 
1115     /**
1116      * The path to dotnet core.
1117      */
1118     @SuppressWarnings("CanBeFinal")
1119     @Parameter(property = "pathToCore")
1120     private String pathToCore;
1121     /**
1122      * The hosted suppressions file URL.
1123      */
1124     @SuppressWarnings("CanBeFinal")
1125     @Parameter(property = "hostedSuppressionsUrl")
1126     private String hostedSuppressionsUrl;
1127     /**
1128      * The password used for Basic auth to the suppressionFiles.
1129      */
1130     @SuppressWarnings("CanBeFinal")
1131     @Parameter(property = "hostedSuppressionsUser")
1132     private String hostedSuppressionsUser;
1133     /**
1134      * The password used for Basic auth to the suppressionFiles. The `hostedSuppressionsServerId` with user/password should be used instead otherwise maven debug logging could expose the password.
1135      */
1136     @SuppressWarnings("CanBeFinal")
1137     @Parameter(property = "hostedSuppressionsPassword")
1138     private String hostedSuppressionsPassword;
1139     /**
1140      * The token used for Bearer auth to the suppressionFiles. The `hostedSuppressionsServerId` with only password should
1141      * be used instead otherwise maven debug logging could expose the token.
1142      */
1143     @SuppressWarnings("CanBeFinal")
1144     @Parameter(property = "hostedSuppressionsBearerToken")
1145     private String hostedSuppressionsBearerToken;
1146     /**
1147      * The server id in the settings.xml used to retrieve encrypted passwords
1148      * from the settings.xml for a mirror of the HostedSuppressions XML file.
1149      */
1150     @SuppressWarnings("CanBeFinal")
1151     @Parameter(property = "hostedSuppressionsServerId")
1152     private String hostedSuppressionsServerId;
1153     /**
1154      * Whether the hosted suppressions file will be updated regardless of the
1155      * `autoupdate` settings.
1156      */
1157     @SuppressWarnings("CanBeFinal")
1158     @Parameter(property = "hostedSuppressionsForceUpdate")
1159     private Boolean hostedSuppressionsForceUpdate;
1160     /**
1161      * Whether the hosted suppressions file will be used.
1162      */
1163     @SuppressWarnings("CanBeFinal")
1164     @Parameter(property = "hostedSuppressionsEnabled")
1165     private Boolean hostedSuppressionsEnabled;
1166     /**
1167      * Skip excessive hosted suppression file update checks for a designated
1168      * duration in hours (defaults to 2 hours).
1169      */
1170     @SuppressWarnings("CanBeFinal")
1171     @Parameter(property = "hostedSuppressionsValidForHours")
1172     private Integer hostedSuppressionsValidForHours;
1173 
1174     /**
1175      * The RetireJS Analyzer configuration:
1176      * <pre>
1177      *   filters: an array of filter patterns that are used to exclude JS files that contain a match
1178      *   filterNonVulnerable: a boolean that when true will remove non-vulnerable JS from the report
1179      *
1180      * Example:
1181      *   &lt;retirejs&gt;
1182      *     &lt;filters&gt;
1183      *       &lt;filter&gt;copyright 2018\(c\) Jeremy Long&lt;/filter&gt;
1184      *     &lt;/filters&gt;
1185      *     &lt;filterNonVulnerable&gt;true&lt;/filterNonVulnerable&gt;
1186      *   &lt;/retirejs&gt;
1187      * </pre>
1188      */
1189     @SuppressWarnings("CanBeFinal")
1190     @Parameter(property = "retirejs")
1191     private Retirejs retirejs;
1192 
1193     /**
1194      * The list of patterns to exclude from the check. This is matched against the project dependencies (and will implicitly also remove transitive dependencies from matching dependencies).
1195      * Each pattern has the format {@code [groupId]:[artifactId]:[type]:[version]}. You can leave out unspecified parts (which is equal to using {@code *}).
1196      * Examples: {@code org.apache.*} would match all artifacts whose group id starts with {@code org.apache.}, and {@code :::*-SNAPSHOT} would match all snapshot artifacts.
1197      */
1198     @Parameter(property = "odc.excludes")
1199     private List<String> excludes;
1200 
1201     /**
1202      * The artifact scope filter.
1203      */
1204     private Filter<String> artifactScopeExcluded;
1205 
1206     /**
1207      * Filter for artifact type.
1208      */
1209     private Filter<String> artifactTypeExcluded;
1210 
1211     /**
1212      * An collection of <code>fileSet</code>s that specify additional files
1213      * and/or directories (from the basedir) to analyze as part of the scan. If
1214      * not specified, defaults to Maven conventions of: src/main/resources,
1215      * src/main/filters, and src/main/webapp. Note, this cannot be set via the
1216      * command line - use `scanDirectory` instead.
1217      */
1218     @Parameter
1219     private List<FileSet> scanSet;
1220     /**
1221      * A list of directories to scan. Note, this should only be used via the
1222      * command line - if configuring the directories to scan consider using the
1223      * `scanSet` instead.
1224      */
1225     @Parameter(property = "scanDirectory")
1226     private List<String> scanDirectory;
1227 
1228     /**
1229      * Whether the project's plugins should also be scanned.
1230      */
1231     @SuppressWarnings("CanBeFinal")
1232     @Parameter(property = "odc.plugins.scan", defaultValue = "false", required = false)
1233     private boolean scanPlugins = false;
1234     /**
1235      * Whether the project's dependencies should also be scanned.
1236      */
1237     @SuppressWarnings("CanBeFinal")
1238     @Parameter(property = "odc.dependencies.scan", defaultValue = "true", required = false)
1239     private boolean scanDependencies = true;
1240     /**
1241      * The proxy configuration.
1242      */
1243     @Parameter
1244     private ProxyConfig proxy;
1245 
1246     // </editor-fold>
1247     //<editor-fold defaultstate="collapsed" desc="Base Maven implementation">
1248 
1249     /**
1250      * Determines if the groupId, artifactId, and version of the Maven
1251      * dependency and artifact match.
1252      *
1253      * @param d the Maven dependency
1254      * @param a the Maven artifact
1255      * @return true if the groupId, artifactId, and version match
1256      */
1257     private static boolean artifactsMatch(org.apache.maven.model.Dependency d, Artifact a) {
1258         return isEqualOrNull(a.getArtifactId(), d.getArtifactId())
1259                 && isEqualOrNull(a.getGroupId(), d.getGroupId())
1260                 && isEqualOrNull(a.getVersion(), d.getVersion());
1261     }
1262 
1263     /**
1264      * Compares two strings for equality; if both strings are null they are
1265      * considered equal.
1266      *
1267      * @param left the first string to compare
1268      * @param right the second string to compare
1269      * @return true if the strings are equal or if they are both null; otherwise
1270      * false.
1271      */
1272     private static boolean isEqualOrNull(String left, String right) {
1273         return (left != null && left.equals(right)) || (left == null && right == null);
1274     }
1275 
1276     /**
1277      * Executes dependency-check.
1278      *
1279      * @throws MojoExecutionException thrown if there is an exception executing
1280      * the mojo
1281      * @throws MojoFailureException thrown if dependency-check failed the build
1282      */
1283     @Override
1284     public void execute() throws MojoExecutionException, MojoFailureException {
1285         generatingSite = false;
1286         final boolean shouldSkip = Boolean.parseBoolean(System.getProperty("dependency-check.skip", Boolean.toString(skip)));
1287         if (shouldSkip) {
1288             getLog().info("Skipping " + getName(Locale.US));
1289         } else {
1290             project.setContextValue("dependency-check-output-dir", this.outputDirectory);
1291             runCheck();
1292         }
1293     }
1294 
1295     /**
1296      * Returns true if the Maven site is being generated.
1297      *
1298      * @return true if the Maven site is being generated
1299      */
1300     protected boolean isGeneratingSite() {
1301         return generatingSite;
1302     }
1303 
1304     /**
1305      * Returns the connection string.
1306      *
1307      * @return the connection string
1308      */
1309     protected String getConnectionString() {
1310         return connectionString;
1311     }
1312 
1313     /**
1314      * Returns if the mojo should fail the build if an exception occurs.
1315      *
1316      * @return whether or not the mojo should fail the build
1317      */
1318     protected boolean isFailOnError() {
1319         return failOnError;
1320     }
1321 
1322     /**
1323      * Generates the Dependency-Check Site Report.
1324      *
1325      * @param sink the sink to write the report to
1326      * @param locale the locale to use when generating the report
1327      * @throws MavenReportException if a maven report exception occurs
1328      */
1329     public void generate(Sink sink, Locale locale) throws MavenReportException {
1330         final boolean shouldSkip = Boolean.parseBoolean(System.getProperty("dependency-check.skip", Boolean.toString(skip)));
1331         if (shouldSkip) {
1332             getLog().info("Skipping report generation " + getName(Locale.US));
1333             return;
1334         }
1335 
1336         generatingSite = true;
1337         project.setContextValue("dependency-check-output-dir", getReportOutputDirectory());
1338         try {
1339             runCheck();
1340         } catch (MojoExecutionException ex) {
1341             throw new MavenReportException(ex.getMessage(), ex);
1342         } catch (MojoFailureException ex) {
1343             getLog().warn("Vulnerabilities were identifies that exceed the CVSS threshold for failing the build");
1344         }
1345     }
1346 
1347     /**
1348      * Returns the correct output directory depending on if a site is being
1349      * executed or not.
1350      *
1351      * @return the directory to write the report(s)
1352      * @throws MojoExecutionException thrown if there is an error loading the
1353      * file path
1354      */
1355     protected File getCorrectOutputDirectory() throws MojoExecutionException {
1356         return getCorrectOutputDirectory(this.project);
1357     }
1358 
1359     /**
1360      * Returns the correct output directory depending on if a site is being
1361      * executed or not.
1362      *
1363      * @param current the Maven project to get the output directory from
1364      * @return the directory to write the report(s)
1365      */
1366     protected File getCorrectOutputDirectory(MavenProject current) {
1367         final Object obj = current.getContextValue("dependency-check-output-dir");
1368         if (obj != null && obj instanceof File) {
1369             return (File) obj;
1370         }
1371         //else we guess
1372         File target = new File(current.getBuild().getDirectory());
1373         if (target.getParentFile() != null && "target".equals(target.getParentFile().getName())) {
1374             target = target.getParentFile();
1375         }
1376         return target;
1377     }
1378 
1379     /**
1380      * Scans the project's artifacts and adds them to the engine's dependency
1381      * list.
1382      *
1383      * @param project the project to scan the dependencies of
1384      * @param engine the engine to use to scan the dependencies
1385      * @return a collection of exceptions that may have occurred while resolving
1386      * and scanning the dependencies
1387      */
1388     protected ExceptionCollection scanArtifacts(MavenProject project, Engine engine) {
1389         return scanArtifacts(project, engine, false);
1390     }
1391 
1392     /**
1393      * Scans the project's artifacts and adds them to the engine's dependency
1394      * list.
1395      *
1396      * @param project the project to scan the dependencies of
1397      * @param engine the engine to use to scan the dependencies
1398      * @param aggregate whether the scan is part of an aggregate build
1399      * @return a collection of exceptions that may have occurred while resolving
1400      * and scanning the dependencies
1401      */
1402     protected ExceptionCollection scanArtifacts(MavenProject project, Engine engine, boolean aggregate) {
1403         try {
1404             final List<String> filterItems = Collections.singletonList(String.format("%s:%s", project.getGroupId(), project.getArtifactId()));
1405             final ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest(project, project.getRemoteArtifactRepositories());
1406             //For some reason the filter does not filter out the project being analyzed
1407             //if we pass in the filter below instead of null to the dependencyGraphBuilder
1408             final DependencyNode dn = dependencyGraphBuilder.buildDependencyGraph(buildingRequest, null);
1409 
1410             final CollectingRootDependencyGraphVisitor collectorVisitor = new CollectingRootDependencyGraphVisitor();
1411 
1412             // exclude artifact by pattern and its dependencies
1413             final DependencyNodeVisitor transitiveFilterVisitor = new FilteringDependencyTransitiveNodeVisitor(collectorVisitor,
1414                     new ArtifactDependencyNodeFilter(new PatternExcludesArtifactFilter(getExcludes())));
1415             // exclude exact artifact but not its dependencies, this filter must be appied on the root for first otherwise
1416             // in case the exclude has the same groupId of the current bundle its direct dependencies are not visited
1417             final DependencyNodeVisitor artifactFilter = new FilteringDependencyNodeVisitor(transitiveFilterVisitor,
1418                     new ArtifactDependencyNodeFilter(new ExcludesArtifactFilter(filterItems)));
1419             dn.accept(artifactFilter);
1420 
1421             //collect dependencies with the filter - see comment above.
1422             final Map<DependencyNode, List<DependencyNode>> nodes = collectorVisitor.getNodes();
1423 
1424             return collectDependencies(engine, project, nodes, buildingRequest, aggregate);
1425         } catch (DependencyGraphBuilderException ex) {
1426             final String msg = String.format("Unable to build dependency graph on project %s", project.getName());
1427             getLog().debug(msg, ex);
1428             return new ExceptionCollection(ex);
1429         }
1430     }
1431 
1432     /**
1433      * Scans the project's artifacts for plugin-dependencies and adds them to
1434      * the engine's dependency list.
1435      *
1436      * @param project the project to scan the plugin-dependencies of
1437      * @param engine the engine to use to scan the plugin-dependencies
1438      * @param exCollection the collection of exceptions that have previously
1439      * occurred
1440      * @return a collection of exceptions that may have occurred while resolving
1441      * and scanning the plugins and their dependencies
1442      */
1443     protected ExceptionCollection scanPlugins(MavenProject project, Engine engine, ExceptionCollection exCollection) {
1444         ExceptionCollection exCol = exCollection;
1445         final Set<Artifact> plugins = new HashSet<>();
1446         final Set<Artifact> buildPlugins = getProject().getPluginArtifacts();
1447         final Set<Artifact> reportPlugins = getProject().getReportArtifacts();
1448         final Set<Artifact> extensions = getProject().getExtensionArtifacts();
1449 
1450         plugins.addAll(buildPlugins);
1451         plugins.addAll(reportPlugins);
1452         plugins.addAll(extensions);
1453 
1454         final ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest(project, project.getPluginArtifactRepositories());
1455         for (Artifact plugin : plugins) {
1456             try {
1457                 final Artifact resolved = artifactResolver.resolveArtifact(buildingRequest, plugin).getArtifact();
1458 
1459                 exCol = addPluginToDependencies(project, engine, resolved, "pom.xml (plugins)", exCol);
1460 
1461                 final DefaultDependableCoordinate pluginCoordinate = new DefaultDependableCoordinate();
1462                 pluginCoordinate.setGroupId(resolved.getGroupId());
1463                 pluginCoordinate.setArtifactId(resolved.getArtifactId());
1464                 pluginCoordinate.setVersion(resolved.getVersion());
1465 
1466                 final String parent = buildReference(resolved.getGroupId(), resolved.getArtifactId(), resolved.getVersion());
1467                 for (Artifact artifact : resolveArtifactDependencies(pluginCoordinate, project)) {
1468                     exCol = addPluginToDependencies(project, engine, artifact, parent, exCol);
1469                 }
1470             } catch (ArtifactResolverException ex) {
1471                 throw new RuntimeException(ex);
1472             } catch (IllegalArgumentException ex) {
1473                 throw new RuntimeException(ex);
1474             } catch (DependencyResolverException ex) {
1475                 throw new RuntimeException(ex);
1476             }
1477         }
1478 
1479         return null;
1480 
1481     }
1482 
1483     private ExceptionCollection addPluginToDependencies(MavenProject project, Engine engine, Artifact artifact, String parent, ExceptionCollection exCollection) {
1484         ExceptionCollection exCol = exCollection;
1485         final String groupId = artifact.getGroupId();
1486         final String artifactId = artifact.getArtifactId();
1487         final String version = artifact.getVersion();
1488         final File artifactFile = artifact.getFile();
1489         if (artifactFile.isFile()) {
1490             final List<ArtifactVersion> availableVersions = artifact.getAvailableVersions();
1491 
1492             final List<Dependency> deps = engine.scan(artifactFile.getAbsoluteFile(),
1493                     project.getName() + " (plugins)");
1494             if (deps != null) {
1495                 Dependency d = null;
1496                 if (deps.size() == 1) {
1497                     d = deps.get(0);
1498                 } else {
1499                     for (Dependency possible : deps) {
1500                         if (artifactFile.getAbsoluteFile().equals(possible.getActualFile())) {
1501                             d = possible;
1502                             break;
1503                         }
1504                     }
1505                     for (Dependency dep : deps) {
1506                         if (d != null && d != dep) {
1507                             final String includedBy = buildReference(groupId, artifactId, version);
1508                             dep.addIncludedBy(includedBy, "plugins");
1509                         }
1510                     }
1511                 }
1512                 if (d != null) {
1513                     final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version);
1514                     d.addAsEvidence("pom", ma, Confidence.HIGHEST);
1515                     if (parent != null) {
1516                         d.addIncludedBy(parent, "plugins");
1517                     } else {
1518                         final String includedby = buildReference(
1519                                 project.getGroupId(),
1520                                 project.getArtifactId(),
1521                                 project.getVersion());
1522                         d.addIncludedBy(includedby, "plugins");
1523                     }
1524                     if (availableVersions != null) {
1525                         for (ArtifactVersion av : availableVersions) {
1526                             d.addAvailableVersion(av.toString());
1527                         }
1528                     }
1529                 }
1530             }
1531         } else {
1532             if (exCol == null) {
1533                 exCol = new ExceptionCollection();
1534             }
1535             exCol.addException(new DependencyNotFoundException("Unable to resolve plugin: "
1536                     + groupId + ":" + artifactId + ":" + version));
1537         }
1538 
1539         return exCol;
1540     }
1541 
1542     private String buildReference(final String groupId, final String artifactId, final String version) {
1543         String includedBy;
1544         try {
1545             final PackageURL purl = new PackageURL("maven", groupId, artifactId, version, null, null);
1546             includedBy = purl.toString();
1547         } catch (MalformedPackageURLException ex) {
1548             getLog().warn("Unable to generate build reference for " + groupId
1549                     + ":" + artifactId + ":" + version, ex);
1550             includedBy = groupId + ":" + artifactId + ":" + version;
1551         }
1552         return includedBy;
1553     }
1554 
1555     protected Set<Artifact> resolveArtifactDependencies(final DependableCoordinate artifact, MavenProject project)
1556             throws DependencyResolverException {
1557         final ProjectBuildingRequest buildingRequest = newResolveArtifactProjectBuildingRequest(project, project.getRemoteArtifactRepositories());
1558 
1559         final Iterable<ArtifactResult> artifactResults = dependencyResolver.resolveDependencies(buildingRequest, artifact, null);
1560 
1561         final Set<Artifact> artifacts = new HashSet<>();
1562 
1563         for (ArtifactResult artifactResult : artifactResults) {
1564             artifacts.add(artifactResult.getArtifact());
1565         }
1566 
1567         return artifacts;
1568 
1569     }
1570 
1571     /**
1572      * Converts the dependency to a dependency node object.
1573      *
1574      * @param nodes the list of dependency nodes
1575      * @param buildingRequest the Maven project building request
1576      * @param parent the parent node
1577      * @param dependency the dependency to convert
1578      * @return the resulting dependency node
1579      * @throws ArtifactResolverException thrown if the artifact could not be
1580      * retrieved
1581      */
1582     private DependencyNode toDependencyNode(List<DependencyNode> nodes, ProjectBuildingRequest buildingRequest,
1583                                             DependencyNode parent, org.apache.maven.model.Dependency dependency) throws ArtifactResolverException {
1584 
1585         final DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate();
1586 
1587         coordinate.setGroupId(dependency.getGroupId());
1588         coordinate.setArtifactId(dependency.getArtifactId());
1589         String version = null;
1590         final VersionRange vr;
1591         try {
1592             vr = VersionRange.createFromVersionSpec(dependency.getVersion());
1593         } catch (InvalidVersionSpecificationException ex) {
1594             throw new ArtifactResolverException("Invalid version specification: "
1595                     + dependency.getGroupId() + ":"
1596                     + dependency.getArtifactId() + ":"
1597                     + dependency.getVersion(), ex);
1598         }
1599         if (vr.hasRestrictions()) {
1600             version = findVersion(nodes, dependency.getGroupId(), dependency.getArtifactId());
1601             if (version == null) {
1602                 //TODO - this still may fail if the restriction is not a valid version number (i.e. only 2.9 instead of 2.9.1)
1603                 //need to get available versions and filter on the restrictions.
1604                 if (vr.getRecommendedVersion() != null) {
1605                     version = vr.getRecommendedVersion().toString();
1606                 } else if (vr.hasRestrictions()) {
1607                     for (Restriction restriction : vr.getRestrictions()) {
1608                         if (restriction.getLowerBound() != null) {
1609                             version = restriction.getLowerBound().toString();
1610                         }
1611                         if (restriction.getUpperBound() != null) {
1612                             version = restriction.getUpperBound().toString();
1613                         }
1614                     }
1615                 } else {
1616                     version = vr.toString();
1617                 }
1618             }
1619         }
1620         if (version == null) {
1621             version = dependency.getVersion();
1622         }
1623         coordinate.setVersion(version);
1624 
1625         final ArtifactType type = session.getRepositorySession().getArtifactTypeRegistry().get(dependency.getType());
1626         coordinate.setExtension(type.getExtension());
1627         coordinate.setClassifier((null == dependency.getClassifier() || dependency.getClassifier().isEmpty())
1628                 ? type.getClassifier() : dependency.getClassifier());
1629         final Artifact artifact = artifactResolver.resolveArtifact(buildingRequest, coordinate).getArtifact();
1630         artifact.setScope(dependency.getScope());
1631         return new DefaultDependencyNode(parent, artifact, dependency.getVersion(), dependency.getScope(), null);
1632     }
1633 
1634     /**
1635      * Returns the version from the list of nodes that match the given groupId
1636      * and artifactID.
1637      *
1638      * @param nodes the nodes to search
1639      * @param groupId the group id to find
1640      * @param artifactId the artifact id to find
1641      * @return the version from the list of nodes that match the given groupId
1642      * and artifactID; otherwise <code>null</code> is returned
1643      */
1644     private String findVersion(List<DependencyNode> nodes, String groupId, String artifactId) {
1645         final Optional<DependencyNode> f = nodes.stream().filter(p
1646                 -> groupId.equals(p.getArtifact().getGroupId())
1647                 && artifactId.equals(p.getArtifact().getArtifactId())).findFirst();
1648         if (f.isPresent()) {
1649             return f.get().getArtifact().getVersion();
1650         }
1651         return null;
1652     }
1653 
1654     /**
1655      * Collect dependencies from the dependency management section.
1656      *
1657      * @param engine reference to the ODC engine
1658      * @param buildingRequest the Maven project building request
1659      * @param project the project being analyzed
1660      * @param nodes the list of dependency nodes
1661      * @param aggregate whether or not this is an aggregate analysis
1662      * @return a collection of exceptions if any occurred; otherwise
1663      * <code>null</code>
1664      */
1665     private ExceptionCollection collectDependencyManagementDependencies(Engine engine, ProjectBuildingRequest buildingRequest,
1666                                                                         MavenProject project, List<DependencyNode> nodes, boolean aggregate) {
1667         if (skipDependencyManagement || project.getDependencyManagement() == null) {
1668             return null;
1669         }
1670 
1671         ExceptionCollection exCol = null;
1672         for (org.apache.maven.model.Dependency dependency : project.getDependencyManagement().getDependencies()) {
1673             try {
1674                 nodes.add(toDependencyNode(nodes, buildingRequest, null, dependency));
1675             } catch (ArtifactResolverException ex) {
1676                 getLog().debug(String.format("Aggregate : %s", aggregate));
1677                 boolean addException = true;
1678                 //CSOFF: EmptyBlock
1679                 if (!aggregate) {
1680                     // do nothing, exception is to be reported
1681                 } else if (addReactorDependency(engine,
1682                         new DefaultArtifact(dependency.getGroupId(), dependency.getArtifactId(),
1683                                 dependency.getVersion(), dependency.getScope(), dependency.getType(), dependency.getClassifier(),
1684                                 new DefaultArtifactHandler()), project)) {
1685                     addException = false;
1686                 }
1687                 //CSON: EmptyBlock
1688                 if (addException) {
1689                     if (exCol == null) {
1690                         exCol = new ExceptionCollection();
1691                     }
1692                     exCol.addException(ex);
1693                 }
1694             }
1695         }
1696         return exCol;
1697     }
1698 
1699     /**
1700      * Resolves the projects artifacts using Aether and scans the resulting
1701      * dependencies.
1702      *
1703      * @param engine the core dependency-check engine
1704      * @param project the project being scanned
1705      * @param nodeMap the map of dependency nodes, generally obtained via the
1706      * DependencyGraphBuilder using the CollectingRootDependencyGraphVisitor
1707      * @param buildingRequest the Maven project building request
1708      * @param aggregate whether the scan is part of an aggregate build
1709      * @return a collection of exceptions that may have occurred while resolving
1710      * and scanning the dependencies
1711      */
1712     //CSOFF: OperatorWrap
1713     private ExceptionCollection collectMavenDependencies(Engine engine, MavenProject project,
1714                                                          Map<DependencyNode, List<DependencyNode>> nodeMap, ProjectBuildingRequest buildingRequest, boolean aggregate) {
1715 
1716         final List<ArtifactResult> allResolvedDeps = new ArrayList<>();
1717 
1718         //dependency management
1719         final List<DependencyNode> dmNodes = new ArrayList<>();
1720         ExceptionCollection exCol = collectDependencyManagementDependencies(engine, buildingRequest, project, dmNodes, aggregate);
1721         for (DependencyNode dependencyNode : dmNodes) {
1722             exCol = scanDependencyNode(dependencyNode, null, engine, project, allResolvedDeps, buildingRequest, aggregate, exCol);
1723         }
1724 
1725         //dependencies
1726         for (Map.Entry<DependencyNode, List<DependencyNode>> entry : nodeMap.entrySet()) {
1727             exCol = scanDependencyNode(entry.getKey(), null, engine, project, allResolvedDeps, buildingRequest, aggregate, exCol);
1728             for (DependencyNode dependencyNode : entry.getValue()) {
1729                 exCol = scanDependencyNode(dependencyNode, entry.getKey(), engine, project, allResolvedDeps, buildingRequest, aggregate, exCol);
1730             }
1731         }
1732         return exCol;
1733     }
1734     //CSON: OperatorWrap
1735 
1736     /**
1737      * Utility method for a work-around to MSHARED-998
1738      *
1739      * @param allDeps The List of ArtifactResults for all dependencies
1740      * @param unresolvedArtifact The ArtifactCoordinate of the artifact we're
1741      * looking for
1742      * @param project The project in whose context resolution was attempted
1743      * @return the resolved artifact matching with {@code unresolvedArtifact}
1744      * @throws DependencyNotFoundException If {@code unresolvedArtifact} could
1745      * not be found within {@code allDeps}
1746      */
1747     private Artifact findInAllDeps(final List<ArtifactResult> allDeps, final Artifact unresolvedArtifact,
1748                                    final MavenProject project)
1749             throws DependencyNotFoundException {
1750         Artifact result = null;
1751         for (final ArtifactResult res : allDeps) {
1752             if (sameArtifact(res, unresolvedArtifact)) {
1753                 result = res.getArtifact();
1754                 break;
1755             }
1756         }
1757         if (result == null) {
1758             throw new DependencyNotFoundException(String.format("Expected dependency not found in resolved artifacts for "
1759                     + "dependency %s of project-artifact %s", unresolvedArtifact, project.getArtifactId()));
1760         }
1761         return result;
1762     }
1763 
1764     /**
1765      * Utility method for a work-around to MSHARED-998
1766      *
1767      * @param res A single ArtifactResult obtained from the DependencyResolver
1768      * @param unresolvedArtifact The unresolved Artifact from the
1769      * dependencyGraph that we try to find
1770      * @return {@code true} when unresolvedArtifact is non-null and matches with
1771      * the artifact of res
1772      */
1773     private boolean sameArtifact(final ArtifactResult res, final Artifact unresolvedArtifact) {
1774         if (res == null || res.getArtifact() == null || unresolvedArtifact == null) {
1775             return false;
1776         }
1777         boolean result = Objects.equals(res.getArtifact().getGroupId(), unresolvedArtifact.getGroupId());
1778         result &= Objects.equals(res.getArtifact().getArtifactId(), unresolvedArtifact.getArtifactId());
1779         // accept any version as matching "LATEST" and any non-snapshot version as matching "RELEASE" meta-version
1780         if ("RELEASE".equals(unresolvedArtifact.getBaseVersion())) {
1781             result &= !res.getArtifact().isSnapshot();
1782         } else if (!"LATEST".equals(unresolvedArtifact.getBaseVersion())) {
1783             result &= Objects.equals(res.getArtifact().getBaseVersion(), unresolvedArtifact.getBaseVersion());
1784         }
1785         result &= Objects.equals(res.getArtifact().getClassifier(), unresolvedArtifact.getClassifier());
1786         result &= Objects.equals(res.getArtifact().getType(), unresolvedArtifact.getType());
1787         return result;
1788     }
1789 
1790     /**
1791      * @param project the {@link MavenProject}
1792      * @param dependencyNode the {@link DependencyNode}
1793      * @return the name to be used when creating a
1794      * {@link Dependency#getProjectReferences() project reference} in a
1795      * {@link Dependency}. The behavior of this method returns {@link MavenProject#getName() project.getName()}<code> + ":" +
1796      * </code>
1797      * {@link DependencyNode#getArtifact() dependencyNode.getArtifact()}{@link Artifact#getScope() .getScope()}.
1798      */
1799     protected String createProjectReferenceName(MavenProject project, DependencyNode dependencyNode) {
1800         return project.getName() + ":" + dependencyNode.getArtifact().getScope();
1801     }
1802 
1803     /**
1804      * Scans the projects dependencies including the default (or defined)
1805      * FileSets.
1806      *
1807      * @param engine the core dependency-check engine
1808      * @param project the project being scanned
1809      * @param nodes the list of dependency nodes, generally obtained via the
1810      * DependencyGraphBuilder
1811      * @param buildingRequest the Maven project building request
1812      * @param aggregate whether the scan is part of an aggregate build
1813      * @return a collection of exceptions that may have occurred while resolving
1814      * and scanning the dependencies
1815      */
1816     private ExceptionCollection collectDependencies(Engine engine, MavenProject project,
1817                                                     Map<DependencyNode, List<DependencyNode>> nodes, ProjectBuildingRequest buildingRequest, boolean aggregate) {
1818 
1819         ExceptionCollection exCol;
1820         exCol = collectMavenDependencies(engine, project, nodes, buildingRequest, aggregate);
1821 
1822         final List<FileSet> projectScan;
1823 
1824         if (scanDirectory != null && !scanDirectory.isEmpty()) {
1825             if (scanSet == null) {
1826                 scanSet = new ArrayList<>();
1827             }
1828             scanDirectory.forEach(d -> {
1829                 final FileSet fs = new FileSet();
1830                 fs.setDirectory(d);
1831                 fs.addInclude(INCLUDE_ALL);
1832                 scanSet.add(fs);
1833             });
1834         }
1835 
1836         if (scanSet == null || scanSet.isEmpty()) {
1837             // Define the default FileSets
1838             final FileSet resourcesSet = new FileSet();
1839             final FileSet filtersSet = new FileSet();
1840             final FileSet webappSet = new FileSet();
1841             final FileSet mixedLangSet = new FileSet();
1842             try {
1843                 resourcesSet.setDirectory(new File(project.getBasedir(), "src/main/resources").getCanonicalPath());
1844                 resourcesSet.addInclude(INCLUDE_ALL);
1845                 filtersSet.setDirectory(new File(project.getBasedir(), "src/main/filters").getCanonicalPath());
1846                 filtersSet.addInclude(INCLUDE_ALL);
1847                 webappSet.setDirectory(new File(project.getBasedir(), "src/main/webapp").getCanonicalPath());
1848                 webappSet.addInclude(INCLUDE_ALL);
1849                 mixedLangSet.setDirectory(project.getBasedir().getCanonicalPath());
1850                 mixedLangSet.addInclude("package.json");
1851                 mixedLangSet.addInclude("package-lock.json");
1852                 mixedLangSet.addInclude("npm-shrinkwrap.json");
1853                 mixedLangSet.addInclude("Gopkg.lock");
1854                 mixedLangSet.addInclude("go.mod");
1855                 mixedLangSet.addInclude("yarn.lock");
1856                 mixedLangSet.addInclude("pnpm-lock.yaml");
1857                 mixedLangSet.addExclude("/node_modules/");
1858             } catch (IOException ex) {
1859                 if (exCol == null) {
1860                     exCol = new ExceptionCollection();
1861                 }
1862                 exCol.addException(ex);
1863             }
1864             projectScan = new ArrayList<>();
1865             projectScan.add(resourcesSet);
1866             projectScan.add(filtersSet);
1867             projectScan.add(webappSet);
1868             projectScan.add(mixedLangSet);
1869 
1870         } else if (aggregate) {
1871             projectScan = new ArrayList<>();
1872             for (FileSet copyFrom : scanSet) {
1873                 //deep copy of the FileSet - modifying the directory if it is not absolute.
1874                 final FileSet fsCopy = new FileSet();
1875                 final File f = new File(copyFrom.getDirectory());
1876                 if (f.isAbsolute()) {
1877                     fsCopy.setDirectory(copyFrom.getDirectory());
1878                 } else {
1879                     try {
1880                         fsCopy.setDirectory(new File(project.getBasedir(), copyFrom.getDirectory()).getCanonicalPath());
1881                     } catch (IOException ex) {
1882                         if (exCol == null) {
1883                             exCol = new ExceptionCollection();
1884                         }
1885                         exCol.addException(ex);
1886                         fsCopy.setDirectory(copyFrom.getDirectory());
1887                     }
1888                 }
1889                 fsCopy.setDirectoryMode(copyFrom.getDirectoryMode());
1890                 fsCopy.setExcludes(copyFrom.getExcludes());
1891                 fsCopy.setFileMode(copyFrom.getFileMode());
1892                 fsCopy.setFollowSymlinks(copyFrom.isFollowSymlinks());
1893                 fsCopy.setIncludes(copyFrom.getIncludes());
1894                 fsCopy.setLineEnding(copyFrom.getLineEnding());
1895                 fsCopy.setMapper(copyFrom.getMapper());
1896                 fsCopy.setModelEncoding(copyFrom.getModelEncoding());
1897                 fsCopy.setOutputDirectory(copyFrom.getOutputDirectory());
1898                 fsCopy.setUseDefaultExcludes(copyFrom.isUseDefaultExcludes());
1899                 projectScan.add(fsCopy);
1900             }
1901         } else {
1902             projectScan = scanSet;
1903         }
1904 
1905         // Iterate through FileSets and scan included files
1906         final FileSetManager fileSetManager = new FileSetManager();
1907         for (FileSet fileSet : projectScan) {
1908             getLog().debug("Scanning fileSet: " + fileSet.getDirectory());
1909             final String[] includedFiles = fileSetManager.getIncludedFiles(fileSet);
1910             for (String include : includedFiles) {
1911                 final File includeFile = new File(fileSet.getDirectory(), include).getAbsoluteFile();
1912                 if (includeFile.exists()) {
1913                     engine.scan(includeFile, project.getName());
1914                 }
1915             }
1916         }
1917         return exCol;
1918     }
1919 
1920     /**
1921      * Checks if the current artifact is actually in the reactor projects that
1922      * have not yet been built. If true a virtual dependency is created based on
1923      * the evidence in the project.
1924      *
1925      * @param engine a reference to the engine being used to scan
1926      * @param artifact the artifact being analyzed in the mojo
1927      * @param depender The project that depends on this virtual dependency
1928      * @return <code>true</code> if the artifact is in the reactor; otherwise
1929      * <code>false</code>
1930      */
1931     private boolean addReactorDependency(Engine engine, Artifact artifact, final MavenProject depender) {
1932         return addVirtualDependencyFromReactor(engine, artifact, depender, "Unable to resolve %s as it has not been built yet "
1933                 + "- creating a virtual dependency instead.");
1934     }
1935 
1936     /**
1937      * Checks if the current artifact is actually in the reactor projects. If
1938      * true a virtual dependency is created based on the evidence in the
1939      * project.
1940      *
1941      * @param engine a reference to the engine being used to scan
1942      * @param artifact the artifact being analyzed in the mojo
1943      * @param depender The project that depends on this virtual dependency
1944      * @param infoLogTemplate the template for the infoLog entry written when a
1945      * virtual dependency is added. Needs a single %s placeholder for the
1946      * location of the displayName in the message
1947      * @return <code>true</code> if the artifact is in the reactor; otherwise
1948      * <code>false</code>
1949      */
1950     private boolean addVirtualDependencyFromReactor(Engine engine, Artifact artifact,
1951                                                     final MavenProject depender, String infoLogTemplate) {
1952 
1953         getLog().debug(String.format("Checking the reactor projects (%d) for %s:%s:%s",
1954                 reactorProjects.size(),
1955                 artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion()));
1956 
1957         for (MavenProject prj : reactorProjects) {
1958 
1959             getLog().debug(String.format("Comparing %s:%s:%s to %s:%s:%s",
1960                     artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion(),
1961                     prj.getGroupId(), prj.getArtifactId(), prj.getVersion()));
1962 
1963             if (prj.getArtifactId().equals(artifact.getArtifactId())
1964                     && prj.getGroupId().equals(artifact.getGroupId())
1965                     && prj.getVersion().equals(artifact.getBaseVersion())) {
1966 
1967                 final String displayName = String.format("%s:%s:%s",
1968                         prj.getGroupId(), prj.getArtifactId(), prj.getVersion());
1969                 getLog().info(String.format(infoLogTemplate,
1970                         displayName));
1971                 final Dependency d = newDependency(prj);
1972                 final String key = String.format("%s:%s:%s", prj.getGroupId(), prj.getArtifactId(), prj.getVersion());
1973                 d.setSha1sum(Checksum.getSHA1Checksum(key));
1974                 d.setSha256sum(Checksum.getSHA256Checksum(key));
1975                 d.setMd5sum(Checksum.getMD5Checksum(key));
1976                 d.setEcosystem(JarAnalyzer.DEPENDENCY_ECOSYSTEM);
1977                 d.setDisplayFileName(displayName);
1978                 d.addProjectReference(depender.getName());
1979                 final String includedby = buildReference(
1980                         depender.getGroupId(),
1981                         depender.getArtifactId(),
1982                         depender.getVersion());
1983                 d.addIncludedBy(includedby);
1984                 d.addEvidence(EvidenceType.PRODUCT, "project", "artifactid", prj.getArtifactId(), Confidence.HIGHEST);
1985                 d.addEvidence(EvidenceType.VENDOR, "project", "artifactid", prj.getArtifactId(), Confidence.LOW);
1986 
1987                 d.addEvidence(EvidenceType.VENDOR, "project", "groupid", prj.getGroupId(), Confidence.HIGHEST);
1988                 d.addEvidence(EvidenceType.PRODUCT, "project", "groupid", prj.getGroupId(), Confidence.LOW);
1989                 d.setEcosystem(JarAnalyzer.DEPENDENCY_ECOSYSTEM);
1990                 Identifier id;
1991                 try {
1992                     id = new PurlIdentifier(StandardTypes.MAVEN, artifact.getGroupId(),
1993                             artifact.getArtifactId(), artifact.getVersion(), Confidence.HIGHEST);
1994                 } catch (MalformedPackageURLException ex) {
1995                     getLog().debug("Unable to create PackageURL object:" + key);
1996                     id = new GenericIdentifier("maven:" + key, Confidence.HIGHEST);
1997                 }
1998                 d.addSoftwareIdentifier(id);
1999                 //TODO unify the setName/version and package path - they are equivelent ideas submitted by two seperate committers
2000                 d.setName(String.format("%s:%s", prj.getGroupId(), prj.getArtifactId()));
2001                 d.setVersion(prj.getVersion());
2002                 d.setPackagePath(displayName);
2003                 if (prj.getDescription() != null) {
2004                     JarAnalyzer.addDescription(d, prj.getDescription(), "project", "description");
2005                 }
2006                 for (License l : prj.getLicenses()) {
2007                     final StringBuilder license = new StringBuilder();
2008                     if (l.getName() != null) {
2009                         license.append(l.getName());
2010                     }
2011                     if (l.getUrl() != null) {
2012                         license.append(" ").append(l.getUrl());
2013                     }
2014                     if (d.getLicense() == null) {
2015                         d.setLicense(license.toString());
2016                     } else if (!d.getLicense().contains(license)) {
2017                         d.setLicense(String.format("%s%n%s", d.getLicense(), license));
2018                     }
2019                 }
2020                 engine.addDependency(d);
2021                 return true;
2022             }
2023         }
2024         return false;
2025     }
2026 
2027     Dependency newDependency(MavenProject prj) {
2028         final File pom = new File(prj.getBasedir(), "pom.xml");
2029 
2030         if (pom.isFile()) {
2031             getLog().debug("Adding virtual dependency from pom.xml");
2032             return new Dependency(pom, true);
2033         } else if (prj.getFile().isFile()) {
2034             getLog().debug("Adding virtual dependency from file");
2035             return new Dependency(prj.getFile(), true);
2036         } else {
2037             return new Dependency(true);
2038         }
2039     }
2040 
2041     /**
2042      * Checks if the current artifact is actually in the reactor projects. If
2043      * true a virtual dependency is created based on the evidence in the
2044      * project.
2045      *
2046      * @param engine a reference to the engine being used to scan
2047      * @param artifact the artifact being analyzed in the mojo
2048      * @param depender The project that depends on this virtual dependency
2049      * @return <code>true</code> if the artifact is a snapshot artifact in the
2050      * reactor; otherwise <code>false</code>
2051      */
2052     private boolean addSnapshotReactorDependency(Engine engine, Artifact artifact, final MavenProject depender) {
2053         if (!artifact.isSnapshot()) {
2054             return false;
2055         }
2056         return addVirtualDependencyFromReactor(engine, artifact, depender, "Found snapshot reactor project in aggregate for %s - "
2057                 + "creating a virtual dependency as the snapshot found in the repository may contain outdated dependencies.");
2058     }
2059 
2060     /**
2061      * @param project The target project to create a building request for.
2062      * @param repos the artifact repositories to use.
2063      * @return Returns a new ProjectBuildingRequest populated from the current
2064      * session and the target project remote repositories, used to resolve
2065      * artifacts.
2066      */
2067     public ProjectBuildingRequest newResolveArtifactProjectBuildingRequest(MavenProject project, List<ArtifactRepository> repos) {
2068         final ProjectBuildingRequest buildingRequest = new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
2069         buildingRequest.setRemoteRepositories(repos);
2070         buildingRequest.setProject(project);
2071         return buildingRequest;
2072     }
2073 
2074     /**
2075      * Executes the dependency-check scan and generates the necessary report.
2076      *
2077      * @throws MojoExecutionException thrown if there is an exception running
2078      * the scan
2079      * @throws MojoFailureException thrown if dependency-check is configured to
2080      * fail the build
2081      */
2082     protected void runCheck() throws MojoExecutionException, MojoFailureException {
2083         muteNoisyLoggers();
2084         try (Engine engine = initializeEngine()) {
2085             ExceptionCollection exCol = null;
2086             if (scanDependencies) {
2087                 exCol = scanDependencies(engine);
2088             }
2089             if (scanPlugins) {
2090                 exCol = scanPlugins(engine, exCol);
2091             }
2092             try {
2093                 engine.analyzeDependencies();
2094             } catch (ExceptionCollection ex) {
2095                 exCol = handleAnalysisExceptions(exCol, ex);
2096             }
2097             if (exCol == null || !exCol.isFatal()) {
2098 
2099                 File outputDir = getCorrectOutputDirectory(this.getProject());
2100                 if (outputDir == null) {
2101                     //in some regards we shouldn't be writing this, but we are anyway.
2102                     //we shouldn't write this because nothing is configured to generate this report.
2103                     outputDir = new File(this.getProject().getBuild().getDirectory());
2104                 }
2105                 try {
2106                     final MavenProject p = this.getProject();
2107                     for (String f : getFormats()) {
2108                         engine.writeReports(p.getName(), p.getGroupId(), p.getArtifactId(), p.getVersion(), outputDir, f, exCol);
2109                     }
2110                 } catch (ReportException ex) {
2111                     if (exCol == null) {
2112                         exCol = new ExceptionCollection(ex);
2113                     } else {
2114                         exCol.addException(ex);
2115                     }
2116                     if (this.isFailOnError()) {
2117                         throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
2118                     } else {
2119                         getLog().debug("Error writing the report", ex);
2120                     }
2121                 }
2122                 showSummary(this.getProject(), engine.getDependencies());
2123                 checkForFailure(engine.getDependencies());
2124                 if (exCol != null && this.isFailOnError()) {
2125                     throw new MojoExecutionException("One or more exceptions occurred during dependency-check analysis", exCol);
2126                 }
2127             }
2128         } catch (DatabaseException ex) {
2129             if (getLog().isDebugEnabled()) {
2130                 getLog().debug("Database connection error", ex);
2131             }
2132             final String msg = "An exception occurred connecting to the local database. Please see the log file for more details.";
2133             if (this.isFailOnError()) {
2134                 throw new MojoExecutionException(msg, ex);
2135             }
2136             getLog().error(msg, ex);
2137         } finally {
2138             getSettings().cleanup();
2139         }
2140     }
2141 
2142     /**
2143      * Combines the two exception collections and if either are fatal, throw an
2144      * MojoExecutionException
2145      *
2146      * @param currentEx the primary exception collection
2147      * @param newEx the new exception collection to add
2148      * @return the combined exception collection
2149      * @throws MojoExecutionException thrown if dependency-check is configured
2150      * to fail on errors
2151      */
2152     private ExceptionCollection handleAnalysisExceptions(ExceptionCollection currentEx, ExceptionCollection newEx) throws MojoExecutionException {
2153         ExceptionCollection returnEx = currentEx;
2154         if (returnEx == null) {
2155             returnEx = newEx;
2156         } else {
2157             returnEx.getExceptions().addAll(newEx.getExceptions());
2158             if (newEx.isFatal()) {
2159                 returnEx.setFatal(true);
2160             }
2161         }
2162         if (returnEx.isFatal()) {
2163             final String msg = String.format("Fatal exception(s) analyzing %s", getProject().getName());
2164             if (this.isFailOnError()) {
2165                 throw new MojoExecutionException(msg, returnEx);
2166             }
2167             getLog().error(msg);
2168             if (getLog().isDebugEnabled()) {
2169                 getLog().debug(returnEx);
2170             }
2171         } else {
2172             final String msg = String.format("Exception(s) analyzing %s", getProject().getName());
2173             if (getLog().isDebugEnabled()) {
2174                 getLog().debug(msg, returnEx);
2175             }
2176         }
2177         return returnEx;
2178     }
2179 
2180     /**
2181      * Scans the dependencies of the projects.
2182      *
2183      * @param engine the engine used to perform the scanning
2184      * @return a collection of exceptions
2185      * @throws MojoExecutionException thrown if a fatal exception occurs
2186      */
2187     protected abstract ExceptionCollection scanDependencies(Engine engine) throws MojoExecutionException;
2188 
2189     /**
2190      * Scans the plugins of the projects.
2191      *
2192      * @param engine the engine used to perform the scanning
2193      * @param exCol the collection of any exceptions that have previously been
2194      * captured.
2195      * @return a collection of exceptions
2196      * @throws MojoExecutionException thrown if a fatal exception occurs
2197      */
2198     protected abstract ExceptionCollection scanPlugins(Engine engine, ExceptionCollection exCol) throws MojoExecutionException;
2199 
2200     /**
2201      * Returns the report output directory.
2202      *
2203      * @return the report output directory
2204      */
2205     @Override
2206     public File getReportOutputDirectory() {
2207         return reportOutputDirectory;
2208     }
2209 
2210     /**
2211      * Sets the Reporting output directory.
2212      *
2213      * @param directory the output directory
2214      */
2215     @Override
2216     public void setReportOutputDirectory(File directory) {
2217         reportOutputDirectory = directory;
2218     }
2219 
2220     /**
2221      * Returns the output directory.
2222      *
2223      * @return the output directory
2224      */
2225     public File getOutputDirectory() {
2226         return outputDirectory;
2227     }
2228 
2229     /**
2230      * Returns whether this is an external report. This method always returns
2231      * true.
2232      *
2233      * @return <code>true</code>
2234      */
2235     @Override
2236     public final boolean isExternalReport() {
2237         return true;
2238     }
2239 
2240     /**
2241      * Returns the output name.
2242      *
2243      * @return the output name
2244      */
2245     @Override
2246     public String getOutputName() {
2247         final Set<String> selectedFormats = getFormats();
2248         if (selectedFormats.contains("HTML") || selectedFormats.contains("ALL") || selectedFormats.size() > 1) {
2249             return "dependency-check-report";
2250         } else if (selectedFormats.contains("JENKINS")) {
2251             return "dependency-check-jenkins.html";
2252         } else if (selectedFormats.contains("XML")) {
2253             return "dependency-check-report.xml";
2254         } else if (selectedFormats.contains("JUNIT")) {
2255             return "dependency-check-junit.xml";
2256         } else if (selectedFormats.contains("JSON")) {
2257             return "dependency-check-report.json";
2258         } else if (selectedFormats.contains("SARIF")) {
2259             return "dependency-check-report.sarif";
2260         } else if (selectedFormats.contains("CSV")) {
2261             return "dependency-check-report.csv";
2262         } else {
2263             getLog().warn("Unknown report format used during site generation.");
2264             return "dependency-check-report";
2265         }
2266     }
2267 
2268     /**
2269      * Returns the category name.
2270      *
2271      * @return the category name
2272      */
2273     @Override
2274     public String getCategoryName() {
2275         return MavenReport.CATEGORY_PROJECT_REPORTS;
2276     }
2277     //</editor-fold>
2278 
2279     /**
2280      * Initializes a new <code>Engine</code> that can be used for scanning. This
2281      * method should only be called in a try-with-resources to ensure that the
2282      * engine is properly closed.
2283      *
2284      * @return a newly instantiated <code>Engine</code>
2285      * @throws DatabaseException thrown if there is a database exception
2286      * @throws MojoExecutionException on configuration errors when failOnError is true
2287      * @throws MojoFailureException on configuration errors when failOnError is false
2288      */
2289     protected Engine initializeEngine() throws DatabaseException, MojoExecutionException, MojoFailureException {
2290         populateSettings();
2291         try {
2292             Downloader.getInstance().configure(settings);
2293         } catch (InvalidSettingException e) {
2294             if (this.failOnError) {
2295                 throw new MojoFailureException(e.getMessage(), e);
2296             } else {
2297                 throw new MojoExecutionException(e.getMessage(), e);
2298             }
2299         }
2300         return new Engine(settings);
2301     }
2302 
2303     //CSOFF: MethodLength
2304 
2305     /**
2306      * Takes the properties supplied and updates the dependency-check settings.
2307      * Additionally, this sets the system properties required to change the
2308      * proxy URL, port, and connection timeout.
2309      */
2310     protected void populateSettings() throws MojoFailureException, MojoExecutionException {
2311         settings = new Settings();
2312         InputStream mojoProperties = null;
2313         try {
2314             mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
2315             settings.mergeProperties(mojoProperties);
2316         } catch (IOException ex) {
2317             getLog().warn("Unable to load the dependency-check maven mojo.properties file.");
2318             if (getLog().isDebugEnabled()) {
2319                 getLog().debug("", ex);
2320             }
2321         } finally {
2322             if (mojoProperties != null) {
2323                 try {
2324                     mojoProperties.close();
2325                 } catch (IOException ex) {
2326                     if (getLog().isDebugEnabled()) {
2327                         getLog().debug("", ex);
2328                     }
2329                 }
2330             }
2331         }
2332         checkForDeprecatedParameters();
2333 
2334         settings.setStringIfNotEmpty(Settings.KEYS.MAVEN_LOCAL_REPO, mavenSettings.getLocalRepository());
2335         settings.setBooleanIfNotNull(Settings.KEYS.AUTO_UPDATE, autoUpdate);
2336         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_EXPERIMENTAL_ENABLED, enableExperimental);
2337         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIRED_ENABLED, enableRetired);
2338         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_GOLANG_DEP_ENABLED, golangDepEnabled);
2339         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_GOLANG_MOD_ENABLED, golangModEnabled);
2340         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_DART_ENABLED, dartAnalyzerEnabled);
2341         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_GOLANG_PATH, pathToGo);
2342         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_YARN_PATH, pathToYarn);
2343         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_PNPM_PATH, pathToPnpm);
2344 
2345         // use global maven proxy if provided and system properties are not set
2346         final Proxy mavenProxyHttp = getMavenProxy(PROTOCOL_HTTP);
2347         final Proxy mavenProxyHttps = getMavenProxy(PROTOCOL_HTTPS);
2348         String httpsNonProxyHosts = null;
2349         String httpNonProxyHosts = null;
2350         boolean proxySetFromMavenSettings = false;
2351         if (mavenProxyHttps != null || mavenProxyHttp != null) {
2352             final String existingHttps = StringUtils.trimToNull(System.getProperty("https.proxyHost"));
2353             if (existingHttps == null) {
2354                 proxySetFromMavenSettings = true;
2355                 if (mavenProxyHttps != null) {
2356                     setProxyServerSysPropsFromMavenProxy(mavenProxyHttps, PROTOCOL_HTTPS);
2357                     if (mavenProxyHttps.getNonProxyHosts() != null && !mavenProxyHttps.getNonProxyHosts().isEmpty()) {
2358                         httpsNonProxyHosts = mavenProxyHttps.getNonProxyHosts();
2359                     }
2360                 } else {
2361                     setProxyServerSysPropsFromMavenProxy(mavenProxyHttp, PROTOCOL_HTTPS);
2362                     httpsNonProxyHosts = mavenProxyHttp.getNonProxyHosts();
2363                 }
2364             }
2365             final String existingHttp = StringUtils.trimToNull(System.getProperty("http.proxyHost"));
2366             if (mavenProxyHttp != null && existingHttp == null) {
2367                 proxySetFromMavenSettings = true;
2368                 setProxyServerSysPropsFromMavenProxy(mavenProxyHttp, PROTOCOL_HTTP);
2369                 httpNonProxyHosts = mavenProxyHttp.getNonProxyHosts();
2370             }
2371             if (proxySetFromMavenSettings) {
2372                 final String existingNonProxyHosts = System.getProperty("http.nonProxyHosts");
2373                 System.setProperty("http.nonProxyHosts", mergeNonProxyHosts(existingNonProxyHosts, httpNonProxyHosts, httpsNonProxyHosts));
2374             }
2375         } else if (this.proxy != null && this.proxy.getHost() != null) {
2376             // or use configured <proxy>
2377             settings.setString(Settings.KEYS.PROXY_SERVER, this.proxy.getHost());
2378             settings.setString(Settings.KEYS.PROXY_PORT, Integer.toString(this.proxy.getPort()));
2379             // user name and password from <server> entry settings.xml
2380             configureServerCredentials(this.proxy.getServerId(), Settings.KEYS.PROXY_USERNAME, Settings.KEYS.PROXY_PASSWORD);
2381         }
2382 
2383         final String[] suppressions = determineSuppressions();
2384         settings.setArrayIfNotEmpty(Settings.KEYS.SUPPRESSION_FILE, suppressions);
2385         settings.setBooleanIfNotNull(Settings.KEYS.UPDATE_VERSION_CHECK_ENABLED, versionCheckEnabled);
2386         settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
2387         settings.setStringIfNotEmpty(Settings.KEYS.CONNECTION_READ_TIMEOUT, readTimeout);
2388         settings.setStringIfNotEmpty(Settings.KEYS.HINTS_FILE, hintsFile);
2389         settings.setFloat(Settings.KEYS.JUNIT_FAIL_ON_CVSS, junitFailOnCVSS);
2390         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_JAR_ENABLED, jarAnalyzerEnabled);
2391         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, nuspecAnalyzerEnabled);
2392         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NUGETCONF_ENABLED, nugetconfAnalyzerEnabled);
2393         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_LIBMAN_ENABLED, libmanAnalyzerEnabled);
2394         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, centralAnalyzerEnabled);
2395         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CENTRAL_USE_CACHE, centralAnalyzerUseCache);
2396         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_ENABLED, artifactoryAnalyzerEnabled);
2397         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_ENABLED, nexusAnalyzerEnabled);
2398         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, assemblyAnalyzerEnabled);
2399         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_MSBUILD_PROJECT_ENABLED, msbuildAnalyzerEnabled);
2400         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, archiveAnalyzerEnabled);
2401         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_KNOWN_EXPLOITED_ENABLED, knownExploitedEnabled);
2402         settings.setStringIfNotEmpty(Settings.KEYS.KEV_URL, knownExploitedUrl);
2403         try {
2404             configureCredentials(knownExploitedServerId, knownExploitedUser, knownExploitedPassword, knownExploitedBearerToken,
2405                     Settings.KEYS.KEV_USER, Settings.KEYS.KEV_PASSWORD, Settings.KEYS.KEV_BEARER_TOKEN);
2406         } catch (InitializationException ex) {
2407             if (this.failOnError) {
2408                 throw new MojoFailureException("Invalid plugin configuration specified for Known Exploited data feed authentication", ex);
2409             } else {
2410                 throw new MojoExecutionException("Invalid plugin configuration specified for Known Exploited data feed authentication", ex);
2411             }
2412         }
2413         settings.setStringIfNotEmpty(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, zipExtensions);
2414         settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_ASSEMBLY_DOTNET_PATH, pathToCore);
2415         settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
2416         configureServerCredentials(nexusServerId, Settings.KEYS.ANALYZER_NEXUS_USER, Settings.KEYS.ANALYZER_NEXUS_PASSWORD);
2417         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NEXUS_USES_PROXY, nexusUsesProxy);
2418         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_URL, artifactoryAnalyzerUrl);
2419         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_USES_PROXY, artifactoryAnalyzerUseProxy);
2420         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_PARALLEL_ANALYSIS, artifactoryAnalyzerParallelAnalysis);
2421         settings.setBooleanIfNotNull(Settings.KEYS.FAIL_ON_UNUSED_SUPPRESSION_RULE, failBuildOnUnusedSuppressionRule);
2422         if (Boolean.TRUE.equals(artifactoryAnalyzerEnabled)) {
2423             if (artifactoryAnalyzerServerId != null) {
2424                 configureServerCredentials(artifactoryAnalyzerServerId, Settings.KEYS.ANALYZER_ARTIFACTORY_API_USERNAME,
2425                         Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN);
2426             } else {
2427                 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_API_USERNAME, artifactoryAnalyzerUsername);
2428                 settings.setStringIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_API_TOKEN, artifactoryAnalyzerApiToken);
2429             }
2430             settings.setStringIfNotNull(Settings.KEYS.ANALYZER_ARTIFACTORY_BEARER_TOKEN, artifactoryAnalyzerBearerToken);
2431         }
2432         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_DISTRIBUTION_ENABLED, pyDistributionAnalyzerEnabled);
2433         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PYTHON_PACKAGE_ENABLED, pyPackageAnalyzerEnabled);
2434         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RUBY_GEMSPEC_ENABLED, rubygemsAnalyzerEnabled);
2435         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OPENSSL_ENABLED, opensslAnalyzerEnabled);
2436         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CMAKE_ENABLED, cmakeAnalyzerEnabled);
2437         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_AUTOCONF_ENABLED, autoconfAnalyzerEnabled);
2438         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_MAVEN_INSTALL_ENABLED, mavenInstallAnalyzerEnabled);
2439         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIP_ENABLED, pipAnalyzerEnabled);
2440         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PIPFILE_ENABLED, pipfileAnalyzerEnabled);
2441         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_POETRY_ENABLED, poetryAnalyzerEnabled);
2442         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_ENABLED, composerAnalyzerEnabled);
2443         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COMPOSER_LOCK_SKIP_DEV, composerAnalyzerSkipDev);
2444         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CPANFILE_ENABLED, cpanfileAnalyzerEnabled);
2445         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_ENABLED, nodeAnalyzerEnabled);
2446         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_ENABLED, nodeAuditAnalyzerEnabled);
2447         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_URL, nodeAuditAnalyzerUrl);
2448         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_USE_CACHE, nodeAuditAnalyzerUseCache);
2449         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_PACKAGE_SKIPDEV, nodePackageSkipDevDependencies);
2450         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_NODE_AUDIT_SKIPDEV, nodeAuditSkipDevDependencies);
2451         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_YARN_AUDIT_ENABLED, yarnAuditAnalyzerEnabled);
2452         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_PNPM_AUDIT_ENABLED, pnpmAuditAnalyzerEnabled);
2453         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_ENABLED, retireJsAnalyzerEnabled);
2454         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_URL, retireJsUrl);
2455         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FORCEUPDATE, retireJsForceUpdate);
2456 
2457         try {
2458             configureCredentials(retireJsUrlServerId, retireJsUser, retireJsPassword, retireJsBearerToken,
2459                     Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_USER, Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_PASSWORD,
2460                     Settings.KEYS.ANALYZER_RETIREJS_REPO_JS_BEARER_TOKEN);
2461         } catch (InitializationException ex) {
2462             if (this.failOnError) {
2463                 throw new MojoFailureException("Invalid plugin configuration specified for retireJsUrl authentication", ex);
2464             } else {
2465                 throw new MojoExecutionException("Invalid plugin configuration specified for retireJsUrl authentication", ex);
2466             }
2467         }
2468         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_MIX_AUDIT_ENABLED, mixAuditAnalyzerEnabled);
2469         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_MIX_AUDIT_PATH, mixAuditPath);
2470         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_ENABLED, bundleAuditAnalyzerEnabled);
2471         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_PATH, bundleAuditPath);
2472         settings.setStringIfNotNull(Settings.KEYS.ANALYZER_BUNDLE_AUDIT_WORKING_DIRECTORY, bundleAuditWorkingDirectory);
2473         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_COCOAPODS_ENABLED, cocoapodsAnalyzerEnabled);
2474         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_CARTHAGE_ENABLED, carthageAnalyzerEnabled);
2475         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_MANAGER_ENABLED, swiftPackageManagerAnalyzerEnabled);
2476         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_SWIFT_PACKAGE_RESOLVED_ENABLED, swiftPackageResolvedAnalyzerEnabled);
2477         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_ENABLED, ossIndexAnalyzerEnabled);
2478         settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_URL, ossIndexAnalyzerUrl);
2479         if (StringUtils.isEmpty(ossIndexPassword)) {
2480             configureServerCredentialsUserPassOrApiKey(ossIndexServerId, Settings.KEYS.ANALYZER_OSSINDEX_USER, Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD);
2481         } else {
2482             settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_USER, ossIndexUsername);
2483             settings.setStringIfNotEmpty(Settings.KEYS.ANALYZER_OSSINDEX_PASSWORD, ossIndexPassword);
2484         }
2485         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_USE_CACHE, ossIndexAnalyzerUseCache);
2486         settings.setIntIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_CACHE_VALID_FOR_HOURS, ossIndexAnalyzerCacheValidForHours);
2487         settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_OSSINDEX_WARN_ONLY_ON_REMOTE_ERRORS, ossIndexWarnOnlyOnRemoteErrors);
2488         if (retirejs != null) {
2489             settings.setBooleanIfNotNull(Settings.KEYS.ANALYZER_RETIREJS_FILTER_NON_VULNERABLE, retirejs.getFilterNonVulnerable());
2490             settings.setArrayIfNotEmpty(Settings.KEYS.ANALYZER_RETIREJS_FILTERS, retirejs.getFilters());
2491         }
2492         //Database configuration
2493         settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
2494         settings.setStringIfNotEmpty(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
2495         settings.setStringIfNotEmpty(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
2496         if (databaseUser == null && databasePassword == null && serverId != null) {
2497             configureServerCredentials(serverId, Settings.KEYS.DB_USER, Settings.KEYS.DB_PASSWORD);
2498         } else {
2499             settings.setStringIfNotEmpty(Settings.KEYS.DB_USER, databaseUser);
2500             settings.setStringIfNotEmpty(Settings.KEYS.DB_PASSWORD, databasePassword);
2501         }
2502         settings.setStringIfNotEmpty(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
2503         settings.setStringIfNotEmpty(Settings.KEYS.DB_FILE_NAME, dbFilename);
2504         settings.setStringIfNotNull(Settings.KEYS.NVD_API_ENDPOINT, nvdApiEndpoint);
2505         settings.setIntIfNotNull(Settings.KEYS.NVD_API_DELAY, nvdApiDelay);
2506         settings.setIntIfNotNull(Settings.KEYS.NVD_API_RESULTS_PER_PAGE, nvdApiResultsPerPage);
2507         settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_DATAFEED_URL, nvdDatafeedUrl);
2508         settings.setIntIfNotNull(Settings.KEYS.NVD_API_VALID_FOR_HOURS, nvdValidForHours);
2509         settings.setIntIfNotNull(Settings.KEYS.NVD_API_MAX_RETRY_COUNT, nvdMaxRetryCount);
2510         if (nvdApiKey == null) {
2511             if (nvdApiKeyEnvironmentVariable != null) {
2512                 settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, System.getenv(nvdApiKeyEnvironmentVariable));
2513                 getLog().debug("Using NVD API key from environment variable " + nvdApiKeyEnvironmentVariable);
2514             } else if (nvdApiServerId != null) {
2515                 try {
2516                     configureServerCredentialsApiKey(nvdApiServerId, Settings.KEYS.NVD_API_KEY);
2517                 } catch (InitializationException ex) {
2518                     if (this.failOnError) {
2519                         throw new MojoFailureException("Invalid plugin configuration specified for NVD API authentication", ex);
2520                     } else {
2521                         throw new MojoExecutionException("Invalid plugin configuration specified for NVD API authentication", ex);
2522                     }
2523                 }
2524                 getLog().debug("Using NVD API key from server's password with id " + nvdApiServerId + " in settings.xml");
2525             }
2526         } else {
2527             settings.setStringIfNotEmpty(Settings.KEYS.NVD_API_KEY, nvdApiKey);
2528         }
2529         try {
2530             configureCredentials(nvdDatafeedServerId, nvdUser, nvdPassword, nvdBearerToken,
2531                     Settings.KEYS.NVD_API_DATAFEED_USER, Settings.KEYS.NVD_API_DATAFEED_PASSWORD, Settings.KEYS.NVD_API_DATAFEED_BEARER_TOKEN);
2532         } catch (InitializationException ex) {
2533             if (this.failOnError) {
2534                 throw new MojoFailureException("Invalid plugin configuration specified for NVD Datafeed authentication", ex);
2535             } else {
2536                 throw new MojoExecutionException("Invalid plugin configuration specified for NVD Datafeed authentication", ex);
2537             }
2538         }
2539         settings.setBooleanIfNotNull(Settings.KEYS.PRETTY_PRINT, prettyPrint);
2540         artifactScopeExcluded = new ArtifactScopeExcluded(skipTestScope, skipProvidedScope, skipSystemScope, skipRuntimeScope);
2541         artifactTypeExcluded = new ArtifactTypeExcluded(skipArtifactType);
2542         try {
2543             configureCredentials(suppressionFileServerId, suppressionFileUser, suppressionFilePassword, suppressionFileBearerToken,
2544                     Settings.KEYS.SUPPRESSION_FILE_USER, Settings.KEYS.SUPPRESSION_FILE_PASSWORD, Settings.KEYS.SUPPRESSION_FILE_BEARER_TOKEN);
2545         } catch (InitializationException ex) {
2546             if (this.failOnError) {
2547                 throw new MojoFailureException("Invalid plugin configuration specified for suppression file authentication", ex);
2548             } else {
2549                 throw new MojoExecutionException("Invalid plugin configuration specified for suppression file authentication", ex);
2550             }
2551         }
2552 
2553         settings.setIntIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_VALID_FOR_HOURS, hostedSuppressionsValidForHours);
2554         settings.setStringIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_URL, hostedSuppressionsUrl);
2555         settings.setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_FORCEUPDATE, hostedSuppressionsForceUpdate);
2556         settings.setBooleanIfNotNull(Settings.KEYS.HOSTED_SUPPRESSIONS_ENABLED, hostedSuppressionsEnabled);
2557         try {
2558             configureCredentials(hostedSuppressionsServerId, hostedSuppressionsUser, hostedSuppressionsPassword, hostedSuppressionsBearerToken,
2559                     Settings.KEYS.HOSTED_SUPPRESSIONS_USER, Settings.KEYS.HOSTED_SUPPRESSIONS_PASSWORD, Settings.KEYS.HOSTED_SUPPRESSIONS_BEARER_TOKEN);
2560         } catch (InitializationException ex) {
2561             if (this.failOnError) {
2562                 throw new MojoFailureException("Invalid plugin configuration specified for hostedSuppressions authentication", ex);
2563             } else {
2564                 throw new MojoExecutionException("Invalid plugin configuration specified for hostedSuppressions authentication", ex);
2565             }
2566         }
2567     }
2568     //CSON: MethodLength
2569 
2570     /**
2571      * Configure the credentials in the settings for a certain connection.<br/>
2572      * <p>
2573      * When a serverId is given, then its values are used instead of the less secure direct values.<br />
2574      * A serverId with username/password will fill the `userKey` and `passwordKey` settings for Basic Auth. A serverId with only password
2575      * filled will fill the `tokenKey` from Bearer Auth.<br/>
2576      * In absence of the serverId, any non-null value will be transferred to the settings.
2577      *
2578      * @param serverId The serverId specified for the connection or {@code null}
2579      * @param usernameValue The username specified for the connection or {@code null}
2580      * @param passwordValue The password specified for the connection or {@code null}
2581      * @param tokenValue The token specified for the connection or {@code null}
2582      * @param userKey The settings key that configures the user or {@code null} when Basic auth is not configurable for the connection
2583      * @param passwordKey The settings key that configures the password or {@code null} when Basic auth is not configurable for the connection
2584      * @param tokenKey The settings key that configures the token or {@code null} when Bearer auth is not configurable for the connection
2585      * @throws InitializationException When both serverId and at least one other property value are filled.
2586      */
2587     private void configureCredentials(String serverId, String usernameValue, String passwordValue, String tokenValue,
2588                                       String userKey, String passwordKey, String tokenKey) throws InitializationException {
2589         if (serverId != null) {
2590             if (usernameValue != null || passwordValue != null || tokenValue != null) {
2591                 throw new InitializationException(
2592                         "Username/password/token configurations should be left out when a serverId (" + serverId + ") is configured");
2593             }
2594             final Server server = settingsXml.getServer(serverId);
2595             if (server != null) {
2596                 configureFromServer(server, userKey, passwordKey, tokenKey, serverId);
2597             } else {
2598                 getLog().error(String.format("Server '%s' not found in the settings.xml file", serverId));
2599             }
2600         } else {
2601             settings.setStringIfNotEmpty(userKey, usernameValue);
2602             settings.setStringIfNotEmpty(passwordKey, passwordValue);
2603             settings.setStringIfNotEmpty(tokenKey, tokenValue);
2604         }
2605     }
2606 
2607     /**
2608      * Configure the credentials in the settings for a certain connection from a settings Server object.<br/>
2609      * <p>
2610      * A serverId with username/password will fill the `userKey` and `passwordKey` settings for Basic Auth.<br/>
2611      * A serverId with only password filled will fill the `tokenKey` fro Bearer Auth.<br/>
2612      *
2613      * @param server The server entry from the settings to configure authentication
2614      * @param userKey The settings key that configures the user or {@code null} when Basic auth is not configurable for the connection
2615      * @param passwordKey The settings key that configures the password or {@code null} when Basic auth is not configurable for the connection
2616      * @param tokenKey The settings key that configures the token or {@code null} when Bearer auth is not configurable for the connection
2617      * @param serverId The serverId specified for the connection or {@code null}
2618      * @throws InitializationException When both serverId and at least one other property value are filled.
2619      */
2620     private void configureFromServer(Server server, String userKey, String passwordKey, String tokenKey, String serverId) throws InitializationException {
2621         final SettingsDecryptionResult result = settingsDecrypter.decrypt(new DefaultSettingsDecryptionRequest(server));
2622         final String username = server.getUsername();
2623         final String password;
2624         if (result.getProblems().isEmpty()) {
2625             password = result.getServer().getPassword();
2626         } else {
2627             logProblems(result.getProblems(), "server setting for " + serverId);
2628             getLog().debug("Using raw password from settings.xml for server " + serverId);
2629             password = server.getPassword();
2630         }
2631         if (username != null) {
2632             if (userKey != null && passwordKey != null) {
2633                 settings.setStringIfNotEmpty(userKey, username);
2634                 settings.setStringIfNotEmpty(passwordKey, password);
2635             } else {
2636                 getLog().warn("Basic type server authentication encountered in serverId " + serverId + ", but only Bearer authentication is "
2637                         + "supported for the resource. For Bearer authentication tokens you should leave out the username in the server-entry in"
2638                         + " settings.xml");
2639                 settings.setStringIfNotEmpty(tokenKey, password);
2640             }
2641         } else {
2642             if (tokenKey != null) {
2643                 settings.setStringIfNotEmpty(tokenKey, password);
2644             } else {
2645                 throw new InitializationException(
2646                         "Bearer type server authentication encountered in serverId " + serverId + ", but only Basic authentication is supported for "
2647                                 + "the  resource. Looks like the username was forgotten to be added in the server-entry in settings.xml");
2648             }
2649         }
2650     }
2651 
2652     private String mergeNonProxyHosts(String existingNonProxyHosts, String httpNonProxyHosts, String httpsNonProxyHosts) {
2653         final HashSet<String> mergedNonProxyHosts = new HashSet<>();
2654         mergedNonProxyHosts.addAll(Arrays.asList(StringUtils.trimToEmpty(existingNonProxyHosts).split("\\|")));
2655         mergedNonProxyHosts.addAll(Arrays.asList(StringUtils.trimToEmpty(httpNonProxyHosts).split("\\|")));
2656         mergedNonProxyHosts.addAll(Arrays.asList(StringUtils.trimToEmpty(httpsNonProxyHosts).split("\\|")));
2657         return String.join("|", mergedNonProxyHosts);
2658     }
2659 
2660     private void setProxyServerSysPropsFromMavenProxy(Proxy mavenProxy, String protocol) {
2661         System.setProperty(protocol + ".proxyHost", mavenProxy.getHost());
2662         if (mavenProxy.getPort() > 0) {
2663             System.setProperty(protocol + ".proxyPort", String.valueOf(mavenProxy.getPort()));
2664         }
2665         if (mavenProxy.getUsername() != null && !mavenProxy.getUsername().isEmpty()) {
2666             System.setProperty(protocol + ".proxyUser", mavenProxy.getUsername());
2667         }
2668         final SettingsDecryptionResult result = settingsDecrypter.decrypt(new DefaultSettingsDecryptionRequest(mavenProxy));
2669         final String password;
2670         if (result.getProblems().isEmpty()) {
2671             password = result.getProxy().getPassword();
2672         } else {
2673             logProblems(result.getProblems(), "proxy settings for " + mavenProxy.getId());
2674             getLog().debug("Using raw password from settings.xml for proxy " + mavenProxy.getId());
2675             password = mavenProxy.getPassword();
2676         }
2677         if (password != null && !password.isEmpty()) {
2678             System.setProperty(protocol + ".proxyPassword", password);
2679         }
2680     }
2681 
2682     /**
2683      * Retrieves the server credentials from the settings.xml, decrypts the
2684      * password, and places the values into the settings under the given key
2685      * names.
2686      *
2687      * @param serverId the server id
2688      * @param userSettingKey the property name for the username
2689      * @param passwordSettingKey the property name for the password
2690      */
2691     private void configureServerCredentials(String serverId, String userSettingKey, String passwordSettingKey) throws MojoFailureException, MojoExecutionException {
2692         try {
2693             configureCredentials(serverId, null, null, null, userSettingKey, passwordSettingKey, null);
2694         } catch (InitializationException ex) {
2695             if (this.failOnError) {
2696                 throw new MojoFailureException(String.format("Error setting credentials (%s, %s) from serverId %s", userSettingKey, passwordSettingKey, serverId), ex);
2697             } else {
2698                 throw new MojoExecutionException(String.format("Error setting credentials (%s, %s) from serverId %s", userSettingKey, passwordSettingKey, serverId), ex);
2699             }
2700         }
2701     }
2702 
2703     /**
2704      * Retrieves the server credentials from the settings.xml, decrypts the
2705      * password, and places the values into the settings under the given key
2706      * names with fallback to API key style if the username is not set.
2707      *
2708      * @param serverId the server id
2709      * @param userSettingKey the property name for the username (setting this value must be optional)
2710      * @param passwordOrApiKeySetting the property name for the password or API key
2711      */
2712     @SuppressWarnings("SameParameterValue")
2713     private void configureServerCredentialsUserPassOrApiKey(String serverId, String userSettingKey, String passwordOrApiKeySetting) throws MojoFailureException, MojoExecutionException {
2714         try {
2715             configureCredentials(serverId, null, null, null, userSettingKey, passwordOrApiKeySetting, passwordOrApiKeySetting);
2716         } catch (InitializationException ex) {
2717             if (this.failOnError) {
2718                 throw new MojoFailureException(String.format("Error setting credentials (%s, %s) from serverId %s", userSettingKey, passwordOrApiKeySetting, serverId), ex);
2719             } else {
2720                 throw new MojoExecutionException(String.format("Error setting credentials (%s, %s) from serverId %s", userSettingKey, passwordOrApiKeySetting, serverId), ex);
2721             }
2722         }
2723     }
2724 
2725 
2726     /**
2727      * Retrieves the server credentials from the settings.xml, decrypts the
2728      * password, and places the values into the settings under the given key
2729      * names. This is used to retrieve an encrypted password as an API key.
2730      *
2731      * @param serverId the server id
2732      * @param apiKeySetting the property name for the API key
2733      */
2734     private void configureServerCredentialsApiKey(String serverId, String apiKeySetting) throws InitializationException {
2735         configureCredentials(serverId, null, null, null, null, null, apiKeySetting);
2736     }
2737 
2738     /**
2739      * Logs the problems encountered during settings decryption of a {@code <server>} or {@code <proxy>} config
2740      * from the maven settings.<br/>
2741      * Logs a generic message about decryption problems at WARN level. If debug logging is enabled a additional message is logged at DEBUG level
2742      * detailing all the encountered problems and their underlying exceptions.
2743      *
2744      * @param problems The problems as reported by the settingsDecrypter.
2745      * @param credentialDesc an identification of what was attempted to be decrypted
2746      */
2747     private void logProblems(List<SettingsProblem> problems, String credentialDesc) {
2748         final String message = "Problems while decrypting " + credentialDesc;
2749         getLog().warn(message);
2750         if (getLog().isDebugEnabled()) {
2751             final StringBuilder dbgMessage = new StringBuilder("Problems while decrypting ").append(credentialDesc).append(": ");
2752             boolean first = true;
2753             for (SettingsProblem problem : problems) {
2754                 dbgMessage.append(first ? "" : ", ").append(problem.getMessage());
2755                 dbgMessage.append("caused by ").append(problem.getException());
2756                 first = false;
2757             }
2758             getLog().debug(dbgMessage.toString());
2759         }
2760     }
2761 
2762     /**
2763      * Combines the configured suppressionFile and suppressionFiles into a
2764      * single array.
2765      *
2766      * @return an array of suppression file paths
2767      */
2768     private String[] determineSuppressions() {
2769         String[] suppressions = suppressionFiles;
2770         if (suppressionFile != null) {
2771             if (suppressions == null) {
2772                 suppressions = new String[]{suppressionFile};
2773             } else {
2774                 suppressions = Arrays.copyOf(suppressions, suppressions.length + 1);
2775                 suppressions[suppressions.length - 1] = suppressionFile;
2776             }
2777         }
2778         return suppressions;
2779     }
2780 
2781     /**
2782      * Hacky method of muting the noisy logging from certain libraries.
2783      */
2784     void muteNoisyLoggers() {
2785         // Mirrors the configuration within cli/src/main/resources/logback.xml
2786         final List<String> noisyLoggers = List.of(
2787                 "org.apache.lucene",
2788                 "org.apache.commons.jcs3",
2789                 "org.apache.hc"
2790         );
2791         for (String loggerName : noisyLoggers) {
2792             System.setProperty("org.slf4j.simpleLogger.log." + loggerName, "error");
2793         }
2794     }
2795 
2796     /**
2797      * Returns the maven proxy.
2798      *
2799      * @param protocol The protocol of the target URL.
2800      * @return the maven proxy configured for that protocol
2801      */
2802     private Proxy getMavenProxy(String protocol) {
2803         if (mavenSettings != null) {
2804             final List<Proxy> proxies = mavenSettings.getProxies();
2805             if (proxies != null && !proxies.isEmpty()) {
2806                 if (mavenSettingsProxyId != null) {
2807                     for (Proxy proxy : proxies) {
2808                         if (mavenSettingsProxyId.equalsIgnoreCase(proxy.getId())) {
2809                             return proxy;
2810                         }
2811                     }
2812                 } else {
2813                     for (Proxy aProxy : proxies) {
2814                         if (aProxy.isActive() && aProxy.getProtocol().equals(protocol)) {
2815                             return aProxy;
2816                         }
2817                     }
2818                 }
2819             }
2820         }
2821         return null;
2822     }
2823 
2824     /**
2825      * Returns a reference to the current project. This method is used instead
2826      * of auto-binding the project via component annotation in concrete
2827      * implementations of this. If the child has a
2828      * <code>@Component MavenProject project;</code> defined then the abstract
2829      * class (i.e. this class) will not have access to the current project (just
2830      * the way Maven works with the binding).
2831      *
2832      * @return returns a reference to the current project
2833      */
2834     protected MavenProject getProject() {
2835         return project;
2836     }
2837 
2838     /**
2839      * Returns the list of Maven Projects in this build.
2840      *
2841      * @return the list of Maven Projects in this build
2842      */
2843     protected List<MavenProject> getReactorProjects() {
2844         return reactorProjects;
2845     }
2846 
2847     /**
2848      * Combines the format and formats properties into a single collection.
2849      *
2850      * @return the selected report formats
2851      */
2852     private Set<String> getFormats() {
2853         final Set<String> invalid = new HashSet<>();
2854         final Set<String> selectedFormats = formats == null || formats.length == 0 ? new HashSet<>() : new HashSet<>(Arrays.asList(formats));
2855         selectedFormats.forEach((s) -> {
2856             try {
2857                 ReportGenerator.Format.valueOf(s.toUpperCase());
2858             } catch (IllegalArgumentException ex) {
2859                 invalid.add(s);
2860             }
2861         });
2862         invalid.forEach((s) -> getLog().warn("Invalid report format specified: " + s));
2863         if (selectedFormats.contains("true")) {
2864             selectedFormats.remove("true");
2865         }
2866         if (format != null && selectedFormats.isEmpty()) {
2867             selectedFormats.add(format);
2868         }
2869         return selectedFormats;
2870     }
2871 
2872     /**
2873      * Returns the list of excluded artifacts based on either artifact id or
2874      * group id and artifact id.
2875      *
2876      * @return a list of artifact to exclude
2877      */
2878     public List<String> getExcludes() {
2879         if (excludes == null) {
2880             excludes = new ArrayList<>();
2881         }
2882         return excludes;
2883     }
2884 
2885     /**
2886      * Returns the artifact scope excluded filter.
2887      *
2888      * @return the artifact scope excluded filter
2889      */
2890     protected Filter<String> getArtifactScopeExcluded() {
2891         return artifactScopeExcluded;
2892     }
2893 
2894     /**
2895      * Returns the configured settings.
2896      *
2897      * @return the configured settings
2898      */
2899     protected Settings getSettings() {
2900         return settings;
2901     }
2902 
2903     //<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
2904 
2905     /**
2906      * Checks to see if a vulnerability has been identified with a CVSS score
2907      * that is above the threshold set in the configuration.
2908      *
2909      * @param dependencies the list of dependency objects
2910      * @throws MojoFailureException thrown if a CVSS score is found that is
2911      * higher than the threshold set
2912      */
2913     protected void checkForFailure(Dependency[] dependencies) throws MojoFailureException {
2914         final StringBuilder ids = new StringBuilder();
2915         for (Dependency d : dependencies) {
2916             boolean addName = true;
2917             for (Vulnerability v : d.getVulnerabilities()) {
2918                 final double cvssV2 = v.getCvssV2() != null && v.getCvssV2().getCvssData() != null && v.getCvssV2().getCvssData().getBaseScore() != null ? v.getCvssV2().getCvssData().getBaseScore() : -1;
2919                 final double cvssV3 = v.getCvssV3() != null && v.getCvssV3().getCvssData() != null && v.getCvssV3().getCvssData().getBaseScore() != null ? v.getCvssV3().getCvssData().getBaseScore() : -1;
2920                 final double cvssV4 = v.getCvssV4() != null && v.getCvssV4().getCvssData() != null && v.getCvssV4().getCvssData().getBaseScore() != null ? v.getCvssV4().getCvssData().getBaseScore() : -1;
2921                 final boolean useUnscored = cvssV2 == -1 && cvssV3 == -1 && cvssV4 == -1;
2922                 final double unscoredCvss = (useUnscored && v.getUnscoredSeverity() != null) ? SeverityUtil.estimateCvssV2(v.getUnscoredSeverity()) : -1;
2923 
2924                 if (failBuildOnAnyVulnerability
2925                         || cvssV2 >= failBuildOnCVSS
2926                         || cvssV3 >= failBuildOnCVSS
2927                         || cvssV4 >= failBuildOnCVSS
2928                         || unscoredCvss >= failBuildOnCVSS
2929                         //safety net to fail on any if for some reason the above misses on 0
2930                         || failBuildOnCVSS <= 0.0
2931                 ) {
2932                     String name = v.getName();
2933                     if (cvssV4 >= 0.0) {
2934                         name += "(" + cvssV4 + ")";
2935                     } else if (cvssV3 >= 0.0) {
2936                         name += "(" + cvssV3 + ")";
2937                     } else if (cvssV2 >= 0.0) {
2938                         name += "(" + cvssV2 + ")";
2939                     } else if (unscoredCvss >= 0.0) {
2940                         name += "(" + unscoredCvss + ")";
2941                     }
2942                     if (addName) {
2943                         addName = false;
2944                         ids.append(NEW_LINE).append(d.getFileName()).append(" (")
2945                                 .append(Stream.concat(d.getSoftwareIdentifiers().stream(), d.getVulnerableSoftwareIdentifiers().stream())
2946                                         .map(Identifier::getValue)
2947                                         .collect(Collectors.joining(", ")))
2948                                 .append("): ")
2949                                 .append(name);
2950                     } else {
2951                         ids.append(", ").append(name);
2952                     }
2953                 }
2954             }
2955         }
2956         if (ids.length() > 0) {
2957             final String msg;
2958             if (showSummary) {
2959                 if (failBuildOnAnyVulnerability) {
2960                     msg = String.format("%n%nOne or more dependencies were identified with vulnerabilities: %n%s%n%n"
2961                             + "See the dependency-check report for more details.%n%n", ids);
2962                 } else {
2963                     msg = String.format("%n%nOne or more dependencies were identified with vulnerabilities that have a CVSS score greater than or "
2964                             + "equal to '%.1f': %n%s%n%nSee the dependency-check report for more details.%n%n", failBuildOnCVSS, ids);
2965                 }
2966             } else {
2967                 msg = String.format("%n%nOne or more dependencies were identified with vulnerabilities.%n%n"
2968                         + "See the dependency-check report for more details.%n%n");
2969             }
2970             throw new MojoFailureException(msg);
2971         }
2972     }
2973 
2974     /**
2975      * Generates a warning message listing a summary of dependencies and their
2976      * associated CPE and CVE entries.
2977      *
2978      * @param mp the Maven project for which the summary is shown
2979      * @param dependencies a list of dependency objects
2980      */
2981     protected void showSummary(MavenProject mp, Dependency[] dependencies) {
2982         if (showSummary) {
2983             DependencyCheckScanAgent.showSummary(mp.getName(), dependencies);
2984         }
2985     }
2986 
2987     //</editor-fold>
2988     //CSOFF: ParameterNumber
2989     private ExceptionCollection scanDependencyNode(DependencyNode dependencyNode, DependencyNode root,
2990                                                    Engine engine, MavenProject project, List<ArtifactResult> allResolvedDeps,
2991                                                    ProjectBuildingRequest buildingRequest, boolean aggregate, ExceptionCollection exceptionCollection) {
2992         ExceptionCollection exCol = exceptionCollection;
2993         if (artifactScopeExcluded.passes(dependencyNode.getArtifact().getScope())
2994                 || artifactTypeExcluded.passes(dependencyNode.getArtifact().getType())) {
2995             return exCol;
2996         }
2997 
2998         boolean isResolved = false;
2999         File artifactFile = null;
3000         String artifactId = null;
3001         String groupId = null;
3002         String version = null;
3003         List<ArtifactVersion> availableVersions = null;
3004         if (org.apache.maven.artifact.Artifact.SCOPE_SYSTEM.equals(dependencyNode.getArtifact().getScope())) {
3005             final Artifact a = dependencyNode.getArtifact();
3006             if (a.isResolved() && a.getFile().isFile()) {
3007                 artifactFile = a.getFile();
3008                 isResolved = artifactFile.isFile();
3009                 groupId = a.getGroupId();
3010                 artifactId = a.getArtifactId();
3011                 version = a.getVersion();
3012                 availableVersions = a.getAvailableVersions();
3013             } else {
3014                 for (org.apache.maven.model.Dependency d : project.getDependencies()) {
3015                     if (d.getSystemPath() != null && artifactsMatch(d, a)) {
3016                         artifactFile = new File(d.getSystemPath());
3017                         isResolved = artifactFile.isFile();
3018                         groupId = a.getGroupId();
3019                         artifactId = a.getArtifactId();
3020                         version = a.getVersion();
3021                         availableVersions = a.getAvailableVersions();
3022                         break;
3023                     }
3024                 }
3025             }
3026             Throwable ignored = null;
3027             if (!isResolved) {
3028                 // Issue #4969 Tycho appears to add System-scoped libraries in reactor projects in unresolved state
3029                 // so attempt to do a resolution for system-scoped too if still nothing found
3030                 try {
3031                     tryResolutionOnce(project, allResolvedDeps, buildingRequest);
3032                     final Artifact result = findInAllDeps(allResolvedDeps, dependencyNode.getArtifact(), project);
3033                     isResolved = result.isResolved();
3034                     artifactFile = result.getFile();
3035                     groupId = result.getGroupId();
3036                     artifactId = result.getArtifactId();
3037                     version = result.getVersion();
3038                     availableVersions = result.getAvailableVersions();
3039                 } catch (DependencyNotFoundException | DependencyResolverException e) {
3040                     getLog().warn("Error performing last-resort System-scoped dependency resolution: " + e.getMessage());
3041                     ignored = e;
3042                 }
3043             }
3044             if (!isResolved) {
3045                 final StringBuilder message = new StringBuilder("Unable to resolve system scoped dependency: ");
3046                 if (artifactFile != null) {
3047                     message.append(dependencyNode.toNodeString()).append(" at path ").append(artifactFile);
3048                 } else {
3049                     message.append(dependencyNode.toNodeString()).append(" at path ").append(a.getFile());
3050                 }
3051                 getLog().error(message);
3052                 if (exCol == null) {
3053                     exCol = new ExceptionCollection();
3054                 }
3055                 final Exception thrown = new DependencyNotFoundException(message.toString());
3056                 if (ignored != null) {
3057                     thrown.addSuppressed(ignored);
3058                 }
3059                 exCol.addException(thrown);
3060             }
3061         } else {
3062             final Artifact dependencyArtifact = dependencyNode.getArtifact();
3063             final Artifact result;
3064             if (dependencyArtifact.isResolved()) {
3065                 //All transitive dependencies, excluding reactor and dependencyManagement artifacts should
3066                 //have been resolved by Maven prior to invoking the plugin - resolving the dependencies
3067                 //manually is unnecessary, and does not work in some cases (issue-1751)
3068                 getLog().debug(String.format("Skipping artifact %s, already resolved", dependencyArtifact.getArtifactId()));
3069                 result = dependencyArtifact;
3070             } else {
3071                 try {
3072                     tryResolutionOnce(project, allResolvedDeps, buildingRequest);
3073                     result = findInAllDeps(allResolvedDeps, dependencyNode.getArtifact(), project);
3074                 } catch (DependencyNotFoundException | DependencyResolverException ex) {
3075                     getLog().debug(String.format("Aggregate : %s", aggregate));
3076                     boolean addException = true;
3077                     //CSOFF: EmptyBlock
3078                     if (!aggregate) {
3079                         // do nothing - the exception is to be reported
3080                     } else if (addReactorDependency(engine, dependencyNode.getArtifact(), project)) {
3081                         // successfully resolved as a reactor dependency - swallow the exception
3082                         addException = false;
3083                     }
3084                     if (addException) {
3085                         if (exCol == null) {
3086                             exCol = new ExceptionCollection();
3087                         }
3088                         exCol.addException(ex);
3089                     }
3090                     return exCol;
3091                 }
3092             }
3093             if (aggregate && virtualSnapshotsFromReactor
3094                     && dependencyNode.getArtifact().isSnapshot()
3095                     && addSnapshotReactorDependency(engine, dependencyNode.getArtifact(), project)) {
3096                 return exCol;
3097             }
3098             isResolved = result.isResolved();
3099             artifactFile = result.getFile();
3100             groupId = result.getGroupId();
3101             artifactId = result.getArtifactId();
3102             version = result.getVersion();
3103             availableVersions = result.getAvailableVersions();
3104         }
3105         if (isResolved && artifactFile != null) {
3106             final List<Dependency> deps = engine.scan(artifactFile.getAbsoluteFile(),
3107                     createProjectReferenceName(project, dependencyNode));
3108             if (deps != null) {
3109                 processResolvedArtifact(artifactFile, deps, groupId, artifactId, version, root, project, availableVersions, dependencyNode);
3110             } else if ("import".equals(dependencyNode.getArtifact().getScope())) {
3111                 final String msg = String.format("Skipping '%s:%s' in project %s as it uses an `import` scope",
3112                         dependencyNode.getArtifact().getId(), dependencyNode.getArtifact().getScope(), project.getName());
3113                 getLog().debug(msg);
3114             } else if ("pom".equals(dependencyNode.getArtifact().getType())) {
3115                 exCol = processPomArtifact(artifactFile, root, project, engine, exCol);
3116             } else {
3117                 if (!scannedFiles.contains(artifactFile)) {
3118                     final String msg = String.format("No analyzer could be found or the artifact has been scanned twice for '%s:%s' in project %s",
3119                             dependencyNode.getArtifact().getId(), dependencyNode.getArtifact().getScope(), project.getName());
3120                     getLog().warn(msg);
3121                 }
3122             }
3123         } else {
3124             final String msg = String.format("Unable to resolve '%s' in project %s",
3125                     dependencyNode.getArtifact().getId(), project.getName());
3126             getLog().debug(msg);
3127             if (exCol == null) {
3128                 exCol = new ExceptionCollection();
3129             }
3130         }
3131         return exCol;
3132     }
3133 
3134     /**
3135      * Try resolution of artifacts once, allowing for
3136      * DependencyResolutionException due to reactor-dependencies not being
3137      * resolvable.
3138      * <br>
3139      * The resolution is attempted only if allResolvedDeps is still empty. The
3140      * assumption is that for any given project at least one of the dependencies
3141      * will successfully resolve. If not, resolution will be attempted once for
3142      * every dependency (as allResolvedDeps remains empty).
3143      *
3144      * @param project The project to dependencies for
3145      * @param allResolvedDeps The collection of successfully resolved
3146      * dependencies, will be filled with the successfully resolved dependencies,
3147      * even in case of resolution failures.
3148      * @param buildingRequest The buildingRequest to hand to Maven's
3149      * DependencyResolver.
3150      * @throws DependencyResolverException For any DependencyResolverException
3151      * other than an Eclipse Aether DependencyResolutionException
3152      */
3153     private void tryResolutionOnce(MavenProject project, List<ArtifactResult> allResolvedDeps, ProjectBuildingRequest buildingRequest) throws DependencyResolverException {
3154         if (allResolvedDeps.isEmpty()) { // no (partially successful) resolution attempt done
3155             try {
3156                 final List<org.apache.maven.model.Dependency> dependencies = project.getDependencies();
3157                 final List<org.apache.maven.model.Dependency> managedDependencies = project
3158                         .getDependencyManagement() == null ? null : project.getDependencyManagement().getDependencies();
3159                 final Iterable<ArtifactResult> allDeps = dependencyResolver
3160                         .resolveDependencies(buildingRequest, dependencies, managedDependencies, null);
3161                 allDeps.forEach(allResolvedDeps::add);
3162             } catch (DependencyResolverException dre) {
3163                 if (dre.getCause() instanceof org.eclipse.aether.resolution.DependencyResolutionException) {
3164                     final List<ArtifactResult> successResults = Mshared998Util
3165                             .getResolutionResults((org.eclipse.aether.resolution.DependencyResolutionException) dre.getCause());
3166                     allResolvedDeps.addAll(successResults);
3167                 } else {
3168                     throw dre;
3169                 }
3170             }
3171         }
3172     }
3173     //CSON: ParameterNumber
3174 
3175     //CSOFF: ParameterNumber
3176     private void processResolvedArtifact(File artifactFile, final List<Dependency> deps,
3177                                          String groupId, String artifactId, String version, DependencyNode root,
3178                                          MavenProject project1, List<ArtifactVersion> availableVersions,
3179                                          DependencyNode dependencyNode) {
3180         scannedFiles.add(artifactFile);
3181         Dependency d = null;
3182         if (deps.size() == 1) {
3183             d = deps.get(0);
3184 
3185         } else {
3186             for (Dependency possible : deps) {
3187                 if (artifactFile.getAbsoluteFile().equals(possible.getActualFile())) {
3188                     d = possible;
3189                     break;
3190                 }
3191             }
3192             for (Dependency dep : deps) {
3193                 if (d != null && d != dep) {
3194                     final String includedBy = buildReference(groupId, artifactId, version);
3195                     dep.addIncludedBy(includedBy);
3196                 }
3197             }
3198         }
3199         if (d != null) {
3200             final MavenArtifact ma = new MavenArtifact(groupId, artifactId, version);
3201             d.addAsEvidence("pom", ma, Confidence.HIGHEST);
3202             if (root != null) {
3203                 final String includedby = buildReference(
3204                         root.getArtifact().getGroupId(),
3205                         root.getArtifact().getArtifactId(),
3206                         root.getArtifact().getVersion());
3207                 d.addIncludedBy(includedby);
3208             } else {
3209                 final String includedby = buildReference(project1.getGroupId(), project1.getArtifactId(), project1.getVersion());
3210                 d.addIncludedBy(includedby);
3211             }
3212             if (availableVersions != null) {
3213                 for (ArtifactVersion av : availableVersions) {
3214                     d.addAvailableVersion(av.toString());
3215                 }
3216             }
3217             getLog().debug(String.format("Adding project reference %s on dependency %s", project1.getName(), d.getDisplayFileName()));
3218         } else if (getLog().isDebugEnabled()) {
3219             final String msg = String.format("More than 1 dependency was identified in first pass scan of '%s' in project %s", dependencyNode.getArtifact().getId(), project1.getName());
3220             getLog().debug(msg);
3221         }
3222     }
3223     //CSON: ParameterNumber
3224 
3225     private ExceptionCollection processPomArtifact(File artifactFile, DependencyNode root,
3226                                                    MavenProject project1, Engine engine, ExceptionCollection exCollection) {
3227         ExceptionCollection exCol = exCollection;
3228         try {
3229             final Dependency d = new Dependency(artifactFile.getAbsoluteFile());
3230             final Model pom = PomUtils.readPom(artifactFile.getAbsoluteFile());
3231             JarAnalyzer.setPomEvidence(d, pom, null, true);
3232             if (root != null) {
3233                 final String includedby = buildReference(
3234                         root.getArtifact().getGroupId(),
3235                         root.getArtifact().getArtifactId(),
3236                         root.getArtifact().getVersion());
3237                 d.addIncludedBy(includedby);
3238             } else {
3239                 final String includedby = buildReference(project1.getGroupId(), project1.getArtifactId(), project1.getVersion());
3240                 d.addIncludedBy(includedby);
3241             }
3242             engine.addDependency(d);
3243         } catch (AnalysisException ex) {
3244             if (exCol == null) {
3245                 exCol = new ExceptionCollection();
3246             }
3247             exCol.addException(ex);
3248             getLog().debug("Error reading pom " + artifactFile.getAbsoluteFile(), ex);
3249         }
3250         return exCol;
3251     }
3252 
3253 
3254     private void checkForDeprecatedParameters() {
3255         warnIfDeprecatedParamUsed("ossIndexAnalyzerEnabled", "ossindexAnalyzerEnabled");
3256         warnIfDeprecatedParamUsed("ossIndexAnalyzerUseCache", "ossindexAnalyzerUseCache");
3257         warnIfDeprecatedParamUsed("ossIndexAnalyzerUrl", "ossindexAnalyzerUrl");
3258     }
3259 
3260     /**
3261      * Checks if the deprecated (aka aliased) parameter is used in the plugin configuration and logs a warning if so.
3262      *
3263      * @param currentName the name of the current parameter (the one that should be used)
3264      * @param deprecatedName the name of the deprecated parameter (the one that should not be used anymore)
3265      */
3266     private void warnIfDeprecatedParamUsed(String currentName, String deprecatedName) {
3267         final org.apache.maven.model.Plugin plugin = project.getBuild().getPluginsAsMap()
3268                 .get(mojoExecution.getGroupId() + ":" + mojoExecution.getArtifactId());
3269         if (plugin == null) {
3270             return;
3271         }
3272         final Object cfg = plugin.getConfiguration();
3273         if (cfg instanceof org.codehaus.plexus.util.xml.Xpp3Dom) {
3274             final org.codehaus.plexus.util.xml.Xpp3Dom dom = (org.codehaus.plexus.util.xml.Xpp3Dom) cfg;
3275             if (dom.getChild(deprecatedName) != null) {
3276                 getLog().warn(String.format(
3277                         "The parameter '%s' is deprecated and should not be used anymore. Please use '%s' instead.",
3278                         deprecatedName, currentName));
3279             }
3280         }
3281     }
3282 }
3283 //CSON: FileLength