View Javadoc

1   //$Id: SAXValidator.java 351 2008-08-14 20:20:56Z jg_hamburg $
2   /********************************************************************************
3    * DDTUnit, a Datadriven Approach to Unit- and Moduletesting
4    * Copyright (c) 2004, Joerg and Kai Gellien
5    * All rights reserved.
6    *
7    * The Software is provided under the terms of the Common Public License 1.0
8    * as provided with the distribution of DDTUnit in the file cpl-v10.html.
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   *     + Redistributions of source code must retain the above copyright
14   *       notice, this list of conditions and the following disclaimer.
15   *
16   *     + Redistributions in binary form must reproduce the above
17   *       copyright notice, this list of conditions and the following
18   *       disclaimer in the documentation and/or other materials provided
19   *       with the distribution.
20   *
21   *     + Neither the name of the authors or DDTUnit, nor the
22   *       names of its contributors may be used to endorse or promote
23   *       products derived from this software without specific prior
24   *       written permission.
25   *
26   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
30   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   ********************************************************************************/
38  package junitx.ddtunit.data.processing.parser;
39  
40  import java.io.File;
41  import java.io.IOException;
42  import java.io.InputStream;
43  
44  import javax.xml.parsers.ParserConfigurationException;
45  import javax.xml.parsers.SAXParserFactory;
46  
47  import junitx.ddtunit.DDTException;
48  
49  import org.slf4j.Logger;
50  import org.slf4j.LoggerFactory;
51  import org.xml.sax.InputSource;
52  import org.xml.sax.Locator;
53  import org.xml.sax.SAXException;
54  import org.xml.sax.SAXNotRecognizedException;
55  import org.xml.sax.SAXParseException;
56  import org.xml.sax.XMLReader;
57  import org.xml.sax.helpers.DefaultHandler;
58  import org.xml.sax.helpers.LocatorImpl;
59  
60  /**
61   * @author jg
62   */
63  public final class SAXValidator extends ErrorHandler {
64      private static final String XML_XERCES_NONAMESPACE_SCHEMA_LOCATION_URI = "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";
65  
66      private static final String XML_XERCES_SCHEMA_FULL_CHECK_URI = "http://apache.org/xml/features/validation/schema-full-checking";
67  
68      private static final String XML_XERCES_VALIDATE_URI = "http://apache.org/xml/features/validation/schema";
69  
70      /**
71       * resource path of xml schema used for validation
72       */
73      public final static String XSD_RESOURCE_PATH = "/junitx/ddtunit/data/processing/parser/ddtunit.xsd";
74  
75      private Logger log = LoggerFactory.getLogger(SAXValidator.class);
76  
77      private XMLReader producer;
78  
79      private DefaultHandler consumer;
80  
81      private static final String XML_VALIDATE_URI = "http://xml.org/sax/features/validation";
82  
83      private static final String XML_NAMESPACE_URI = "http://xml.org/sax/features/namespaces";
84  
85      private static final String XML_NAMESPACE_PREFIX_URI = "http://xml.org/sax/features/namespace-prefixes";
86  
87      private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
88  
89      private static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
90  
91      private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
92  
93      private static final String LF = System.getProperty("line.separator");
94  
95      public SAXValidator() {
96          log.debug("DDTParser - constructor START");
97          try {
98              // the SAX way
99              // this.producer = XMLReaderFactory.createXMLReader();
100             // the jaxp1.1 way
101             SAXParserFactory factory = SAXParserFactory.newInstance();
102             factory.setNamespaceAware(true);
103             factory.setValidating(true);
104             this.producer = factory.newSAXParser().getXMLReader();
105             // this.producer = new SAXParser();
106             this.producer.setFeature(XML_NAMESPACE_PREFIX_URI, false);
107             this.producer.setFeature(XML_NAMESPACE_URI, true);
108             
109             this.producer.setFeature(XML_VALIDATE_URI, true);
110             this.producer.setFeature(XML_XERCES_VALIDATE_URI, true);
111             this.producer.setFeature(XML_XERCES_SCHEMA_FULL_CHECK_URI, true);
112             this.producer.setProperty(
113                 XML_XERCES_NONAMESPACE_SCHEMA_LOCATION_URI, ParserImpl.XSD_URL);
114             this.producer.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
115             this.producer.setProperty(JAXP_SCHEMA_SOURCE, ParserImpl.XSD_URL);
116         } catch (SAXNotRecognizedException e) {
117             throw DDTException
118                 .create(
119                     new StringBuffer(
120                             "XML ParserImpl does not support schema validation as of JAXP 1.2"),
121                     e);
122         } catch (ParserConfigurationException e) {
123             throw DDTException.create(new StringBuffer(
124                     "Error configuring parser."), e);
125         } catch (SAXException e) {
126             throw DDTException.create(new StringBuffer(
127                     "Error configuring parser."), e);
128         }
129 
130         this.producer.setErrorHandler(new ErrorHandler());
131         this.producer.setEntityResolver(new EntityResolver());
132         log.debug("DDTParser - constructor END");
133 
134     }
135 
136     public void validate(String resourceName) {
137         this.consumer = new DefaultHandler();
138         Locator locator = new LocatorImpl();
139         this.consumer.setDocumentLocator(locator);
140         this.producer.setContentHandler(consumer);
141         this.producer.setEntityResolver(new EntityResolver());
142         try {
143             // process reource
144             // check if resource is file or resource
145             InputSource iSource = null;
146             InputStream in = this.getClass().getResourceAsStream(resourceName);
147 
148             if (in == null) {
149                 File inFile = new File(resourceName);
150 
151                 if (inFile.exists()) {
152                     iSource = new InputSource(resourceName);
153                     iSource.setSystemId(inFile.toURL().toExternalForm());
154                     this.producer.parse(iSource);
155                 } else {
156                     StringBuffer sb = new StringBuffer();
157                     sb.append("Could not find provided testdata resource: ")
158                         .append(resourceName);
159                     throw DDTException.create(sb, null);
160                 }
161             } else {
162                 iSource = new InputSource(in);
163                 iSource.setSystemId(this.getClass().getResource(resourceName)
164                     .toExternalForm());
165                 this.producer.parse(iSource);
166             }
167         } catch (IOException e) {
168             log.error("Error on behalf of xml test resource.", e);
169             throw DDTException.create(new StringBuffer(
170                     "Error on behalf of xml test resource."), e);
171         } catch (SAXException e) {
172             StringBuffer sb = new StringBuffer(
173                     "Error during parsing of xml testresource");
174             if (SAXParseException.class.isInstance(e)) {
175                 sb.append(LF).append("Resource \'").append(resourceName)
176                     .append("\' line/column ").append(
177                         ((SAXParseException) e).getLineNumber()).append("/")
178                     .append(((SAXParseException) e).getColumnNumber());
179             }
180             log.error(sb.toString(), e);
181             throw DDTException.create(sb, e);
182         } finally {
183             log.debug("parse(" + resourceName + ")-END");
184         }
185     }
186 }