You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by pi...@apache.org on 2005/09/12 03:10:13 UTC

svn commit: r280229 [1/2] - in /cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon: components/validation/ components/validation/impl/ transformation/

Author: pier
Date: Sun Sep 11 18:09:57 2005
New Revision: 280229

URL: http://svn.apache.org/viewcvs?rev=280229&view=rev
Log:
Major overhaul of the validation API:
- rewrote contract for validation: now the Validator shields the inner workings of schemas / parsers / validators
- moved caching and automatic schema detection directly as extensions of the Validator
- modified Jing and Xerces implementation to work with the modified API
This should make life easier for people using validators. That said, this is currently UNTESTED.
I just want to commit those before (as I always do) I loose all my work.
Samples rewrite and testing will come tomorrow

Added:
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidationHandler.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidatorException.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractValidator.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingValidator.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidationHandler.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DraconianErrorHandler.java
Removed:
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AutomaticSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingSchemaParser.java
Modified:
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidator.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesGrammarParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/transformation/ValidatingTransformer.java

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java?rev=280229&r1=280228&r2=280229&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java Sun Sep 11 18:09:57 2005
@@ -16,16 +16,26 @@
 package org.apache.cocoon.components.validation;
 
 import org.apache.excalibur.source.SourceValidity;
-import org.xml.sax.ContentHandler;
 import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
 
 /**
- * <p>An interface defining a schema used for validation of XML documents.</p>
+ * <p>The {@link Schema} interface defines an abstraction of a schema usable to
+ * validate an XML document.</p>
+ *
+ * <p>This interface is not tied to any specific validation grammar language
+ * such as the <a href="http://www.w3.org/XML/Schema">W3C XML Shema</a> language
+ * or the <a href="http://www.relaxng.org/">RELAX-NG</a/> language.</p>
+ *
+ * <p>Selection and use of specific schema grammar languages is performed through
+ * the use of the {@link Validator} interface.</p>
  * 
- * <p>A schema, by itself, simply provide access to its {@link SourceValidity}
- * (if any, for caching), and is able to create instances of {@link ContentHandler}s
- * that will receive SAX Events and validate them.</p>
+ * <p>Once returned by the {@link SchemaParser#getSchema()}, a {@link Schema}
+ * instance must be able to validate a number of XML documents: each time a document
+ * needs to be validated, a new {@link ValidationHandler} can be obtained invoking the
+ * {@link #createValidator(ErrorHandler)} method. While validating an XML document,
+ * {@link SAXException}s should be thrown back to the caller only when the specified
+ * {@link ErrorHandler} is configured to do so.</p> 
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
@@ -34,46 +44,34 @@
     /**
      * <p>Return the {@link SourceValidity} associated with this {@link Schema}.</p>
      * 
-     * <p>If the current schema grammar allow inclusion of sub-schemas, the
-     * {@link SourceValidity} returned by this method <b>must</b> validate both the
-     * original schema URI <b>and</b> all its sub-schemas.</p>
+     * <p>If the schema represented by this instance was parsed from several sources
+     * (through the use of inclusions or referencing to external entities, for
+     * example) the {@link SourceValidity} returned by this method <b>must</b>
+     * consider all of them when the {@link SourceValidity#isValid()} or the
+     * {@link SourceValidity#isValid(SourceValidity)} methods are called.</p>
      * 
      * @return a {@link SourceValidity} instance or <b>null</b> if not known.
      */
     public SourceValidity getValidity();
 
     /**
-     * <p>Return a new {@link ContentHandler} instance that can be used to send SAX
-     * events to for proper validation.</p>
+     * <p>Return a new {@link ValidationHandler} instance that can be used to
+     * validate an XML document by sending SAX events to it.</p>
      *
-     * <p>By default, this method will create a {@link ContentHandler} failing on the
-     * first occurrence of an warning, error or fatal error . If this behavior is
-     * not suitable, use the {@link #newValidator(ErrorHandler)} method instead and
-     * specify an {@link ErrorHandler} suitable to your needs.</p>
-     *
-     * <p>Once used, the returned {@link ContentHandler} <b>can't</b> be reused.</p> 
-     * 
-     * @return a <b>non-null</b> {@link ContentHandler} instance.
-     * @throws SAXException if an error occurred creating the validation handler.
-     */
-    public ContentHandler newValidator()
-    throws SAXException;
-
-    /**
-     * <p>Return a new {@link ContentHandler} instance that can be used to send SAX
-     * events to for proper validation.</p>
-     * 
      * <p>The specified {@link ErrorHandler} will be notified of all warnings or
      * errors encountered validating the SAX events sent to the returned
-     * {@link ContentHandler}.</p>
-     * 
-     * <p>Once used, the returned {@link ContentHandler} <b>can not</b> be reused.</p> 
-     * 
-     * @param handler an {@link ErrorHandler} to notify of validation errors.
-     * @return a <b>non-null</b> {@link ContentHandler} instance.
+     * {@link ValidationHandler}, and <b>must not</b> be <b>null</b>.</p>
+     *
+     * <p>The returned {@link ValidationHandler} can be used to validate <b>only
+     * one</b> XML document. To validate more than one document, this method should
+     * be called once for each document to validate.</p>
+     *
+     * @param errorHandler an {@link ErrorHandler} to notify of validation errors.
+     * @return a <b>non-null</b> {@link ValidationHandler} instance.
+     * @throws NullPointerException if the {@link ErrorHandler} was <b>null</b>.
      * @throws SAXException if an error occurred creating the validation handler.
      */
-    public ContentHandler newValidator(ErrorHandler handler)
-    throws SAXException;
+    public ValidationHandler createValidator(ErrorHandler handler)
+    throws NullPointerException, SAXException;
 
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java?rev=280229&r1=280228&r2=280229&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java Sun Sep 11 18:09:57 2005
@@ -17,48 +17,45 @@
 
 import java.io.IOException;
 
-import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.excalibur.source.Source;
 import org.xml.sax.SAXException;
 
 /**
- * <p>A component parsing schemas usable for XML validation and returning them as
- * {@link Schema} instances.</p>
+ * <p>The {@link SchemaParser} interface defines the abstraction of a component able
+ * to parse sources and produce {@link Schema} instances suitable for validation of
+ * XML documents.</p>
  * 
- * <p>This interface does not imply any requirement in terms of the grammar used
- * to produce {@link Schema} instances. Normally multiple-grammar selection is
- * provided through the {@link Validator} class.</p>
+ * <p>A {@link SchemaParser} might be able to understand more than one grammar
+ * language at the same time. The list of all supported grammar languages must be
+ * returned by the {@link #getSupportedGrammars()} method.</p>
  * 
- * <p>The only requirement imposed by this interface is that the final class
- * implementing this interface must be {@link ThreadSafe}.</p>
- *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
-public interface SchemaParser extends ThreadSafe {
+public interface SchemaParser {
 
-    /** <p>Avalon Role name of this component.</p> */
+    /** <p>Avalon Role name of {@link SchemaParser} components.</p> */
     public static final String ROLE = SchemaParser.class.getName();
 
     /**
-     * <p>Parse the specified URI and return a {@link Schema}.</p>
+     * <p>Parse the specified {@link Source} and return a new {@link Schema}.</p>
      * 
-     * <p>Once parsed, the returned {@link Schema} can be used multiple time to
-     * validate documents by sending their SAX events to the handler returned by
-     * the {@link Schema#newValidator()}.</p>
-     * 
-     * @param uri the URI of the {@link Schema} to return.
+     * <p>The returned {@link Schema} must be able to validate multiple documents
+     * via multiple invocations of {@link Schema#createValidator(ErrorHandler)}.</p> 
+     *
+     * @param source the {@link Source} associated with the {@link Schema} to return.
      * @return a <b>non-null</b> {@link Schema} instance.
-     * @throws SAXException if an error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
      * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws IllegalArgumentException if the specified grammar type is not one
+     *                                  of the grammar types returned by the
+     *                                  {@link #getSupportedGrammars()} method.  
      */
-    public Schema getSchema(String uri)
-    throws SAXException, IOException;
+    public Schema getSchema(Source source, String grammar)
+    throws SAXException, IOException, IllegalArgumentException;
 
     /**
-     * <p>Return an array of {@link String}s containing all schema grammars
+     * <p>Return an array of {@link String}s containing all the grammar languages
      * supported by this {@link SchemaParser}.</p>
-     * 
-     * <p>All {@link String}s in the array returned by this method should be
-     * valid grammar names as defined in the {@link Validator} class.</p>
      *
      * @return a <b>non-null</b> array of {@link String}s.
      */

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidationHandler.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidationHandler.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidationHandler.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidationHandler.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,44 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation;
+
+import org.apache.excalibur.source.SourceValidity;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * <p>A {@link ValidationHandler} represents a {@link ContentHandler} validating
+ * SAX events according to a validation schema.</p>
+ * 
+ * <p>As the handler might be tied to one (or more) resources from where the original
+ * schema was read from, the {@link #getValidity()} method provides a way to verify
+ * whether the validation instruction are still valid or not.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public interface ValidationHandler extends ContentHandler, LexicalHandler {
+
+    /**
+     * <p>Return a {@link SourceValidity} instance associated with the original
+     * resources of the schema describing the validation instructions.</p>
+     *
+     * <p>As the handler might be tied to one (or more) resources from where the
+     * original schema was read from, the {@link #getValidity()} method provides a
+     * way to verify whether the validation instruction are still valid or not.</p>
+     */
+    public SourceValidity getValidity();
+
+}

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java?rev=280229&r1=280228&r2=280229&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java Sun Sep 11 18:09:57 2005
@@ -15,54 +15,236 @@
  */
 package org.apache.cocoon.components.validation;
 
-import org.apache.avalon.framework.service.ServiceSelector;
+import java.io.IOException;
+
+import org.apache.excalibur.source.Source;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
 
 /**
- * <p>The {@link Validator} interface defines a {@link ServiceSelector} selecting
- * between different {@link SchemaParser}.</p>
+ * <p>The {@link Validator} interface provides the abstraction of a component able
+ * to validate XML documents using schemas defined in different languages.</p>
+ * 
+ * <p>This is basically the main entry point of the validation API, allowing users
+ * to transparently access validators (in the form of {@link ValidationHandler}s
+ * receiving SAX events for the documents to be validated), in different grammar
+ * languages, using different implementations.</p>
+ * 
+ * <p>As more than one {@link SchemaParser} might be able to parse and create
+ * {@link Schema} instances for a particular grammar language, this interface
+ * defines a unique lookup method to allow selection of a particular
+ * {@link SchemaParser} implementation.</p>
  * 
- * <p>Selection can occur either normally, based on a component name specified in
- * the configuration files, or on the {@link SchemaParser#getSupportedGrammars()
- * supported grammars} of the configured {@link SchemaParser}s.</p>
+ * <p>Assuming that two different {@link SchemaParser}s called <code>first</code>
+ * and <code>second</code> are both able to understand the
+ * {@link #GRAMMAR_RELAX_NG RELAX NG} grammar (identified by the
+ * <code>http://relaxng.org/ns/structure/0.9</code> identifier) one could select
+ * between the two implementation using the following two strings:</p>
+ * 
+ * <ul>
+ *   <li><code>first:http://relaxng.org/ns/structure/0.9</code></li>
+ *   <li><code>second:http://relaxng.org/ns/structure/0.9</code></li>
+ * </ul>
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
-public interface Validator extends ServiceSelector {
+public interface Validator {
 
-    /** <p>Role name to use when this component is accessed via a selector.</p> */
+    /** <p>Avalon Role name of {@link Validator} components.</p> */
     public static final String ROLE = Validator.class.getName();
 
-    /** 
-     * <p>An grammar identifer specifying tht the {@link SchemaParser} can
-     * automatically detect the grammar while parsing.</p>
-     */
-    public static final String GRAMMAR_AUTOMATIC = "http://apache.org/cocoon/validation/grammars/automatic/1.0";
-
-    /** <p>The <a href="http://www.schematron.com/">ISO SCHEMATRON</a/> grammar identifer.</p> */
+    /** <p>The <a href="http://www.schematron.com/">ISO Schematron</a/> grammar identifer.</p> */
     public static final String GRAMMAR_ISO_SCHEMATRON = "http://purl.oclc.org/dsdl/schematron";
     /** <p>The <a href="http://www.relaxng.org/">RELAX NG</a/> grammar identifer.</p> */
     public static final String GRAMMAR_RELAX_NG = "http://relaxng.org/ns/structure/0.9";
-    /** <p>The <a href="http://www.xml.gr.jp/relax">RELAX CORE</a/> grammar identifer.</p> */
+    /** <p>The <a href="http://www.xml.gr.jp/relax">RELAX Core</a/> grammar identifer.</p> */
     public static final String GRAMMAR_RELAX_CORE = "http://www.xml.gr.jp/xmlns/relaxCore";
-    /** <p>The <a href="http://www.xml.gr.jp/relax">RELAX NAMESPACE</a/> grammar identifer.</p> */
+    /** <p>The <a href="http://www.xml.gr.jp/relax">RELAX Namespace</a/> grammar identifer.</p> */
     public static final String GRAMMAR_RELAX_NS = "http://www.xml.gr.jp/xmlns/relaxNamespace";
-    /** <p>The <a href="http://xml.ascc.net/schematron/">SCHEMATRON</a/> grammar identifer.</p> */
+    /** <p>The <a href="http://xml.ascc.net/schematron/">Schematron</a/> grammar identifer.</p> */
     public static final String GRAMMAR_SCHEMATRON = "http://www.ascc.net/xml/schematron";
-    /** <p>The <a href="http://www.thaiopensource.com/trex/">TREX</a/> grammar identifer.</p> */
+    /** <p>The <a href="http://www.thaiopensource.com/trex/">Trex</a/> grammar identifer.</p> */
     public static final String GRAMMAR_TREX = "http://www.thaiopensource.com/trex";
-    /** <p>The <a href="http://www.w3.org/XML/Schema">XML SCHEMA</a/> grammar identifer.</p> */
+    /** <p>The <a href="http://www.w3.org/XML/Schema">XML Schema</a/> grammar identifer.</p> */
     public static final String GRAMMAR_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
     /** <p>The <a href="http://www.w3.org/TR/REC-xml">XML DTD</a/> grammar identifer.</p> */
     public static final String GRAMMAR_XML_DTD = "http://www.w3.org/XML/1998/namespace";
-    
-    /** <p>The list of all known grammars excluding {@link #GRAMMAR_AUTOMATIC}.</p> */
-    public static final String GRAMMARS[] = new String[] { GRAMMAR_ISO_SCHEMATRON,
-                                                           GRAMMAR_RELAX_NG,
-                                                           GRAMMAR_RELAX_CORE,
-                                                           GRAMMAR_RELAX_NS,
-                                                           GRAMMAR_SCHEMATRON,
-                                                           GRAMMAR_TREX,
-                                                           GRAMMAR_XML_SCHEMA,
-                                                           GRAMMAR_XML_DTD };
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, and each error or warning occurring while
+     * validating the document will trigger a {@link SAXException} to be thrown back
+     * to the caller.</p> 
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each error or warning occurring while validating the document will trigger
+     * a {@link SAXException} to be thrown back to the caller.</p> 
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @param grammar the grammar language of the schema to parse.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri, String grammar)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, while each validation error or warning will
+     * be passed to the specified {@link ErrorHandler} which will have the ability
+     * to generate and throw a {@link SAXException} back to the caller.</p>
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri, ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each validation error or warning will be passed to the specified
+     * {@link ErrorHandler} which will have the ability to generate and throw a
+     * {@link SAXException} back to the caller.</p>
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @param grammar the grammar language of the schema to parse.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri, String grammar,
+                                               ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, and each error or warning occurring while
+     * validating the document will trigger a {@link SAXException} to be thrown back
+     * to the caller.</p> 
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each error or warning occurring while validating the document will trigger
+     * a {@link SAXException} to be thrown back to the caller.</p> 
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @param grammar the grammar language of the schema to parse.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source, String grammar)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, while each validation error or warning will
+     * be passed to the specified {@link ErrorHandler} which will have the ability
+     * to generate and throw a {@link SAXException} back to the caller.</p>
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source,
+                                                  ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException;
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each validation error or warning will be passed to the specified
+     * {@link ErrorHandler} which will have the ability to generate and throw a
+     * {@link SAXException} back to the caller.</p>
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @param grammar the grammar language of the schema to parse.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source, String grammar,
+                                               ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException;
 
 }

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidatorException.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidatorException.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidatorException.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/ValidatorException.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation;
+
+import org.xml.sax.SAXException;
+
+/**
+ * <p>An exception representing that a {@link Validator} was not able to detect
+ * or did not support a specified schema grammar language.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class ValidatorException extends SAXException {
+
+    /**
+     * <p>Create a new {@link ValidatorException} instance.</p>
+     */
+    public ValidatorException(String message) {
+        super(message);
+    }
+
+    /**
+     * <p>Create a new {@link ValidatorException} instance.</p>
+     */
+    public ValidatorException(String message, Exception exception) {
+        super(message, exception);
+        this.initCause(exception);
+    }
+
+}

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java?rev=280229&r1=280228&r2=280229&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java Sun Sep 11 18:09:57 2005
@@ -17,10 +17,6 @@
 
 import org.apache.cocoon.components.validation.Schema;
 import org.apache.excalibur.source.SourceValidity;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 
 /**
  * <p>A simple implementation of the {@link Schema} interface.</p>
@@ -46,35 +42,5 @@
      */
     public SourceValidity getValidity() {
         return this.validity;
-    }
-
-    /**
-     * <p>Return a new {@link ContentHandler} instance that can be used to send SAX
-     * events to for proper validation.</p>
-     *
-     * <p>By default, this method will create a {@link ContentHandler} failing on the
-     * first occurrence of an warning, error or fatal error . If this behavior is
-     * not suitable, use the {@link #newValidator(ErrorHandler)} method instead and
-     * specify an {@link ErrorHandler} suitable to your needs.</p>
-     *
-     * <p>Once used, the returned {@link ContentHandler} <b>can't</b> be reused.</p> 
-     * 
-     * @return a <b>non-null</b> {@link ContentHandler} instance.
-     * @throws SAXException if an error occurred creating the validation handler.
-     */
-    public ContentHandler newValidator()
-    throws SAXException {
-        ErrorHandler handler = new ErrorHandler() {
-            public void warning(SAXParseException e) throws SAXException {
-                throw e;
-            }
-            public void error(SAXParseException e) throws SAXException {
-                throw e;
-            }
-            public void fatalError(SAXParseException e) throws SAXException {
-                throw e;
-            }
-        };
-        return this.newValidator(handler);
     }
 }

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchemaParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchemaParser.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchemaParser.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchemaParser.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,74 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation.impl;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.components.validation.Schema;
+import org.apache.cocoon.components.validation.SchemaParser;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.xml.EntityResolver;
+
+/**
+ * <p>A {@link SchemaParser} caching {@link Schema} instance for multiple use.</p>
+ *
+ * <p>A {@link Schema} will be cached until its {@link SourceValidity} expires.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public abstract class AbstractSchemaParser extends AbstractLogEnabled
+implements Serviceable, Initializable, Disposable, SchemaParser {
+
+    /** <p>The {@link ServiceManager} configured for this instance.</p> */
+    protected ServiceManager serviceManager = null;
+    /** <p>The {@link SourceResolver} to resolve URIs into {@link Source}s.</p> */
+    protected SourceResolver sourceResolver = null;
+    /** <p>The {@link EntityResolver} resolving against catalogs of public IDs.</p> */
+    protected EntityResolver entityResolver = null;
+
+    /**
+     * <p>Contextualize this component specifying a {@link ServiceManager} instance.</p>
+     */
+    public void service(ServiceManager manager)
+    throws ServiceException {
+        this.serviceManager = manager;
+    }
+    
+    /**
+     * <p>Initialize this component instance.</p>
+     * 
+     * <p>A this point component resolution will happen.</p>
+     */
+    public void initialize()
+    throws Exception {
+        this.entityResolver = (EntityResolver) this.serviceManager.lookup(EntityResolver.ROLE);
+        this.sourceResolver = (SourceResolver) this.serviceManager.lookup(SourceResolver.ROLE);
+    }
+    
+    /**
+     * <p>Dispose this component instance.</p>
+     */
+    public void dispose() {
+        if (this.entityResolver != null) this.serviceManager.release(this.entityResolver);
+        if (this.sourceResolver != null) this.serviceManager.release(this.sourceResolver);
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractValidator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractValidator.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractValidator.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractValidator.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,479 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation.impl;
+
+import java.io.IOException;
+
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.cocoon.components.validation.Schema;
+import org.apache.cocoon.components.validation.SchemaParser;
+import org.apache.cocoon.components.validation.ValidationHandler;
+import org.apache.cocoon.components.validation.Validator;
+import org.apache.cocoon.components.validation.ValidatorException;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.xml.sax.NOPContentHandler;
+import org.apache.excalibur.xml.sax.SAXParser;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.xml.sax.Attributes;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * <p>The {@link AbstractValidator} provides a generic implementation of the methods
+ * specified by the {@link Validator} interface.</p>
+ * 
+ * <p>Final implementations must implement three component management methods
+ * {@link #lookupParserByGrammar(String)}, {@link #lookupParserByName(String)} and
+ * {@link #releaseParser(SchemaParser)}.</p>
+ * 
+ * <p>In addition to this, they might also override the default implementation of
+ * the {@link #getSchema(String, SchemaParser, String)} method, for example when
+ * caching {@link Schema} instances.</p>
+ * 
+ * <p>This implementation provides a simple grammar identification mechanism, which
+ * can be overridden by reimplementing the {@link #detectGrammar(Source)} method
+ * provided by this class.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public abstract class AbstractValidator
+implements Validator, Serviceable, Disposable {
+
+    /** <p>The configured {@link ServiceManager} instance.</p> */
+    protected ServiceManager manager = null;
+    /** <p>The configured {@link SourceResolver} instance.</p> */
+    protected SourceResolver resolver = null;
+
+    /**
+     * <p>Create a new {@link AbstractValidator} instance.</p>
+     */
+    public AbstractValidator() {
+        super();
+    }
+
+    /**
+     * <p>Specify the {@link ServiceManager} available to this instance.</p>
+     */
+    public void service(ServiceManager manager)
+    throws ServiceException {
+        this.manager = manager;
+        this.resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
+    }
+
+    /**
+     * <p>Dispose of this component instance.</p>
+     */
+    public void dispose() {
+        if (this.resolver != null) this.manager.release(this.resolver);
+    }
+
+    /* =========================================================================== */
+    /* IMPLEMENTATION OF THE VALIDATOR INTERFACE                                   */
+    /* =========================================================================== */
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, and each error or warning occurring while
+     * validating the document will trigger a {@link SAXException} to be thrown back
+     * to the caller.</p> 
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri)
+    throws IOException, SAXException, ValidatorException {
+        return this.getValidationHandler(uri, null, null);
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each error or warning occurring while validating the document will trigger
+     * a {@link SAXException} to be thrown back to the caller.</p> 
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @param grammar the grammar language of the schema to parse.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri, String grammar)
+    throws IOException, SAXException, ValidatorException {
+        return this.getValidationHandler(uri, grammar, null);
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, while each validation error or warning will
+     * be passed to the specified {@link ErrorHandler} which will have the ability
+     * to generate and throw a {@link SAXException} back to the caller.</p>
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri, ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException {
+        return this.getValidationHandler(uri, null, errorHandler);
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each validation error or warning will be passed to the specified
+     * {@link ErrorHandler} which will have the ability to generate and throw a
+     * {@link SAXException} back to the caller.</p>
+     *
+     * @param uri the location of the schema to use to validate the document.
+     * @param grammar the grammar language of the schema to parse.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(String uri, String grammar,
+                                               ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException {
+        if (uri == null) throw new IOException("Specified schema URI was null");
+        Source source = null;
+        try {
+            source = this.resolver.resolveURI(uri);
+            return this.getValidationHandler(source, grammar, errorHandler);
+        } finally {
+            if (source != null) this.resolver.release(source);
+        }
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, and each error or warning occurring while
+     * validating the document will trigger a {@link SAXException} to be thrown back
+     * to the caller.</p> 
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source)
+    throws IOException, SAXException, ValidatorException {
+        return this.getValidationHandler(source, null, null);
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each error or warning occurring while validating the document will trigger
+     * a {@link SAXException} to be thrown back to the caller.</p> 
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @param grammar the grammar language of the schema to parse.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source, String grammar)
+    throws IOException, SAXException, ValidatorException {
+        return this.getValidationHandler(source, grammar, null);
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>The {@link Validator} will attempt to automatically detect the grammar
+     * language of the specified schema, while each validation error or warning will
+     * be passed to the specified {@link ErrorHandler} which will have the ability
+     * to generate and throw a {@link SAXException} back to the caller.</p>
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the grammar language of the specified schema
+     *                            could not be detected or was not supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source,
+                                                  ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException {
+        return this.getValidationHandler(source, null, errorHandler);
+    }
+
+    /**
+     * <p>Return a {@link ValidationHandler} validating an XML document according to
+     * the schema found at the specified location.</p>
+     *
+     * <p>Each validation error or warning will be passed to the specified
+     * {@link ErrorHandler} which will have the ability to generate and throw a
+     * {@link SAXException} back to the caller.</p>
+     *
+     * @param source the {@link Source} identifying the schema to use for validation.
+     * @param grammar the grammar language of the schema to parse.
+     * @param errorHandler the {@link ErrorHandler} notified of validation problems.
+     * @return a <b>non null</b> {@link ValidationHandler} able to SAX events from
+     *         the original XML document to validate.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws ValidatorException if the specified grammar language wasn't supported.
+     * @link SchemaParser#getSchema(String, String)
+     * @link Schema#createValidator(ErrorHandler)
+     */
+    public ValidationHandler getValidationHandler(Source source, String grammar,
+                                               ErrorHandler errorHandler)
+    throws IOException, SAXException, ValidatorException {
+        if (errorHandler == null) errorHandler = DraconianErrorHandler.INSTANCE;
+
+        SchemaParser parser = null;
+        try {
+            /* If no grammar was supplied, try to detect one */
+            if (grammar == null) grammar = this.detectGrammar(source);
+
+            /* Save the grammar name and try to find a schema parser */
+            String language = grammar; 
+            parser = this.lookupParserByGrammar(grammar);
+
+            /*
+             * If the schema parser for the language was not found, we might have to
+             * look up for the form name:grammar as specified by Validator.
+             */
+            if (parser == null) {
+                int index = grammar.indexOf(':');
+                if (index > 0) {
+                    String name = grammar.substring(0, index);
+                    language = grammar.substring(index + 1);
+                    parser = this.lookupParserByName(name);
+                }
+            }
+
+            /* If still we didn't find any parser, simply die of natural death */
+            if (parser == null) {
+                String message = "Unsupported grammar language" + grammar;
+                throw new ValidatorException(message);
+            }
+
+            /* Somehow we have a schema parser, check it supports the gramar */
+            String languages[] = parser.getSupportedGrammars();
+            for (int x = 0; x < languages.length; x++) {
+                if (! language.equals(languages[x])) continue;
+                /* Hah! language supported, go ahead and parse now */
+                Schema schema = this.getSchema(parser, source, language);
+                return schema.createValidator(errorHandler);
+            }
+
+            /* Something really odd going on, this should never happen */
+            String message = "Schema parser " + parser.getClass().getName() +
+                             " does not support grammar " + grammar;
+            throw new ValidatorException(message);
+
+        } finally {
+            if (parser != null) this.releaseParser(parser);
+        }
+    }
+
+    /* =========================================================================== */
+    /* METHODS TO BE IMPLEMENTED BY THE EXTENDING CLASSES                          */
+    /* =========================================================================== */
+
+    /**
+     * <p>Attempt to acquire a {@link SchemaParser} interface able to understand
+     * the grammar language specified.</p>
+     * 
+     * @param grammar the grammar language that must be understood by the returned
+     *                {@link SchemaParser}
+     * @return a {@link SchemaParser} instance or <b>null</b> if none was found able
+     *         to understand the specified grammar language.
+     */
+    protected abstract SchemaParser lookupParserByGrammar(String grammar);
+
+    /**
+     * <p>Attempt to acquire a {@link SchemaParser} interface associated with the
+     * specified instance name.</p>
+     * 
+     * @param name the name associated with the {@link SchemaParser} to be returned.
+     * @return a {@link SchemaParser} instance or <b>null</b> if none was found.
+     */
+    protected abstract SchemaParser lookupParserByName(String name);
+
+    /**
+     * <p>Release a previously acquired {@link SchemaParser} instance back to its
+     * original component manager.</p>
+     * 
+     * <p>This method is supplied in case solid implementations of this class relied
+     * on the {@link ServiceManager} to manage {@link SchemaParser}s instances.</p>
+     * 
+     * @param parser the {@link SchemaParser} whose instance is to be released.
+     */
+    protected abstract void releaseParser(SchemaParser parser);
+    
+    /* =========================================================================== */
+    /* METHODS SPECIFIC TO ABSTRACTVALIDATOR OVERRIDABLE BY OTHER IMPLEMENTATIONS  */
+    /* =========================================================================== */
+
+    /**
+     * <p>Return a {@link Schema} instance from the specified {@link SchemaParser}
+     * associated with the given {@link Source} and grammar language.</p>
+     * 
+     * <p>This method simply implements resolution returning the {@link Schema}
+     * instance acquired calling <code>parser.getSchema(source,grammar)</code>.</p>
+     * 
+     * @param parser the {@link SchemaParser} producing the {@link Schema}.
+     * @param source the {@link Source} associated with the {@link Schema} to return.
+     * @param grammar the grammar language of the schema to produce.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     */
+    protected Schema getSchema(SchemaParser parser, Source source, String grammar)
+    throws IOException, SAXException {
+        try {
+            return parser.getSchema(source, grammar);
+        } catch (IllegalArgumentException exception) {
+            String message = "Schema parser " + parser.getClass().getName() +
+                             " does not support grammar " + grammar;
+            throw new ValidatorException(message, exception);
+        }
+    }
+
+    /**
+     * <p>Attempt to detect the grammar language used by the schema identified
+     * by the specified {@link Source}.</p>
+     * 
+     * @param source a {@link Source} instance pointing to the schema to be analyzed.
+     * @throws IOException if an I/O error occurred accessing the schema.
+     * @throws SAXException if an error occurred parsing the schema.
+     * @throws ValidatorException if the language of the schema could not be guessed.
+     */
+    protected String detectGrammar(Source source)
+    throws IOException, SAXException, ValidatorException {
+        SAXParser xmlParser = null;
+        String grammar = null;
+
+        try {
+            DetectionHandler handler = new DetectionHandler();
+            if (source instanceof XMLizable) {
+                XMLizable xmlizable = (XMLizable) source;
+                xmlizable.toSAX(handler);
+            } else {
+                xmlParser = (SAXParser) this.manager.lookup((SAXParser.ROLE)); 
+                InputSource input = new InputSource();
+                input.setSystemId(source.getURI());
+                input.setByteStream(source.getInputStream());
+                xmlParser.parse(input, handler);
+            }
+        } catch (ServiceException exception) {
+            throw new SAXException("Unable to access XML parser", exception);
+        } catch (DetectionException exception) {
+            grammar = exception.grammar;
+        } catch (SAXParseException exception) {
+            grammar = Validator.GRAMMAR_XML_DTD;
+        } finally {
+            if (xmlParser != null) this.manager.release(xmlParser);
+        }
+
+        if (("".equals(grammar)) || (grammar == null)) {
+            String message = "Unable to detect grammar for schema at ";
+            throw new ValidatorException(message + source.getURI());
+        } else {
+            return grammar;
+        }
+    }
+
+    /* =========================================================================== */
+    /* METHODS AND INNER CLASSES FOR AUTOMATIC GRAMMAR LANGUAGE DETECTION          */
+    /* =========================================================================== */
+
+    /**
+     * <p>A simple implementation of a {@link ValidationHandler} detecting schemas
+     * based on the namespace of the root element.</p>
+     */
+    private static final class DetectionHandler extends NOPContentHandler {
+        
+        /**
+         * <p>Detect the namespace of the root element and always throw a
+         * {@link SAXException} or a {@link DetectionException}.</p>
+         */
+        public void startElement(String ns, String lnam, String qnam, Attributes a)
+        throws SAXException {
+            throw new DetectionException(ns);
+        }
+    }
+
+    /**
+     * <p>An exception thrown by {@link DetectionHandler} representing that
+     * a grammar was successfully detected.</p>
+     */
+    private static final class DetectionException extends SAXException {
+
+        private final String grammar;
+
+        private DetectionException(String grammar) {
+            super ("Grammar detected: " + grammar);
+            this.grammar = grammar;
+        }
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingValidator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingValidator.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingValidator.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingValidator.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,186 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation.impl;
+
+import java.io.IOException;
+
+import org.apache.cocoon.components.validation.Schema;
+import org.apache.cocoon.components.validation.SchemaParser;
+import org.apache.cocoon.components.validation.ValidatorException;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.store.Store;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>An extension of the {@link DefaultValidator} class allowing {@link Schema}
+ * instances to be cached.</p>
+ * 
+ * <p>The {@link #getSchema(SchemaParser, String, String)} method will manage
+ * whether to return a cached or a freshly parsed {@link Schema} instance.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class CachingValidator extends DefaultValidator {
+
+    /** <p>The {@link Store} used for caching {@link Schema}s (if enabled).</p> */
+    private Store store = null;
+
+    /**
+     * <p>Initialize this component instance.</p>
+     */
+    public void initialize()
+    throws Exception {
+        this.store = (Store) this.manager.lookup(Store.TRANSIENT_STORE);
+        super.initialize();
+    }
+    
+    /**
+     * <p>Dispose this component instance.</p>
+     */
+    public void dispose() {
+        try {
+            super.dispose();
+        } finally {
+            if (this.store != null) this.manager.release(this.store);
+        }
+    }
+
+    /**
+     * <p>Return a {@link Schema} instance from the specified {@link SchemaParser}
+     * associated with the given {@link Source} and grammar language.</p>
+     * 
+     * <p>This method will overriding the default behaviour specified by the
+     * {@link AbstractValidator#getSchema(SchemaParser, Source, String)} method,
+     * and supports cacheability of {@link Schema} instances through the use of
+     * a {@link Store} looked up using the {@link Store#TRANSIENT_STORE} Avalon
+     * role.</p>
+     * 
+     * <p>Cached {@link Schema} instances will be retained in the configured
+     * {@link Store} until the checks on the validity obtained calling the
+     * {@link Schema#getValidity()} method will declare that the schema is still
+     * valid.</p>
+     * 
+     * @param parser the {@link SchemaParser} producing the {@link Schema}.
+     * @param source the {@link Source} associated with the {@link Schema} to return.
+     * @param grammar the grammar language of the schema to produce.
+     * @throws SAXException if a grammar error occurred parsing the schema.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     */
+    public Schema getSchema(SchemaParser parser, Source source, String grammar)
+    throws IOException, SAXException {
+
+        /* Prepare a key, and try to get the cached copy of the schema */
+        String uri = source.getURI();
+        String key = this.getClass().getName() + "[" + parser.getClass().getName()
+                     + ":" + grammar + "]@" + source.getURI();
+        Schema schema = null;
+        SourceValidity validity = null;
+        schema = (Schema) this.store.get(key);
+
+        /* If the schema was found verify its validity and optionally clear */
+        if (schema != null) {
+            validity = schema.getValidity();
+            if (validity == null) {
+                /* Why did we cache it in the first place? */
+                this.logger.warn("Cached schema " + uri + " has null validity");
+                this.store.remove(key);
+                schema = null;
+            } else if (validity.isValid() != SourceValidity.VALID) {
+                this.store.remove(key);
+                schema = null;
+            }
+        }
+
+        /* If the schema was not cached or was cleared, parse and cache it */
+        if (schema == null) {
+            this.logger.debug("Parsing schema \"" + uri + "\"");
+            schema = super.getSchema(parser, source, grammar);
+            validity = schema.getValidity();
+            if (validity != null) {
+                if (validity.isValid() == SourceValidity.VALID) {
+                    this.store.store(key, schema);
+                }
+            }
+        }
+
+        /* Return the parsed or cached schema */
+        return schema;
+    }    
+
+    /**
+     * <p>Attempt to detect the grammar language used by the schema identified
+     * by the specified {@link Source}.</p>
+     * 
+     * <p>The grammar languages detected will be cached until the {@link Source}'s
+     * {@link SourceValidity} declares that the schema is valid.</p>
+     * 
+     * @param source a {@link Source} instance pointing to the schema to be analyzed.
+     * @throws IOException if an I/O error occurred accessing the schema.
+     * @throws SAXException if an error occurred parsing the schema.
+     * @throws ValidatorException if the language of the schema could not be guessed.
+     */
+    protected String detectGrammar(Source source)
+    throws IOException, SAXException, ValidatorException {
+        /* Prepare a key, and try to get the cached copy of the schema */
+        String uri = source.getURI();
+        String key = this.getClass().getName() + "@" + source.getURI();
+
+        CachedGrammar grammar = null;
+        grammar = (CachedGrammar) this.store.get(key);
+
+        /* If the schema was found verify its validity and optionally clear */
+        if (grammar != null) {
+            if (grammar.validity == null) {
+                /* Why did we cache it in the first place? */
+                this.logger.warn("Cached grammar " + uri + " has null validity");
+                this.store.remove(key);
+                grammar = null;
+            } else if (grammar.validity.isValid() != SourceValidity.VALID) {
+                this.store.remove(key);
+                grammar = null;
+            }
+        }
+
+        /* If the schema was not cached or was cleared, parse and cache it */
+        if (grammar != null) {
+            return grammar.grammar;
+        } else {
+            this.logger.debug("Detecting grammar for schema \"" + uri + "\"");
+            String language = super.detectGrammar(source);
+            SourceValidity validity = source.getValidity();
+            if (validity != null) {
+                if (validity.isValid() == SourceValidity.VALID) {
+                    this.store.store(key, new CachedGrammar(validity, language));
+                }
+            }
+            return language;
+        }
+    }
+    
+    /**
+     * <p>A simple inner class associating grammar languages and source validity
+     * for caching of schema grammar detection.</p>
+     */
+    private static final class CachedGrammar {
+        private final SourceValidity validity;
+        private final String grammar;
+        private CachedGrammar(SourceValidity validity, String grammar) {
+            this.validity = validity;
+            this.grammar = grammar;
+        }
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidationHandler.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidationHandler.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidationHandler.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidationHandler.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,67 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation.impl;
+
+import org.apache.cocoon.components.validation.ValidationHandler;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.xml.sax.NOPContentHandler;
+import org.apache.excalibur.xml.sax.NOPLexicalHandler;
+import org.apache.excalibur.xml.sax.XMLConsumerProxy;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * <p>The default implementation of the {@link ValidationHandler} interface.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class DefaultValidationHandler extends XMLConsumerProxy
+implements ValidationHandler {
+
+    /** <p>The {@link SourceValidity} associated with the schema.</p> */
+    private final SourceValidity validity;
+
+    /**
+     * <p>Create a new {@link DefaultValidationHandler} instance.</p>
+     */
+    public DefaultValidationHandler(SourceValidity validity,
+                                    ContentHandler handler) {
+        this(validity, handler, null);
+    }
+
+    /**
+     * <p>Create a new {@link DefaultValidationHandler} instance.</p>
+     */
+    public DefaultValidationHandler(SourceValidity validity,
+                                    ContentHandler contentHandler,
+                                    LexicalHandler lexicalHandler) {
+        super(contentHandler == null? new NOPContentHandler(): contentHandler,
+              lexicalHandler == null? new NOPLexicalHandler(): lexicalHandler);
+        this.validity = validity;
+    }
+
+    /**
+     * <p>Return a {@link SourceValidity} instance associated with the original
+     * resources of the schema describing the validation instructions.</p>
+     *
+     * <p>As the handler might be tied to one (or more) resources from where the
+     * original schema was read from, the {@link #getValidity()} method provides a
+     * way to verify whether the validation instruction are still valid or not.</p>
+     */
+    public SourceValidity getValidity() {
+        return this.validity;
+    }
+}