001: //$Id: SAXValidator.java 261 2006-11-15 21:55:52Z jg_hamburg $
002: /********************************************************************************
003: * DDTUnit, a Datadriven Approach to Unit- and Moduletesting
004: * Copyright (c) 2004, Joerg and Kai Gellien
005: * All rights reserved.
006: *
007: * The Software is provided under the terms of the Common Public License 1.0
008: * as provided with the distribution of DDTUnit in the file cpl-v10.html.
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * + Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * + Redistributions in binary form must reproduce the above
017: * copyright notice, this list of conditions and the following
018: * disclaimer in the documentation and/or other materials provided
019: * with the distribution.
020: *
021: * + Neither the name of the authors or DDTUnit, nor the
022: * names of its contributors may be used to endorse or promote
023: * products derived from this software without specific prior
024: * written permission.
025: *
026: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
027: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
028: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
029: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
030: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
031: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
032: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
033: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
034: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
035: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
036: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037: ********************************************************************************/package junitx.ddtunit.data.processing.parser;
038:
039: import java.io.File;
040: import java.io.IOException;
041: import java.io.InputStream;
042:
043: import javax.xml.parsers.ParserConfigurationException;
044: import javax.xml.parsers.SAXParserFactory;
045:
046: import junitx.ddtunit.DDTException;
047:
048: import org.apache.log4j.Logger;
049: import org.xml.sax.InputSource;
050: import org.xml.sax.Locator;
051: import org.xml.sax.SAXException;
052: import org.xml.sax.SAXNotRecognizedException;
053: import org.xml.sax.SAXParseException;
054: import org.xml.sax.XMLReader;
055: import org.xml.sax.helpers.DefaultHandler;
056: import org.xml.sax.helpers.LocatorImpl;
057:
058: /**
059: * @author jg
060: */
061: public final class SAXValidator extends ErrorHandler {
062: private static final String XML_XERCES_NONAMESPACE_SCHEMA_LOCATION_URI = "http://apache.org/xml/properties/schema/external-noNamespaceSchemaLocation";
063:
064: private static final String XML_XERCES_SCHEMA_FULL_CHECK_URI = "http://apache.org/xml/features/validation/schema-full-checking";
065:
066: private static final String XML_XERCES_VALIDATE_URI = "http://apache.org/xml/features/validation/schema";
067:
068: /**
069: * resource path of xml schema used for validation
070: */
071: public final static String XSD_RESOURCE_PATH = "/junitx/ddtunit/data/processing/parser/ddtunit.xsd";
072:
073: private Logger log = Logger.getLogger(SAXValidator.class);
074:
075: private XMLReader producer;
076:
077: private DefaultHandler consumer;
078:
079: private static final String XML_VALIDATE_URI = "http://xml.org/sax/features/validation";
080:
081: private static final String XML_NAMESPACE_URI = "http://xml.org/sax/features/namespaces";
082:
083: private static final String XML_NAMESPACE_PREFIX_URI = "http://xml.org/sax/features/namespace-prefixes";
084:
085: private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
086:
087: private static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
088:
089: private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
090:
091: private static final String LF = System
092: .getProperty("line.separator");
093:
094: public SAXValidator() {
095: log.debug("DDTParser - constructor START");
096: try {
097: // the SAX way
098: // this.producer = XMLReaderFactory.createXMLReader();
099: // the jaxp1.1 way
100: SAXParserFactory factory = SAXParserFactory.newInstance();
101: factory.setNamespaceAware(true);
102: factory.setValidating(true);
103: this .producer = factory.newSAXParser().getXMLReader();
104: // this.producer = new SAXParser();
105: this .producer.setFeature(XML_NAMESPACE_PREFIX_URI, false);
106: this .producer.setFeature(XML_NAMESPACE_URI, true);
107:
108: this .producer.setFeature(XML_VALIDATE_URI, true);
109: this .producer.setFeature(XML_XERCES_VALIDATE_URI, true);
110: this .producer.setFeature(XML_XERCES_SCHEMA_FULL_CHECK_URI,
111: true);
112: this .producer.setProperty(
113: XML_XERCES_NONAMESPACE_SCHEMA_LOCATION_URI,
114: ParserImpl.XSD_URL);
115: this .producer.setProperty(JAXP_SCHEMA_LANGUAGE,
116: W3C_XML_SCHEMA);
117: this .producer.setProperty(JAXP_SCHEMA_SOURCE,
118: ParserImpl.XSD_URL);
119: } catch (SAXNotRecognizedException e) {
120: throw DDTException
121: .create(
122: new StringBuffer(
123: "XML ParserImpl does not support schema validation as of JAXP 1.2"),
124: e);
125: } catch (ParserConfigurationException e) {
126: throw DDTException.create(new StringBuffer(
127: "Error configuring parser."), e);
128: } catch (SAXException e) {
129: throw DDTException.create(new StringBuffer(
130: "Error configuring parser."), e);
131: }
132:
133: this .producer.setErrorHandler(new ErrorHandler());
134: this .producer.setEntityResolver(new EntityResolver());
135: log.debug("DDTParser - constructor END");
136:
137: }
138:
139: public void validate(String resourceName) {
140: this .consumer = new DefaultHandler();
141: Locator locator = new LocatorImpl();
142: this .consumer.setDocumentLocator(locator);
143: this .producer.setContentHandler(consumer);
144: this .producer.setEntityResolver(new EntityResolver());
145: try {
146: // process reource
147: // check if resource is file or resource
148: InputSource iSource = null;
149: InputStream in = this .getClass().getResourceAsStream(
150: resourceName);
151:
152: if (in == null) {
153: File inFile = new File(resourceName);
154:
155: if (inFile.exists()) {
156: iSource = new InputSource(resourceName);
157: iSource
158: .setSystemId(inFile.toURL()
159: .toExternalForm());
160: this .producer.parse(iSource);
161: } else {
162: StringBuffer sb = new StringBuffer();
163: sb
164: .append(
165: "Could not find provided testdata resource: ")
166: .append(resourceName);
167: throw DDTException.create(sb, null);
168: }
169: } else {
170: iSource = new InputSource(in);
171: iSource.setSystemId(this .getClass().getResource(
172: resourceName).toExternalForm());
173: this .producer.parse(iSource);
174: }
175: } catch (IOException e) {
176: log.error("Error on behalf of xml test resource.", e);
177: throw DDTException.create(new StringBuffer(
178: "Error on behalf of xml test resource."), e);
179: } catch (SAXException e) {
180: StringBuffer sb = new StringBuffer(
181: "Error during parsing of xml testresource");
182: if (SAXParseException.class.isInstance(e)) {
183: sb
184: .append(LF)
185: .append("Resource \'")
186: .append(resourceName)
187: .append("\' line/column ")
188: .append(((SAXParseException) e).getLineNumber())
189: .append("/").append(
190: ((SAXParseException) e)
191: .getColumnNumber());
192: }
193: log.error(sb.toString(), e);
194: throw DDTException.create(sb, e);
195: } finally {
196: log.debug("parse(" + resourceName + ")-END");
197: }
198: }
199: }
|