Permalink
Browse files

Fixes #89 - Add specific JAXP-factory mechanisms to JAXP-based pillar…

…s for SAX parsing.

Also update the sax-based parsing descriptions/documentation.
  • Loading branch information...
1 parent 17e18fe commit 2dfdd9b93f24c2c2b1c567b15ef677f6c1d4a887 @rolfl rolfl committed Aug 26, 2012
@@ -0,0 +1,118 @@
+/*--
+
+ Copyright (C) 2012 Jason Hunter & Brett McLaughlin.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions, and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions, and the disclaimer that follows
+ these conditions in the documentation and/or other materials
+ provided with the distribution.
+
+ 3. The name "JDOM" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact <request_AT_jdom_DOT_org>.
+
+ 4. Products derived from this software may not be called "JDOM", nor
+ may "JDOM" appear in their name, without prior written permission
+ from the JDOM Project Management <request_AT_jdom_DOT_org>.
+
+ In addition, we request (but do not require) that you include in the
+ end-user documentation provided with the redistribution and/or in the
+ software itself an acknowledgement equivalent to the following:
+ "This product includes software developed by the
+ JDOM Project (http://www.jdom.org/)."
+ Alternatively, the acknowledgment may be graphical using the logos
+ available at http://www.jdom.org/images/logos.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many
+ individuals on behalf of the JDOM Project and was originally
+ created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
+ Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
+ on the JDOM Project, please see <http://www.jdom.org/>.
+
+ */
+
+package org.jdom2.input.sax;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import org.jdom2.JDOMException;
+
+/**
+ * Create XMLReaders directly from the javax.xml.parsers.SAXParserFactory API using an explicit
+ * implementation of the parser instead of relying on the default JAXP search path.
+ * <p>
+ * If you want to rely on the default JAXP search mechanism you should instead use one of the simple
+ * members of the {@link XMLReaders} enumeration, or use one of the simple constructors on
+ * {@link XMLReaderXSDFactory} or {@link XMLReaderSchemaFactory}.
+ * <p>
+ * See the documentation for {@link SAXParserFactory} for the details on what the factoryClassName
+ * and classLoader should be.
+ *
+ * @see org.jdom2.input.sax
+ * @since 2.0.3
+ * @author Rolf Lear
+ */
+public class XMLReaderJAXPFactory implements XMLReaderJDOMFactory {
+
+ private final SAXParserFactory instance;
+ private final boolean validating;
+
+ /**
+ * Create an XMLReaderJAXPFactory using the specified factory name, classloader, and
+ * dtdvalidating flag.
+ * @param factoryClassName The name of the implementation to use for the SAXParserFactory.
+ * @param classLoader The classloader to use for locating the SAXParserFactory (may be null).
+ * @param dtdvalidate Whether this should create DTD Validating XMLReaders.
+ */
+ public XMLReaderJAXPFactory(final String factoryClassName, final ClassLoader classLoader,
+ boolean dtdvalidate) {
+ instance = SAXParserFactory.newInstance(factoryClassName, classLoader);
+ instance.setNamespaceAware(true);
+ instance.setValidating(dtdvalidate);
+ validating = dtdvalidate;
+ }
+
+ @Override
+ public XMLReader createXMLReader() throws JDOMException {
+ try {
+ return instance.newSAXParser().getXMLReader();
+ } catch (SAXException e) {
+ throw new JDOMException(
+ "Unable to create a new XMLReader instance", e);
+ } catch (ParserConfigurationException e) {
+ throw new JDOMException(
+ "Unable to create a new XMLReader instance", e);
+ }
+ }
+
+ @Override
+ public boolean isValidating() {
+ return validating;
+ }
+
+}
@@ -60,7 +60,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
/**
* This {@link XMLReaderJDOMFactory} class returns XMLReaders configured to
* validate against the supplied Schema instance. The Schema could be an XSD
- * schema or some other schema supported by SAX (e.g. RelaxNG).
+ * schema or some other schema supported by SAX (e.g. RelaxNG). The SAX Parser
+ * is obtained through the JAXP process.
* <p>
* If you want to validate an XML document against the XSD references embedded
* in the XML itself (xsdSchemaLocation) then you do not want to use this class
@@ -82,8 +83,23 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* @param schema
* The Schema to use for validation.
*/
- public XMLReaderSchemaFactory(Schema schema) {
+ public XMLReaderSchemaFactory(final Schema schema) {
super(SAXParserFactory.newInstance(), schema);
}
+ /**
+ * XMLReader instances from this class will be configured to validate using
+ * the supplied Schema instance, and use the specified JAXP SAXParserFactory.
+ *
+ * @param factoryClassName The name of the SAXParserFactory class to use
+ * @param classloader The classLoader to use for loading the SAXParserFactory.
+ * @param schema
+ * The Schema to use for validation.
+ * @since 2.0.3
+ */
+ public XMLReaderSchemaFactory(final String factoryClassName, final ClassLoader classloader,
+ final Schema schema) {
+ super(SAXParserFactory.newInstance(factoryClassName, classloader), schema);
+ }
+
}
@@ -66,7 +66,9 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
/**
* This XMLReaderJDOMFactory class returns XMLReaders configured to validate
- * against the supplied XML Schema (XSD) instance.
+ * against the supplied XML Schema (XSD) instance. The SAX Parser is obtained through
+ * the JAXP process.
+ *
* <p>
* This class has var-arg constructors, accepting potentially many XSD sources.
* It is just as simple though to have a single source:
@@ -111,6 +113,25 @@ public XMLReaderXSDFactory(String... systemid)
/**
* Create an XML Schema validating XMLReader factory using one or more XSD
+ * sources from SystemID references, and use the specified JAXP SAXParserFactory.
+ *
+ * @param factoryClassName The name of the SAXParserFactory class to use
+ * @param classloader The classLoader to use for loading the SAXParserFactory.
+ * @param systemid
+ * The var-arg array of at least one SystemID reference (URL) to
+ * locate the XSD's used to validate
+ * @throws JDOMException
+ * If the Schemas could not be loaded from the SystemIDs This will
+ * wrap a SAXException that contains the actual fault.
+ * @since 2.0.3
+ */
+ public XMLReaderXSDFactory(final String factoryClassName, final ClassLoader classloader,
+ final String... systemid) throws JDOMException {
+ super(SAXParserFactory.newInstance(factoryClassName, classloader), xsdschemas, systemid);
+ }
+
+ /**
+ * Create an XML Schema validating XMLReader factory using one or more XSD
* sources from URL references.
*
* @param systemid
@@ -126,6 +147,25 @@ public XMLReaderXSDFactory(URL... systemid) throws JDOMException {
/**
* Create an XML Schema validating XMLReader factory using one or more XSD
+ * sources from URL references, and use the specified JAXP SAXParserFactory.
+ *
+ * @param factoryClassName The name of the SAXParserFactory class to use
+ * @param classloader The classLoader to use for loading the SAXParserFactory.
+ * @param systemid
+ * The var-arg array of at least one SystemID reference (URL) to
+ * locate the XSD's used to validate
+ * @throws JDOMException
+ * If the Schemas could not be loaded from the SystemIDs This will
+ * wrap a SAXException that contains the actual fault.
+ * @since 2.0.3
+ */
+ public XMLReaderXSDFactory(final String factoryClassName, final ClassLoader classloader,
+ URL... systemid) throws JDOMException {
+ super(SAXParserFactory.newInstance(factoryClassName, classloader), xsdschemas, systemid);
+ }
+
+ /**
+ * Create an XML Schema validating XMLReader factory using one or more XSD
* sources from File references.
*
* @param systemid
@@ -141,6 +181,25 @@ public XMLReaderXSDFactory(File... systemid) throws JDOMException {
/**
* Create an XML Schema validating XMLReader factory using one or more XSD
+ * sources from File references, and use the specified JAXP SAXParserFactory.
+ *
+ * @param factoryClassName The name of the SAXParserFactory class to use
+ * @param classloader The classLoader to use for loading the SAXParserFactory.
+ * @param systemid
+ * The var-arg array of at least one SystemID reference (File) to
+ * locate the XSD's used to validate
+ * @throws JDOMException
+ * If the Schemas could not be loaded from the SystemIDs This will
+ * wrap a SAXException that contains the actual fault.
+ * @since 2.0.3
+ */
+ public XMLReaderXSDFactory(final String factoryClassName, final ClassLoader classloader,
+ File... systemid) throws JDOMException {
+ super(SAXParserFactory.newInstance(factoryClassName, classloader), xsdschemas, systemid);
+ }
+
+ /**
+ * Create an XML Schema validating XMLReader factory using one or more XSD
* sources from Transform Source references.
*
* @param sources
@@ -154,4 +213,23 @@ public XMLReaderXSDFactory(Source... sources) throws JDOMException {
super(SAXParserFactory.newInstance(), xsdschemas, sources);
}
+ /**
+ * Create an XML Schema validating XMLReader factory using one or more XSD
+ * sources from Transform Source references, and use the specified JAXP SAXParserFactory.
+ *
+ * @param factoryClassName The name of the SAXParserFactory class to use
+ * @param classloader The classLoader to use for loading the SAXParserFactory.
+ * @param sources
+ * The var-arg array of at least one transform Source reference to
+ * locate the XSD's used to validate
+ * @throws JDOMException
+ * If the Schemas could not be loaded from the Sources This will
+ * wrap a SAXException that contains the actual fault.
+ * @since 2.0.3
+ */
+ public XMLReaderXSDFactory(final String factoryClassName, final ClassLoader classloader,
+ Source... sources) throws JDOMException {
+ super(SAXParserFactory.newInstance(factoryClassName, classloader), xsdschemas, sources);
+ }
+
}
@@ -87,7 +87,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
{@link org.jdom2.input.sax.XMLReaders#NONVALIDATING} which it
mates with a Default {@link org.jdom2.input.sax.SAXHandler} factory, and the
{@link org.jdom2.DefaultJDOMFactory}.
- <li>A number of other constructors that mostly are for backward-compatibility
+ <li>A number of other constructors that are mostly for backward-compatibility
with JDOM 1.x. These other constructors affect what
{@link org.jdom2.input.sax.XMLReaderJDOMFactory} will be used but still use
the default SAXHandler and JDOMFactory values.
@@ -101,10 +101,29 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
<h2>The XMLReaderJDOMFactory Pillar</h2>
-
- SAX parsers have been exposed as different things during the evolution of the
- SAX API, but in SAX2.0 they are <code>XMLReader</code> instances. Thus
- SAXBuilder needs an XMLReader to process the input. To get an XMLReader the
+
+ A brief history of XML Parsers in Java:<br>
+ XML Parsers have been available in Java from essentially 'the beginning'. There
+ have been a number different ways to access these parsers though:
+ <ol>
+ <li>Create the parser directly 'by name'.
+ <li>Use the SAX (and later the SAX 2.0) API to locate a parser.
+ <li>Use JAXP (versions 1, through 1.4) API to locate a parser.
+ </ol>
+ <p>
+ In addition to the different ways of creating an XML parser, there have also
+ been updates to the way the actual SAX parsing API is exposed to Java (the Java
+ interface). The SAX specification was revised with version 2.0. The 'new' SAX
+ version introduced the XMLReader concept, which replaces the XMLParser concept.
+ These two concepts aim to accomplish the same goal, but do it in different
+ ways.
+ <p>
+ JDOM 2.x requires an XMLReader (SAX 2.0) interface, thus your XML parser needs
+ to be compatible with SAX 2.0 (for the XMLReader), but should be accessible
+ through JAXP which is the more modern and flexible access system.
+ <p>
+ The purpose of the XMLReaderJDOMFactory Pillar is to give the SAXBuilder an
+ XMLReader instance (a SAX 2.0 parser). To get an XMLReader the
SAXBuilder delegates to the {@link org.jdom2.input.sax.XMLReaderJDOMFactory}
by calling {@link org.jdom2.input.sax.XMLReaderJDOMFactory#createXMLReader()}
<p>
@@ -132,18 +151,20 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
<li>It allows you to create differently-configured 'factories' that
create XMLReaders in a pre-specified format (SAX2.0 has a single global
factory that creates raw XMLReader instances that then need to be
- re-configured for you task).
+ re-configured for your task).
</ul>
<h3>JAXP Factories</h3>
- JDOM exposes five factories that use JAXP to source XMLReaders. These factories
+ JDOM exposes six factories that use JAXP to source XMLReaders. These factories
cover almost all conditions under which you would want a SAX parser:
<ol>
<li>A simple non-validating SAX parser
<li>A validating parser that uses the DOCTYPE references in the XML to validate
against.
<li>A validating parser that uses the XML Schema (XSD) references embedded in
the XML to validate against.
+ <li>A factory that uses a specific JAXP-based parser that can optionally
+ validate using the DTD DocType.
<li>A validating parser that uses an external Schema (XML Schema, Relax NG,
etc.) to validate the XML against.
<li>A special case of the Schema-validating factory that specialises in XML
@@ -155,15 +176,22 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
are 'singletons' that can be used in a multi-threaded and concurrent way to
provide XMLReaders that are configured correctly for the respective behaviour.
<p>
+ To parse with a specific (rather than the default) JAXP-based XML Parser
+ you can use the {@link org.jdom2.input.sax.XMLReaderJAXPFactory}. This factory
+ can optionally be set to do DTD validation during the parse.
+ <p>
To validate using an arbitrary external Schema you can use the
{@link org.jdom2.input.sax.XMLReaderSchemaFactory} to create an instance for
the particular Schema you want to validate against. Because this requires an
- input Schema it cannot be constructed as a singleton like the others.
+ input Schema it cannot be constructed as a singleton like the others. There
+ are constructors that allow you to use a specific (rather than the default)
+ JAXP-compatible parser.
<p>
{@link org.jdom2.input.sax.XMLReaderXSDFactory} is a special case of
XMLReaderSchemaFactory which internally uses an efficient mechanism to
compile Schema instances from one or many input XSD documents which can come
- from multiple sources.
+ from multiple sources. There are constructors that allow you to use a specific
+ (rather than the default) JAXP-compatible parser.
<h3>SAX 2.0 Factory</h3>
Oops, something went wrong.

0 comments on commit 2dfdd9b

Please sign in to comment.