attached is an implementation of xml schema that is parser independent. The logic for Xerces 2.1/Xerces 2.3 and others parser has been splitted into two new classes:
digester/parser/XercesParser digester/parser/GenericParser
The digester has been modified to call ParserFeatureSetterFactory, which will discover which parser is used (see the attached diff). I have tested with Xerces 2.1, Xerces 2.5 and Crimson (default with JDK 1.4). I also tested the code using Tomcat 5.
Let me know what you think. Once we all agree I will commit it.
Thanks,
-- Jeanfrancois
/* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. 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 following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgement may appear in the software itself, * if and wherever such third-party acknowledgements normally appear. * * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * "Apache" nor may "Apache" appear in their names without prior * written permission of the Apache Software Foundation. * * 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 APACHE SOFTWARE FOUNDATION OR * ITS 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 Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */
package org.apache.commons.digester.parser;
import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
/**
* Create a <code>SAXParser</code> configured to support XML Schema and DTD.
*
* @author Jean-Francois Arcand
*/
public class GenericParser{
/**
* The Log to which all SAX event related logging calls will be made.
*/
protected static Log log =
LogFactory.getLog("org.apache.commons.digester.Digester.sax");
/**
* The JAXP 1.2 property required to set up the schema location.
*/
private static final String JAXP_SCHEMA_SOURCE =
"http://java.sun.com/xml/jaxp/properties/schemaSource";
/**
* The JAXP 1.2 property to set up the schemaLanguage used.
*/
protected static String JAXP_SCHEMA_LANGUAGE =
"http://java.sun.com/xml/jaxp/properties/schemaLanguage";
/**
* Create a <code>SAXParser</code> configured to support XML Scheman and DTD
* @param properties parser specific properties/features
* @return an XML Schema/DTD enabled <code>SAXParser</code>
*/
public static SAXParser newSAXParser(Properties properties)
throws ParserConfigurationException,
SAXException,
SAXNotRecognizedException{
SAXParserFactory factory =
(SAXParserFactory)properties.get("SAXParserFactory");
SAXParser parser = factory.newSAXParser();
String schemaLocation = (String)properties.get("schemaLocation");
String schemaLanguage = (String)properties.get("schemaLanguage");
try{
if (schemaLocation != null) {
parser.setProperty(JAXP_SCHEMA_LANGUAGE, schemaLanguage);
parser.setProperty(JAXP_SCHEMA_SOURCE, schemaLocation);
}
} catch (SAXNotRecognizedException e){
log.info(parser.getClass().getName() + ": "
+ e.getMessage() + " not supported.");
}
return parser;
}
}
/* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. 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 following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgement may appear in the software itself, * if and wherever such third-party acknowledgements normally appear. * * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * "Apache" nor may "Apache" appear in their names without prior * written permission of the Apache Software Foundation. * * 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 APACHE SOFTWARE FOUNDATION OR * ITS 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 Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.digester.parser; import java.lang.reflect.Method; import java.util.Properties; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; /** * Create a <code>SAXParser</code> based on the underlying Xerces version. * Currently, Xerces 2.3 and up doesn't implement schema validation the same way * 2.1 was. In other to support schema validation in a portable way between * parser, some features/properties need to be set. * * @author Jean-Francois Arcand */ public class XercesParser{ /** * The Log to which all SAX event related logging calls will be made. */ protected static Log log = LogFactory.getLog("org.apache.commons.digester.Digester.sax"); /** * The JAXP 1.2 property required to set up the schema location. */ private static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; /** * The JAXP 1.2 property to set up the schemaLanguage used. */ protected static String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage"; /** * Xerces dynamic validation property */ protected static String XERCES_DYNAMIC = "http://apache.org/xml/features/validation/dynamic"; /** * Xerces schema validation property */ protected static String XERCES_SCHEMA = "http://apache.org/xml/features/validation/schema"; /** * A <code>float</code> representing the underlying Xerces version */ protected static float version; /** * The current Xerces version. */ protected static String versionNumber = null; /** * Return the current Xerces version. * @return the current Xerces version. */ private static String getXercesVersion() { // If for some reason we can't get the version, set it to 1.0. String versionNumber = "1.0"; try{ // Use reflection to avoid a build dependency with Xerces. Class versionClass = Class.forName("org.apache.xerces.impl.Version"); // Will return Xerces-J 2.x.0 Method method = versionClass.getMethod("getVersion", null); String version = (String)method.invoke(null,null); versionNumber = version.substring( "Xerces-J".length() , version.lastIndexOf(".") ); } catch (Exception ex){ // Do nothing. } return versionNumber; } /** * Create a <code>SAXParser</code> based on the underlying * <code>Xerces</code> version. * @param properties parser specific properties/features * @return an XML Schema/DTD enabled <code>SAXParser</code> */ public static SAXParser newSAXParser(Properties properties) throws ParserConfigurationException, SAXException, SAXNotSupportedException { SAXParserFactory factory = (SAXParserFactory)properties.get("SAXParserFactory"); if (versionNumber == null){ versionNumber = getXercesVersion(); version = new Float( versionNumber ).floatValue(); } // Note: 2.2 is completely broken (with XML Schema). if (version > 2.1) { configureXerces(factory); return factory.newSAXParser(); } else { SAXParser parser = factory.newSAXParser(); configureOldXerces(parser,properties); return parser; } } /** * Configure schema validation as recommended by the JAXP 1.2 spec. * The <code>properties</code> object may contains information about * the schema local and language. * @param properties parser optional info */ private static void configureOldXerces(SAXParser parser, Properties properties) throws ParserConfigurationException, SAXNotSupportedException { String schemaLocation = (String)properties.get("schemaLocation"); String schemaLanguage = (String)properties.get("schemaLanguage"); try{ if (schemaLocation != null) { parser.setProperty(JAXP_SCHEMA_LANGUAGE, schemaLanguage); parser.setProperty(JAXP_SCHEMA_SOURCE, schemaLocation); } } catch (SAXNotRecognizedException e){ log.info(parser.getClass().getName() + ": " + e.getMessage() + " not supported."); } } /** * Configure schema validation as recommended by the Xerces spec. * Both DTD and Schema validation will be enabled simultaneously. * @param properties parser optional info */ private static void configureXerces(SAXParserFactory factory) throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException { factory.setFeature(XERCES_DYNAMIC, true); factory.setFeature(XERCES_SCHEMA, true); } }
/* * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 2001-2003 The Apache Software Foundation. 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 following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgement may appear in the software itself, * if and wherever such third-party acknowledgements normally appear. * * 4. The names "Apache", "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache", * "Apache" nor may "Apache" appear in their names without prior * written permission of the Apache Software Foundation. * * 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 APACHE SOFTWARE FOUNDATION OR * ITS 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 Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.digester; import java.lang.reflect.Method; import java.util.Properties; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.apache.commons.digester.parser.GenericParser; import org.apache.commons.digester.parser.XercesParser; import org.xml.sax.SAXException; import org.xml.sax.SAXNotRecognizedException; import org.xml.sax.SAXNotSupportedException; /** * Creates a <code>SAXParser</code> based on the underlying parser. * * @author Jean-Francois Arcand */ public class ParserFeatureSetterFactory{ /** * <code>true</code> is Xerces is used. */ private static boolean isXercesUsed; static { try{ // Use reflection to avoid a build dependency with Xerces. Class versionClass = Class.forName("org.apache.xerces.impl.Version"); isXercesUsed = true; } catch (Exception ex){ isXercesUsed = false; } } /** * Create a new <code>SAXParser</code> * @return a <code>SAXParser</code> configured based on the underlying * parser implementation. */ public static SAXParser newSAXParser(Properties properties) throws ParserConfigurationException, SAXException, SAXNotRecognizedException, SAXNotSupportedException { if (isXercesUsed){ return XercesParser.newSAXParser(properties); } else { return GenericParser.newSAXParser(properties); } } }
? ParserFeatureSetterFactory.java
? diff.txt
? parser
Index: Digester.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/digester/src/java/org/apache/commons/digester/Digester.java,v
retrieving revision 1.86
diff -u -r1.86 Digester.java
--- Digester.java 19 Nov 2003 21:05:19 -0000 1.86
+++ Digester.java 2 Dec 2003 22:49:07 -0000
@@ -74,6 +74,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Properties;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
@@ -113,8 +114,8 @@
* even from the same thread.</p>
*
* <p><strong>IMPLEMENTATION NOTE</strong> - A bug in Xerces 2.0.2 prevents
- * the support of XML schema. You need Xerces 2.1 or JAXP 1.2.1 to make
- * that class working with XML schema</p>
+ * the support of XML schema. You need Xerces 2.1/2.3 and up to make
+ * this class working with XML schema</p>
*
* @author Craig McClanahan
* @author Scott Sanders
@@ -224,19 +225,6 @@
*/
protected SAXParserFactory factory = null;
-
- /**
- * The JAXP 1.2 property required to set up the schema location.
- */
- private static final String JAXP_SCHEMA_SOURCE =
- "http://java.sun.com/xml/jaxp/properties/schemaSource";
-
- /**
- * The JAXP 1.2 property to set up the schemaLanguage used.
- */
- protected String JAXP_SCHEMA_LANGUAGE =
- "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
-
/**
* The Locator associated with our parser.
@@ -702,21 +690,21 @@
// Create a new parser
try {
- parser = getFactory().newSAXParser();
+ if (validating) {
+ Properties properties = new Properties();
+ properties.put("SAXParserFactory", getFactory());
+ if (schemaLocation != null) {
+ properties.put("schemaLocation", schemaLocation);
+ properties.put("schemaLanguage", schemaLanguage);
+ }
+ parser = ParserFeatureSetterFactory.newSAXParser(properties);
} else {
+ parser = getFactory().newSAXParser();
+ }
} catch (Exception e) {
log.error("Digester.getParser: ", e);
return (null);
}
- // Configure standard properties and return the new instance
- try {
- if (schemaLocation != null) {
- setProperty(JAXP_SCHEMA_LANGUAGE, schemaLanguage);
- setProperty(JAXP_SCHEMA_SOURCE, schemaLocation);
- }
- } catch (Exception e) {
- log.warn("" + e);
- }
return (parser);
}
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
