1 /*
2 * This file is part of dependency-check-ant.
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) 2015 Jeremy Long. All Rights Reserved.
17 */
18 package org.owasp.dependencycheck.taskdefs;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.util.List;
24
25 import org.apache.tools.ant.BuildException;
26 import org.apache.tools.ant.Project;
27 import org.apache.tools.ant.Task;
28 import org.owasp.dependencycheck.Engine;
29 import org.owasp.dependencycheck.utils.Downloader;
30 import org.owasp.dependencycheck.utils.InvalidSettingException;
31 import org.owasp.dependencycheck.utils.Settings;
32 import org.owasp.dependencycheck.ant.logging.AntTaskHolder;
33
34 /**
35 * An Ant task definition to execute dependency-check during an Ant build.
36 *
37 * @author Jeremy Long
38 */
39 public class Purge extends Task {
40
41 /**
42 * The properties file location.
43 */
44 private static final String PROPERTIES_FILE = "task.properties";
45 /**
46 * The configured settings.
47 */
48 private Settings settings;
49
50 /**
51 * The location of the data directory that contains
52 */
53 private String dataDirectory = null;
54 /**
55 * Indicates if dependency-check should fail the build if an exception
56 * occurs.
57 */
58 private boolean failOnError = true;
59
60 /**
61 * Construct a new DependencyCheckTask.
62 */
63 public Purge() {
64 super();
65
66 // Call this before Dependency Check Core starts logging anything - this way, all SLF4J messages from
67 // core end up coming through this tasks logger
68 AntTaskHolder.setTask(this);
69 }
70
71 public Settings getSettings() {
72 return settings;
73 }
74
75 /**
76 * Set the value of dataDirectory.
77 *
78 * @param dataDirectory new value of dataDirectory
79 */
80 public void setDataDirectory(String dataDirectory) {
81 this.dataDirectory = dataDirectory;
82 }
83
84 /**
85 * Get the value of failOnError.
86 *
87 * @return the value of failOnError
88 */
89 public boolean isFailOnError() {
90 return failOnError;
91 }
92
93 /**
94 * Set the value of failOnError.
95 *
96 * @param failOnError new value of failOnError
97 */
98 public void setFailOnError(boolean failOnError) {
99 this.failOnError = failOnError;
100 }
101
102 /**
103 * Sets the
104 * {@link Thread#getContextClassLoader() Thread Context Class Loader} to the
105 * one for this class, and then calls
106 * {@link #executeWithContextClassloader()}. This is done because the JCS
107 * cache needs to have the Thread Context Class Loader set to something that
108 * can resolve it's classes. Other build tools do this by default but Ant
109 * does not.
110 *
111 * @throws BuildException throws if there is a problem. See
112 * {@link #executeWithContextClassloader()} for details
113 */
114 @Override
115 public final void execute() throws BuildException {
116 muteNoisyLoggers();
117 final ClassLoader current = Thread.currentThread().getContextClassLoader();
118 try {
119 Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
120
121 executeWithContextClassloader();
122 } finally {
123 Thread.currentThread().setContextClassLoader(current);
124 AntTaskHolder.remove();
125 }
126 }
127
128 /**
129 * Hacky method of muting the noisy logging from certain libraries.
130 */
131 private void muteNoisyLoggers() {
132 // Mirrors the configuration within cli/src/main/resources/logback.xml
133 final List<String> noisyLoggers = List.of(
134 "org.apache.lucene",
135 "org.apache.commons.jcs3",
136 "org.apache.hc"
137 );
138 for (String loggerName : noisyLoggers) {
139 System.setProperty("org.slf4j.simpleLogger.log." + loggerName, "error");
140 }
141 }
142
143 /**
144 * Executes the dependency-check purge to delete the existing local copy of
145 * the NVD CVE data.
146 *
147 * @throws BuildException thrown if there is a problem deleting the file(s)
148 */
149 //see note on `Check.dealWithReferences()` for information on this suppression
150 @SuppressWarnings("squid:RedundantThrowsDeclarationCheck")
151 protected void executeWithContextClassloader() throws BuildException {
152 populateSettings();
153 try {
154 Downloader.getInstance().configure(settings);
155 } catch (InvalidSettingException e) {
156 throw new BuildException(e);
157 }
158 try (Engine engine = new Engine(Engine.Mode.EVIDENCE_PROCESSING, getSettings())) {
159 engine.purge();
160 } finally {
161 settings.cleanup(true);
162 }
163 }
164
165 /**
166 * Takes the properties supplied and updates the dependency-check settings.
167 * Additionally, this sets the system properties required to change the
168 * proxy server, port, and connection timeout.
169 *
170 * @throws BuildException thrown if the properties file cannot be read.
171 */
172 //see note on `Check.dealWithReferences()` for information on this suppression
173 @SuppressWarnings("squid:RedundantThrowsDeclarationCheck")
174 protected void populateSettings() throws BuildException {
175 settings = new Settings();
176 try (InputStream taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE)) {
177 settings.mergeProperties(taskProperties);
178 } catch (IOException ex) {
179 final String msg = "Unable to load the dependency-check ant task.properties file.";
180 if (this.failOnError) {
181 throw new BuildException(msg, ex);
182 }
183 log(msg, ex, Project.MSG_WARN);
184 }
185 if (dataDirectory != null) {
186 settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
187 } else {
188 final File jarPath = new File(Purge.class.getProtectionDomain().getCodeSource().getLocation().getPath());
189 final File base = jarPath.getParentFile();
190 final String sub = settings.getString(Settings.KEYS.DATA_DIRECTORY);
191 final File dataDir = new File(base, sub);
192 settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
193 }
194 }
195 }