View Javadoc
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) 2013 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.analyzer;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.util.List;
26  import java.util.Set;
27  import java.util.regex.Pattern;
28  import org.owasp.dependencycheck.suppression.SuppressionParseException;
29  import org.owasp.dependencycheck.suppression.SuppressionParser;
30  import org.owasp.dependencycheck.suppression.SuppressionRule;
31  import org.owasp.dependencycheck.utils.DownloadFailedException;
32  import org.owasp.dependencycheck.utils.Downloader;
33  import org.owasp.dependencycheck.utils.FileUtils;
34  import org.owasp.dependencycheck.utils.Settings;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  /**
39   * Abstract base suppression analyzer that contains methods for parsing the suppression xml file.
40   *
41   * @author Jeremy Long
42   */
43  public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
44  
45      /**
46       * The Logger for use throughout the class
47       */
48      private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSuppressionAnalyzer.class);
49  
50      //<editor-fold defaultstate="collapsed" desc="All standard implementation details of Analyzer">
51      /**
52       * Returns a list of file EXTENSIONS supported by this analyzer.
53       *
54       * @return a list of file EXTENSIONS supported by this analyzer.
55       */
56      public Set<String> getSupportedExtensions() {
57          return null;
58      }
59  
60      //</editor-fold>
61      /**
62       * The initialize method loads the suppression XML file.
63       *
64       * @throws Exception thrown if there is an exception
65       */
66      @Override
67      public void initialize() throws Exception {
68          super.initialize();
69          loadSuppressionData();
70      }
71  
72      /**
73       * The list of suppression rules
74       */
75      private List<SuppressionRule> rules;
76  
77      /**
78       * Get the value of rules.
79       *
80       * @return the value of rules
81       */
82      public List<SuppressionRule> getRules() {
83          return rules;
84      }
85  
86      /**
87       * Set the value of rules.
88       *
89       * @param rules new value of rules
90       */
91      public void setRules(List<SuppressionRule> rules) {
92          this.rules = rules;
93      }
94  
95      /**
96       * Loads the suppression rules file.
97       *
98       * @throws SuppressionParseException thrown if the XML cannot be parsed.
99       */
100     private void loadSuppressionData() throws SuppressionParseException {
101         final SuppressionParser parser = new SuppressionParser();
102         File file = null;
103         try {
104             rules = parser.parseSuppressionRules(this.getClass().getClassLoader().getResourceAsStream("dependencycheck-base-suppression.xml"));
105         } catch (SuppressionParseException ex) {
106             LOGGER.debug("Unable to parse the base suppression data file", ex);
107         }
108         final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
109         if (suppressionFilePath == null) {
110             return;
111         }
112         boolean deleteTempFile = false;
113         try {
114             final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
115             if (uriRx.matcher(suppressionFilePath).matches()) {
116                 deleteTempFile = true;
117                 file = FileUtils.getTempFile("suppression", "xml");
118                 final URL url = new URL(suppressionFilePath);
119                 try {
120                     Downloader.fetchFile(url, file, false);
121                 } catch (DownloadFailedException ex) {
122                     Downloader.fetchFile(url, file, true);
123                 }
124             } else {
125                 file = new File(suppressionFilePath);
126                 if (!file.exists()) {
127                     final InputStream suppressionsFromClasspath = this.getClass().getClassLoader().getResourceAsStream(suppressionFilePath);
128                     if (suppressionsFromClasspath != null) {
129                         deleteTempFile = true;
130                         file = FileUtils.getTempFile("suppression", "xml");
131                         try {
132                             org.apache.commons.io.FileUtils.copyInputStreamToFile(suppressionsFromClasspath, file);
133                         } catch (IOException ex) {
134                             throwSuppressionParseException("Unable to locate suppressions file in classpath", ex);
135                         }
136                     }
137                 }
138             }
139 
140             if (file != null) {
141                 try {
142                     //rules = parser.parseSuppressionRules(file);
143                     rules.addAll(parser.parseSuppressionRules(file));
144                     LOGGER.debug("{} suppression rules were loaded.", rules.size());
145                 } catch (SuppressionParseException ex) {
146                     LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
147                     LOGGER.warn(ex.getMessage());
148                     LOGGER.debug("", ex);
149                     throw ex;
150                 }
151             }
152         } catch (DownloadFailedException ex) {
153             throwSuppressionParseException("Unable to fetch the configured suppression file", ex);
154         } catch (MalformedURLException ex) {
155             throwSuppressionParseException("Configured suppression file has an invalid URL", ex);
156         } catch (IOException ex) {
157             throwSuppressionParseException("Unable to create temp file for suppressions", ex);
158         } finally {
159             if (deleteTempFile && file != null) {
160                 FileUtils.delete(file);
161             }
162         }
163     }
164 
165     /**
166      * Utility method to throw parse exceptions.
167      *
168      * @param message the exception message
169      * @param exception the cause of the exception
170      * @throws SuppressionParseException throws the generated SuppressionParseException
171      */
172     private void throwSuppressionParseException(String message, Exception exception) throws SuppressionParseException {
173         LOGGER.warn(message);
174         LOGGER.debug("", exception);
175         throw new SuppressionParseException(message, exception);
176     }
177 }