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