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) 2016 Jeremy Long. All Rights Reserved.
17   */
18  package org.owasp.dependencycheck.xml.hints;
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 javax.xml.parsers.ParserConfigurationException;
28  import javax.xml.parsers.SAXParser;
29  import javax.xml.parsers.SAXParserFactory;
30  
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  import org.xml.sax.InputSource;
34  import org.xml.sax.SAXException;
35  import org.xml.sax.XMLReader;
36  
37  /**
38   * A simple validating parser for XML Hint Rules.
39   *
40   * @author Jeremy Long
41   */
42  public class HintParser {
43  
44      /**
45       * The logger.
46       */
47      private static final Logger LOGGER = LoggerFactory.getLogger(HintParser.class);
48      /**
49       * JAXP Schema Language. Source:
50       * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
51       */
52      public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
53      /**
54       * W3C XML Schema. Source:
55       * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
56       */
57      public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
58      /**
59       * JAXP Schema Source. Source:
60       * http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
61       */
62      public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
63  
64      /**
65       * The schema for the hint XML files.
66       */
67      private static final String HINT_SCHEMA = "schema/dependency-hint.1.1.xsd";
68  
69      /**
70       * Parses the given XML file and returns a list of the hints contained.
71       *
72       * @param file an XML file containing hints
73       * @return a list of hint rules
74       * @throws HintParseException thrown if the XML file cannot be parsed
75       */
76      public Hints parseHints(File file) throws HintParseException {
77          FileInputStream fis = null;
78          try {
79              fis = new FileInputStream(file);
80              return parseHints(fis);
81          } catch (IOException ex) {
82              LOGGER.debug("", ex);
83              throw new HintParseException(ex);
84          } catch (SAXException ex) {
85              throw new HintParseException(ex);
86          } finally {
87              if (fis != null) {
88                  try {
89                      fis.close();
90                  } catch (IOException ex) {
91                      LOGGER.debug("Unable to close stream", ex);
92                  }
93              }
94          }
95      }
96  
97      /**
98       * Parses the given XML stream and returns a list of the hint rules
99       * contained.
100      *
101      * @param inputStream an InputStream containing hint rules
102      * @return a list of hint rules
103      * @throws HintParseException thrown if the XML cannot be parsed
104      * @throws SAXException thrown if the XML cannot be parsed
105      */
106     public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException {
107         InputStream schemaStream = null;
108         try {
109             schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
110             final HintHandler handler = new HintHandler();
111             final SAXParserFactory factory = SAXParserFactory.newInstance();
112             factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
113             factory.setNamespaceAware(true);
114             factory.setValidating(true);
115             final SAXParser saxParser = factory.newSAXParser();
116             saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
117             saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
118             final XMLReader xmlReader = saxParser.getXMLReader();
119             xmlReader.setErrorHandler(new HintErrorHandler());
120             xmlReader.setContentHandler(handler);
121 
122             final Reader reader = new InputStreamReader(inputStream, "UTF-8");
123             final InputSource in = new InputSource(reader);
124 
125             xmlReader.parse(in);
126             final Hints hints = new Hints();
127             hints.setHintRules(handler.getHintRules());
128             hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules());
129             return hints;
130         } catch (ParserConfigurationException ex) {
131             LOGGER.debug("", ex);
132             throw new HintParseException(ex);
133         } catch (SAXException ex) {
134             if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
135                 throw ex;
136             } else {
137                 LOGGER.debug("", ex);
138                 throw new HintParseException(ex);
139             }
140         } catch (FileNotFoundException ex) {
141             LOGGER.debug("", ex);
142             throw new HintParseException(ex);
143         } catch (IOException ex) {
144             LOGGER.debug("", ex);
145             throw new HintParseException(ex);
146         } finally {
147             if (schemaStream != null) {
148                 try {
149                     schemaStream.close();
150                 } catch (IOException ex) {
151                     LOGGER.debug("Error closing hint file stream", ex);
152                 }
153             }
154         }
155     }
156 }