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