View Javadoc
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 }