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