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.suppression;
19  
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.FileNotFoundException;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.InputStreamReader;
26  import java.io.Reader;
27  import java.util.List;
28  import javax.xml.parsers.ParserConfigurationException;
29  import javax.xml.parsers.SAXParser;
30  import javax.xml.parsers.SAXParserFactory;
31  
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  import org.xml.sax.InputSource;
35  import org.xml.sax.SAXException;
36  import org.xml.sax.XMLReader;
37  
38  /**
39   * A simple validating parser for XML Suppression Rules.
40   *
41   * @author Jeremy Long
42   */
43  public class SuppressionParser {
44  
45      /**
46       * The logger.
47       */
48      private static final Logger LOGGER = LoggerFactory.getLogger(SuppressionParser.class);
49      /**
50       * JAXP Schema Language. Source:
51       * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
52       */
53      public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
54      /**
55       * W3C XML Schema. Source:
56       * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
57       */
58      public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
59      /**
60       * JAXP Schema Source. Source:
61       * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
62       */
63      public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
64  
65      /**
66       * Parses the given xml file and returns a list of the suppression rules
67       * contained.
68       *
69       * @param file an xml file containing suppression rules
70       * @return a list of suppression rules
71       * @throws SuppressionParseException thrown if the xml file cannot be parsed
72       */
73      public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
74          FileInputStream fis = null;
75          try {
76              fis = new FileInputStream(file);
77              return parseSuppressionRules(fis);
78          } catch (IOException ex) {
79              LOGGER.debug("", ex);
80              throw new SuppressionParseException(ex);
81          } catch (SAXException ex) {
82              try {
83                  if (fis != null) {
84                      try {
85                          fis.close();
86                      } catch (IOException ex1) {
87                          LOGGER.debug("Unable to close stream", ex1);
88                      }
89                  }
90                  fis = new FileInputStream(file);
91              } catch (FileNotFoundException ex1) {
92                  throw new SuppressionParseException(ex);
93              }
94              return parseOldSuppressionRules(fis);
95          } finally {
96              if (fis != null) {
97                  try {
98                      fis.close();
99                  } catch (IOException ex) {
100                     LOGGER.debug("Unable to close stream", ex);
101                 }
102             }
103         }
104     }
105 
106     /**
107      * Parses the given xml stream and returns a list of the suppression rules
108      * contained.
109      *
110      * @param inputStream an InputStream containing suppression rues
111      * @return a list of suppression rules
112      * @throws SuppressionParseException thrown if the xml cannot be parsed
113      * @throws SAXException thrown if the xml cannot be parsed
114      */
115     public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
116         try {
117             final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/dependency-suppression.1.1.xsd");
118             final SuppressionHandler handler = new SuppressionHandler();
119             final SAXParserFactory factory = SAXParserFactory.newInstance();
120             factory.setNamespaceAware(true);
121             factory.setValidating(true);
122             final SAXParser saxParser = factory.newSAXParser();
123             saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
124             saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
125             final XMLReader xmlReader = saxParser.getXMLReader();
126             xmlReader.setErrorHandler(new SuppressionErrorHandler());
127             xmlReader.setContentHandler(handler);
128 
129             final Reader reader = new InputStreamReader(inputStream, "UTF-8");
130             final InputSource in = new InputSource(reader);
131             //in.setEncoding("UTF-8");
132 
133             xmlReader.parse(in);
134 
135             return handler.getSuppressionRules();
136         } catch (ParserConfigurationException ex) {
137             LOGGER.debug("", ex);
138             throw new SuppressionParseException(ex);
139         } catch (SAXException ex) {
140             if (ex.getMessage().contains("Cannot find the declaration of element 'suppressions'.")) {
141                 throw ex;
142             } else {
143                 LOGGER.debug("", ex);
144                 throw new SuppressionParseException(ex);
145             }
146         } catch (FileNotFoundException ex) {
147             LOGGER.debug("", ex);
148             throw new SuppressionParseException(ex);
149         } catch (IOException ex) {
150             LOGGER.debug("", ex);
151             throw new SuppressionParseException(ex);
152         }
153     }
154 
155     /**
156      * Parses the given xml stream and returns a list of the suppression rules
157      * contained.
158      *
159      * @param inputStream an InputStream containing suppression rues
160      * @return a list of suppression rules
161      * @throws SuppressionParseException if the xml cannot be parsed
162      */
163     private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
164         try {
165             final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/suppression.xsd");
166             final SuppressionHandler handler = new SuppressionHandler();
167             final SAXParserFactory factory = SAXParserFactory.newInstance();
168             factory.setNamespaceAware(true);
169             factory.setValidating(true);
170             final SAXParser saxParser = factory.newSAXParser();
171             saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_LANGUAGE, SuppressionParser.W3C_XML_SCHEMA);
172             saxParser.setProperty(SuppressionParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
173             final XMLReader xmlReader = saxParser.getXMLReader();
174             xmlReader.setErrorHandler(new SuppressionErrorHandler());
175             xmlReader.setContentHandler(handler);
176 
177             final Reader reader = new InputStreamReader(inputStream, "UTF-8");
178             final InputSource in = new InputSource(reader);
179             //in.setEncoding("UTF-8");
180 
181             xmlReader.parse(in);
182 
183             return handler.getSuppressionRules();
184         } catch (ParserConfigurationException ex) {
185             LOGGER.debug("", ex);
186             throw new SuppressionParseException(ex);
187         } catch (SAXException ex) {
188             LOGGER.debug("", ex);
189             throw new SuppressionParseException(ex);
190         } catch (FileNotFoundException ex) {
191             LOGGER.debug("", ex);
192             throw new SuppressionParseException(ex);
193         } catch (IOException ex) {
194             LOGGER.debug("", ex);
195             throw new SuppressionParseException(ex);
196         }
197     }
198 }