1 /*
2 * This file is part of dependency-check-core.
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) 2016 Stefan Neuhaus. All Rights Reserved.
17 */
18 package org.owasp.dependencycheck;
19
20 import org.owasp.dependencycheck.analyzer.Analyzer;
21 import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
22 import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
23 import org.owasp.dependencycheck.dependency.Dependency;
24 import org.owasp.dependencycheck.utils.Settings;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.util.List;
29 import java.util.concurrent.Callable;
30
31 /**
32 * Task to support parallelism of dependency-check analysis. Analyses a single
33 * {@link Dependency} by a specific {@link Analyzer}.
34 *
35 * @author Stefan Neuhaus
36 */
37 class AnalysisTask implements Callable<Void> {
38
39 /**
40 * Instance of the logger.
41 */
42 private static final Logger LOGGER = LoggerFactory.getLogger(AnalysisTask.class);
43
44 /**
45 * A reference to the analyzer.
46 */
47 private final Analyzer analyzer;
48 /**
49 * The dependency to analyze.
50 */
51 private final Dependency dependency;
52 /**
53 * A reference to the dependency-check engine.
54 */
55 private final Engine engine;
56 /**
57 * The list of exceptions that may occur during analysis.
58 */
59 private final List<Throwable> exceptions;
60 /**
61 * A reference to the global settings object.
62 */
63 private final Settings settings;
64
65 /**
66 * Creates a new analysis task.
67 *
68 * @param analyzer a reference of the analyzer to execute
69 * @param dependency the dependency to analyze
70 * @param engine the dependency-check engine
71 * @param exceptions exceptions that occur during analysis will be added to
72 * this collection of exceptions
73 * @param settings a reference to the global settings object; this is
74 * necessary so that when the thread is started the dependencies have a
75 * correct reference to the global settings.
76 */
77 AnalysisTask(Analyzer analyzer, Dependency dependency, Engine engine, List<Throwable> exceptions, Settings settings) {
78 this.analyzer = analyzer;
79 this.dependency = dependency;
80 this.engine = engine;
81 this.exceptions = exceptions;
82 this.settings = settings;
83 }
84
85 /**
86 * Executes the analysis task.
87 *
88 * @return null
89 * @throws Exception thrown if unable to execute the analysis task
90 */
91 @Override
92 public Void call() {
93 try {
94 Settings.setInstance(settings);
95
96 if (shouldAnalyze()) {
97 LOGGER.debug("Begin Analysis of '{}' ({})", dependency.getActualFilePath(), analyzer.getName());
98 try {
99 analyzer.analyze(dependency, engine);
100 } catch (AnalysisException ex) {
101 LOGGER.warn("An error occurred while analyzing '{}' ({}).", dependency.getActualFilePath(), analyzer.getName());
102 LOGGER.debug("", ex);
103 exceptions.add(ex);
104 } catch (Throwable ex) {
105 LOGGER.warn("An unexpected error occurred during analysis of '{}' ({}): {}",
106 dependency.getActualFilePath(), analyzer.getName(), ex.getMessage());
107 LOGGER.debug("", ex);
108 exceptions.add(ex);
109 }
110 }
111 } finally {
112 Settings.cleanup(false);
113 }
114 return null;
115 }
116
117 /**
118 * Determines if the analyzer can analyze the given dependency.
119 *
120 * @return whether or not the analyzer can analyze the dependency
121 */
122 boolean shouldAnalyze() {
123 if (analyzer instanceof FileTypeAnalyzer) {
124 final FileTypeAnalyzer fileTypeAnalyzer = (FileTypeAnalyzer) analyzer;
125 return fileTypeAnalyzer.accept(dependency.getActualFile());
126 }
127
128 return true;
129 }
130 }