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 [2/2] - in /cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon: components/validation/ components/validation/impl/ transformation/

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidator.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/DefaultValidator.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DefaultValidator.java Sun Sep 11 18:09:57 2005
@@ -17,10 +17,8 @@
 
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
@@ -37,39 +35,38 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.components.validation.SchemaParser;
 import org.apache.cocoon.components.validation.Validator;
 
 /**
- * <p>The default implementation of the {@link Validator} interface.</p>
+ * <p>The default implementation of the {@link Validator} interface provides
+ * core management for a number of {@link SchemaParser} instances.</p>
+ * 
+ * <p>Given the simplicity of this implementation, only {@link SchemaParser}s
+ * implementing the {@link ThreadSafe} interface can be managed, and they can be
+ * accessed directly (via its name) through the methods specified by the
+ * {@link ServiceSelector} interface.</p>
+ *
+ * <p>That said, normally selection would occur using the methods declared by the
+ * {@link AbstractValidator} class and implemented here.</p>
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
-public class DefaultValidator implements Validator, LogEnabled, ThreadSafe,
-Contextualizable, Serviceable, Configurable, Initializable, Disposable {
-    
-    /** <p>The default shorthand code to use in subcomponent configurations.</p> */
-    public static final String DEFAULT_SHORTHAND = "schema-parser";
-    /** <p>The default subcomponent {@link Class} instance.</p> */
-    public static final Class DEFAULT_CLASS = SchemaParser.class;
-
-    /** <p>The shorthand code to use in subcomponents configurations.</p> */
-    private final String shorthand;
-    /** <p>The {@link Class} of the subcomponents selected by this instance.</p> */
-    private final Class componentClass;
-    /** <p>The {@link Set} of all instantiated components.</p> */
-    private final Set components;
-    /** <p>A {@link Map} associating names with component instances.</p> */
-    private final Map selections;
+public class DefaultValidator extends AbstractValidator implements LogEnabled,
+ThreadSafe, Contextualizable, Initializable, Disposable, ServiceSelector {
+
+    /** <p>A {@link Map} associating {@link SchemaParser}s with their names.</p> */
+    private final Map componentx = Collections.synchronizedMap(new HashMap());
+    /** <p>A {@link Map} associating component names with grammars.</p> */
+    private final Map grammars = Collections.synchronizedMap(new HashMap());
 
     /** <p>The configured {@link Logger} instance.</p> */
-    private Logger logger = null;
+    protected Logger logger = null;
     /** <p>The configured {@link Context} instance.</p> */
     private Context context = null;
-    /** <p>The configured {@link ServiceManager} instance.</p> */
-    private ServiceManager manager = null;
     /** <p>The configured {@link Configuration} instance.</p> */
     private Configuration conf = null;
 
@@ -77,20 +74,7 @@
      * <p>Create a new {@link DefaultValidator} instance.</p>
      */
     public DefaultValidator() {
-        this(null, null);
-    }
-
-    /**
-     * <p>Create a new {@link DefaultValidator} instance.</p>
-     *
-     * @param shorthand the shorthand code to use in subcomponents configurations.
-     * @param componentClass the {@link Class} of the subcomponents selected by this.
-     */
-    public DefaultValidator(String shorthand, Class componentClass) {
-        this.shorthand = shorthand == null? DEFAULT_SHORTHAND: shorthand;
-        this.componentClass = componentClass == null? DEFAULT_CLASS: componentClass;
-        this.components = Collections.synchronizedSet(new HashSet());
-        this.selections = Collections.synchronizedMap(new HashMap());
+        super();
     }
 
     /**
@@ -109,14 +93,6 @@
     }
 
     /**
-     * <p>Specify the {@link ServiceManager} available to this instance.</p>
-     */
-    public void service(ServiceManager manager)
-    throws ServiceException {
-        this.manager = manager;
-    }
-
-    /**
      * <p>Configure this instance.</p>
      */
     public void configure(Configuration conf)
@@ -126,9 +102,6 @@
 
     /**
      * <p>Initialize this instance.</p>
-     * 
-     * <p>Required components lookup and sub-components initialization will occur
-     * when this method is called.</p>
      */
     public void initialize()
     throws Exception {
@@ -138,64 +111,90 @@
         if (this.context == null) throw new IllegalStateException("Null context");
         if (this.manager == null) throw new IllegalStateException("Null manager");
         if (this.conf == null) throw new IllegalStateException("Null configuration");
-        
-        Configuration configurations[] = this.conf.getChildren(this.shorthand);
+
+        Configuration configurations[] = this.conf.getChildren("schema-parser");
         this.logger.debug("Configuring " + configurations.length + " schema parsers"
                           + " from " + this.conf.getLocation());
+
+        /* Iterate through all the sub-confiuration instances */
         for (int x = 0; x < configurations.length; x++) try {
-            Configuration configuration = configurations[x];
-            String className = configuration.getAttribute("class");
-            String selectionKey = configuration.getAttribute("name");
+            final Configuration configuration = configurations[x];
+            final String className = configuration.getAttribute("class");
+            final String selectionKey = configuration.getAttribute("name");
+            
+            /* Check that we don't have a duplicate schema parser name in configs */
+            if (this.componentx.containsKey(selectionKey)) {
+                String message = "Duplicate schema parser \"" + selectionKey + "\"";
+                throw new ConfigurationException(message, configuration);
+            }
+
+            /* Dump some debugging information, just in case */
             this.logger.debug("Configuring schema parser " + selectionKey + " as "
                               + className + " from " + configuration.getLocation());
 
-            Class clazz;
+            /* Try to load and instantiate the SchemaParser */
+            final SchemaParser schemaParser;
             try {
-                clazz = Class.forName(className);
-            } catch (Exception exception) {
-                String message = "Unable to load class " + className;
-                throw new ConfigurationException(message, configuration, exception);
-            }
+                /* Load the class */
+                final Class clazz = Class.forName(className);
 
-            if (!this.componentClass.isAssignableFrom(clazz)) {
-                String message = "Class " + className + " does not represent a "
-                                 + this.componentClass.getName();
-                throw new ConfigurationException(message, configuration);
-            }
+                /* ClassCastExceptions normally don't come with messages (darn) */
+                if (! SchemaParser.class.isAssignableFrom(clazz)) {
+                    String message = "Class " + className + " doesn't implement the "
+                                     + SchemaParser.class.getName() + " interface";
+                    throw new ConfigurationException(message, configuration);
+                }
 
-            Object component;
-            try {
-                component = clazz.newInstance();
+                /* We only support ThreadSafe SchemaParser instances */
+                if (! ThreadSafe.class.isAssignableFrom(clazz)) {
+                    String message = "Class " + className + " doesn't implement the "
+                                     + ThreadSafe.class.getName() + " interface";
+                    throw new ConfigurationException(message, configuration);
+                }
+
+                /* Instantiate and set up the new SchemaParser */
+                schemaParser = (SchemaParser) clazz.newInstance();
+                this.setupComponent(schemaParser, configuration);
+
+            } catch (ConfigurationException exception) {
+                throw exception;
             } catch (Exception exception) {
                 String message = "Unable to instantiate SchemaParser " + className;
                 throw new ConfigurationException(message, configuration, exception);
             }
 
-            this.components.add(this.setupComponent(component, configuration));
-            this.selections.put(selectionKey, component);
-            this.logger.debug("SchemaParser " + selectionKey + " class" + className);
-            if (component instanceof SchemaParser) {
-                SchemaParser parser = (SchemaParser) component;
-                String grammars[] = parser.getSupportedGrammars();
-                if (grammars != null) {
-                    for (int k = 0; k < grammars.length; k++) {
-                        if (this.selections.containsKey(grammars[k])) continue;
-                        this.selections.put(grammars[k], component);
-                        this.logger.debug("SchemaParser " + selectionKey +
-                                          "provides grammar " + grammars[k]);
-                    }
-                }
+            /* Store this instance (and report about it) */
+            this.componentx.put(selectionKey, schemaParser);
+            this.logger.debug("SchemaParser \"" + selectionKey + "\" instantiated" +
+                              " from class " + className);
+
+            /* Analyze the grammars provided by the current SchemaParser */
+            String grammars[] = schemaParser.getSupportedGrammars();
+            if (grammars == null) continue;
+
+            /* Iterate through the grammars and store them (default lookup) */
+            for (int k = 0; k < grammars.length; k++) {
+                if (this.grammars.containsKey(grammars[k])) continue;
+
+                /* Noone yet supports this grammar, make this the default */
+                this.grammars.put(grammars[k], selectionKey);
+                this.logger.debug("SchemaParser \"" + selectionKey + "\" is the " +
+                                  "default grammar provider for " + grammars[k]);
             }
+
         } catch (Exception exception) {
+            /* Darn, we had an exception instantiating one of the components */
             this.logger.warn("Exception creating schema parsers", exception);
 
-            Iterator iterator = this.components.iterator();
+            /* Dispose all previously stored component instances */
+            Iterator iterator = this.componentx.values().iterator();
             while (iterator.hasNext()) try {
                 this.decommissionComponent(iterator.next());
             } catch (Exception nested) {
                 this.logger.fatalError("Error decommissioning component", nested);
             }
 
+            /* Depending on the exception type, re-throw it or wrap it */
             if (exception instanceof ConfigurationException) {
                 throw exception;
             } else {
@@ -205,48 +204,113 @@
                 throw new ConfigurationException(message, configuration, exception);
             }
         }
-        this.logger.debug("Configured successfully");
     }
 
     /**
-     * <p>Select the subcomponent managed by this instance associated wit the
-     * specified key.</p>
+     * <p>Dispose of this instance.</p>
+     * 
+     * <p>All sub-components initialized previously will be disposed of when this
+     * method is called.</p>
      */
-    public Object select(Object key)
-    throws ServiceException {
-        if (this.isSelectable(key)) return this.selections.get(key);
-        throw new ServiceException((String) key, "Schema parser not configured");
+    public void dispose() {
+        Iterator iterator = this.componentx.values().iterator();
+        while (iterator.hasNext()) try {
+            this.decommissionComponent(iterator.next());
+        } catch (Exception exception) {
+            this.logger.fatalError("Error decommissioning component", exception);
+        }
     }
 
+    /* =========================================================================== */
+    /* IMPLEMENTATION OF METHODS SPECIFIED BY THE ABSTRACTVALIDATOR CLASS          */
+    /* =========================================================================== */
+
     /**
-     * <p>Ensure that a subcomponent is selectable for the specified key.</p>
-     */
-    public boolean isSelectable(Object key) {
-        return this.selections.containsKey((String) key);
+     * <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 SchemaParser lookupParserByGrammar(String grammar) {
+        if (this.grammars.containsKey(grammar)) {
+            return this.lookupParserByName((String) this.grammars.get(grammar));
+        }
+        return null;
     }
 
     /**
-     * <p>Release a previously selected subcomponent instance.</p>
+     * <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.
      */
-    public void release(Object object) {
-        // Nothing to do over here...
+    protected SchemaParser lookupParserByName(String name) {
+        if (this.isSelectable(name)) try {
+            return (SchemaParser) this.select(name);
+        } catch (ServiceException exception) {
+            return null;
+        }
+        return null;
     }
 
     /**
-     * <p>Dispose of this instance.</p>
+     * <p>Release a previously acquired {@link SchemaParser} instance back to its
+     * original component manager.</p>
      * 
-     * <p>All sub-components initialized previously will be disposed of when this
-     * method is called.</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.
      */
-    public void dispose() {
-        Iterator iterator = this.components.iterator();
-        while (iterator.hasNext()) try {
-            this.decommissionComponent(iterator.next());
-        } catch (Exception exception) {
-            this.logger.fatalError("Error decommissioning component", exception);
+    protected void releaseParser(SchemaParser parser) {
+        this.release(parser);
+    }
+
+    /* =========================================================================== */
+    /* IMPLEMENTATION OF THE METHODS SPECIFIED BY THE SERVICESELECTOR INTERFACE    */
+    /* =========================================================================== */
+
+    /**
+     * <p>Select a subcomponent ({@link SchemaParser}) associated with the specified
+     * selection key (its configured &quot;name&quot;).</p>
+     */
+    public Object select(Object selectionKey)
+    throws ServiceException {
+        /* Look up for the specified component and return it if found */
+        if ( this.componentx.containsKey(selectionKey)) {
+            return this.componentx.get(selectionKey);
         }
+
+        /* Fail miserably */
+        String message = "No component associated with " + selectionKey;
+        throw new ServiceException((String) selectionKey, message);
+    }
+
+    /**
+     * <p>Check whether a subcomponent ({@link SchemaParser}) associated with the
+     * specified selection key (its configured &quot;name&quot;) is selectable in
+     * this {@link ServiceSelector} instance.</p>
+     */
+    public boolean isSelectable(Object selectionKey) {
+        return this.componentx.containsKey(selectionKey);
     }
-    
+
+    /**
+     * <p>Release a subcomponent ({@link SchemaParser}) instance previously selected
+     * from this {@link ServiceSelector} instance.</p>
+     */
+    public void release(Object component) {
+        // We don't need to do anything  in this method.
+    }
+
+    /* =========================================================================== */
+    /* SUBCOMPONENTS (SCHEMA PARSERS) LIFECYCLE MANAGEMENT METHODS                 */
+    /* =========================================================================== */
+
     /**
      * <p>Manage the instantiation lifecycle of a specified component.</p>
      */

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DraconianErrorHandler.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DraconianErrorHandler.java?rev=280229&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DraconianErrorHandler.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/DraconianErrorHandler.java Sun Sep 11 18:09:57 2005
@@ -0,0 +1,59 @@
+/*
+ * 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.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * <p>An implementation of the {@link ErrorHandler} interface re-throwing
+ * all exceptions passed to it.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public final class DraconianErrorHandler implements ErrorHandler {
+    
+    /** <p>The singleton instance of the {@link DraconianErrorHandler}.</p> */
+    public static final DraconianErrorHandler INSTANCE = new DraconianErrorHandler();
+
+    /** <p>Deny normal construction of instances of this class.</p> */
+    private DraconianErrorHandler() { }
+
+    /**
+     * <p>Simply re-throw the specified {@link SAXParseException}.</p>
+     */
+    public void warning(SAXParseException exception)
+    throws SAXException {
+        throw exception;
+    }
+
+    /**
+     * <p>Simply re-throw the specified {@link SAXParseException}.</p>
+     */
+    public void error(SAXParseException exception)
+    throws SAXException {
+        throw exception;
+    }
+
+    /**
+     * <p>Simply re-throw the specified {@link SAXParseException}.</p>
+     */
+    public void fatalError(SAXParseException exception)
+    throws SAXException {
+        throw exception;
+    }
+}

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.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/JingSchema.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.java Sun Sep 11 18:09:57 2005
@@ -15,7 +15,7 @@
  */
 package org.apache.cocoon.components.validation.impl;
 
-import org.apache.cocoon.components.validation.Schema;
+import org.apache.cocoon.components.validation.ValidationHandler;
 import org.apache.excalibur.source.SourceValidity;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.ErrorHandler;
@@ -23,18 +23,21 @@
 
 import com.thaiopensource.util.PropertyMap;
 import com.thaiopensource.util.PropertyMapBuilder;
+import com.thaiopensource.validate.Schema;
 import com.thaiopensource.validate.ValidateProperty;
 import com.thaiopensource.validate.Validator;
 import com.thaiopensource.xml.sax.DraconianErrorHandler;
 
 /**
- * <p>The implementation of the {@link Schema} implementation from the
- * {@link JingSchemaParser} component.</p>
+ * <p>An extension of {@link AbstractSchema} used by the {@link JingSchemaParser}
+ * implementation.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
 public class JingSchema extends AbstractSchema {
-
+    
     /** <p>The original schema instance to wrap.</p> */
-    private final com.thaiopensource.validate.Schema schema;
+    private final Schema schema;
 
     /**
      * <p>Create a new {@link JingSchema} instance.</p>
@@ -42,33 +45,33 @@
      * @param schema the JING original schema to wrap.
      * @param validity the {@link SourceValidity} associated with the schema.
      */
-    protected JingSchema(com.thaiopensource.validate.Schema schema,
-                         SourceValidity validity) {
+    protected JingSchema(Schema schema, SourceValidity validity) {
         super(validity);
         this.schema = schema;
     }
 
     /**
-     * <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 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>
+     * {@link ValidationHandler}.</p>
      * 
-     * <p>Once used, the returned {@link ContentHandler} <b>can't</b> be reused.</p> 
+     * <p>Once used, the returned {@link ValidationHandler} <b>can't</b> be reused.</p> 
      * 
      * @param errorHandler an {@link ErrorHandler} to notify of validation errors.
-     * @return a <b>non-null</b> {@link ContentHandler} instance.
+     * @return a <b>non-null</b> {@link ValidationHandler} instance.
      * @throws SAXException if an error occurred creating the validation handler.
      */
-    public ContentHandler newValidator(ErrorHandler errorHandler)
+    public ValidationHandler createValidator(ErrorHandler errorHandler)
     throws SAXException {
         if (errorHandler == null) errorHandler = new DraconianErrorHandler();
         final PropertyMapBuilder builder = new PropertyMapBuilder();
         ValidateProperty.ERROR_HANDLER.put(builder, errorHandler);
         final PropertyMap properties = builder.toPropertyMap();
         final Validator validator = this.schema.createValidator(properties);
-        return validator.getContentHandler();
+        final ContentHandler handler = validator.getContentHandler();
+        return new DefaultValidationHandler(this.getValidity(), handler);
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchemaParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchemaParser.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/JingSchemaParser.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchemaParser.java Sun Sep 11 18:09:57 2005
@@ -17,9 +17,11 @@
 
 import java.io.IOException;
 
+import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.components.validation.Schema;
 import org.apache.cocoon.components.validation.SchemaParser;
 import org.apache.cocoon.components.validation.Validator;
+import org.apache.excalibur.source.Source;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 
@@ -34,11 +36,7 @@
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
-public class JingSchemaParser extends CachingSchemaParser {
-
-    /** <p>The list of grammars supported by the {@link JingSchemaParser}.</p> */
-    private static final String[] GRAMMARS =
-                                        new String[] { Validator.GRAMMAR_RELAX_NG };
+public class JingSchemaParser extends AbstractSchemaParser implements ThreadSafe {
 
     /**
      * <p>Create a new {@link JingSchemaParser} instance.</p>
@@ -48,25 +46,38 @@
     }
 
     /**
-     * <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>The returned {@link Schema} must be able to validate multiple documents
+     * via multiple invocations of {@link Schema#createValidator(ErrorHandler)}.</p> 
      *
-     * @param uri the URI of the {@link Schema} to return.
+     * @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 parseSchema(String uri)
+    public Schema getSchema(Source source, String grammar)
     throws SAXException, IOException {
+        if (! Validator.GRAMMAR_RELAX_NG.equals(grammar)) {
+            throw new IllegalArgumentException("Unsupported grammar " + grammar);
+        }
+
         SchemaReader schemaReader = SAXSchemaReader.getInstance();
         JingContext context = new JingContext(sourceResolver, entityResolver);
-        InputSource source = context.resolveEntity(null, uri);
+        InputSource input = new InputSource();
+        input.setByteStream(source.getInputStream());
+        input.setSystemId(source.getURI());
+        context.pushInputSource(input);
 
         try {
             final com.thaiopensource.validate.Schema schema;
-            schema = schemaReader.createSchema(source, context.getProperties());
+            schema = schemaReader.createSchema(input, context.getProperties());
             return new JingSchema(schema, context.getValidity());
         } catch (IncorrectSchemaException exception) {
-            String message = "Incorrect schema \"" + uri + "\"";
+            String message = "Incorrect schema \"" + source.getURI() + "\"";
             throw new SAXException(message, exception);
         }
     }
@@ -79,6 +90,6 @@
      * {@link Validator#GRAMMAR_RELAX_NG RELAX NG} grammar.</p>
      */
     public String[] getSupportedGrammars() {
-        return GRAMMARS;
+        return new String[] { Validator.GRAMMAR_RELAX_NG };
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesGrammarParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesGrammarParser.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/XercesGrammarParser.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesGrammarParser.java Sun Sep 11 18:09:57 2005
@@ -19,11 +19,13 @@
 
 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.SourceValidity;
 import org.apache.xerces.util.XMLGrammarPoolImpl;
 import org.apache.xerces.xni.XNIException;
 import org.apache.xerces.xni.grammars.XMLGrammarLoader;
 import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLInputSource;
 import org.apache.xerces.xni.parser.XMLParseException;
 import org.xml.sax.SAXException;
 
@@ -36,7 +38,7 @@
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
-public abstract class XercesGrammarParser extends CachingSchemaParser 
+public abstract class XercesGrammarParser extends AbstractSchemaParser 
 implements SchemaParser {
 
     /**
@@ -47,14 +49,20 @@
     }
 
     /**
-     * <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>The returned {@link Schema} must be able to validate multiple documents
+     * via multiple invocations of {@link Schema#createValidator(ErrorHandler)}.</p> 
      *
-     * @param uri the URI of the {@link Schema} to return.
+     * @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.  
      */
-    protected final Schema parseSchema(String uri)
+    public Schema getSchema(Source source, String grammar)
     throws IOException, SAXException {
         try {
             /* Create a Xerces Grammar Pool and Entity Resolver */
@@ -70,8 +78,11 @@
             context.initialize(loader);
 
             /* Load (parse and interpret) the grammar */
+            String uri = source.getURI();
             this.getLogger().debug("Loading grammar from " + uri);
-            loader.loadGrammar(r.resolveUri(uri));
+            XMLInputSource input = new XMLInputSource(null, uri, uri);
+            input.setByteStream(source.getInputStream());
+            loader.loadGrammar(input);
             this.getLogger().debug("Grammar successfully loaded from " + uri);
 
             /* Return a new Schema instance */

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.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/XercesSchema.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java Sun Sep 11 18:09:57 2005
@@ -15,6 +15,7 @@
  */
 package org.apache.cocoon.components.validation.impl;
 
+import org.apache.cocoon.components.validation.ValidationHandler;
 import org.apache.excalibur.source.SourceValidity;
 import org.apache.xerces.xni.XMLDocumentHandler;
 import org.apache.xerces.xni.grammars.XMLGrammarPool;
@@ -47,21 +48,23 @@
     }
 
     /**
-     * <p>Return a {@link ContentHandler} able to receive SAX events and performing
-     * validation according to the schema wrapped by this instance.</p>
+     * <p>Return a {@link ValidationHandler} able to receive SAX events and
+     * performing validation according to the schema wrapped by this instance.</p>
      *
      * @param errorHandler {@link ErrorHandler} to be notified of validation errors.
-     * @return a <b>non-null</b> {@link ContentHandler} instance.
-     * @throws SAXException if an error occurred creating the {@link ContentHandler}.
+     * @return a <b>non-null</b> {@link ValidationHandler} instance.
+     * @throws SAXException if an error occurred creating the handler.
      */
-    public ContentHandler newValidator(ErrorHandler errorHandler)
+    public ValidationHandler createValidator(ErrorHandler errorHandler)
     throws SAXException {
         XercesContext context = new XercesContext(this.grammarPool,
                                                   new XercesEntityResolver(),
                                                   errorHandler);
         try {
             Object instance = context.initialize(this.validatorClass.newInstance());
-            return new XercesContentHandler((XMLDocumentHandler) instance);
+            XMLDocumentHandler documentHandler = (XMLDocumentHandler) instance; 
+            ContentHandler finalHandler = new XercesContentHandler(documentHandler);
+            return new DefaultValidationHandler(this.getValidity(), finalHandler);
         } catch (Exception exception) {
             throw new SAXException("Unable to access validator", exception);
         }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.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/XercesSchemaParser.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java Sun Sep 11 18:09:57 2005
@@ -32,9 +32,6 @@
  */
 public class XercesSchemaParser extends XercesGrammarParser implements SchemaParser {
 
-    private static final String[] GRAMMARS = new String[] { Validator.GRAMMAR_XML_SCHEMA };
-    private static final Class VALIDATOR = XMLSchemaValidator.class;
-
     /**
      * <p>Create a new {@link XercesSchemaParser} instance.</p>
      */
@@ -50,7 +47,7 @@
      * {@link Validator#GRAMMAR_XML_SCHEMA} grammar.</p>
      */
     public String[] getSupportedGrammars() {
-        return GRAMMARS;
+        return new String[] { Validator.GRAMMAR_XML_SCHEMA };
     }
 
     /**
@@ -64,6 +61,6 @@
      * <p>Return a {@link Class} implementing the final validation handler.</p>
      */
     protected Class getValidationHandlerClass() {
-        return VALIDATOR;
+        return XMLSchemaValidator.class;
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/transformation/ValidatingTransformer.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/transformation/ValidatingTransformer.java?rev=280229&r1=280228&r2=280229&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/transformation/ValidatingTransformer.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/transformation/ValidatingTransformer.java Sun Sep 11 18:09:57 2005
@@ -29,15 +29,14 @@
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.caching.CacheableProcessingComponent;
-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.environment.SourceResolver;
 import org.apache.cocoon.xml.ContentHandlerWrapper;
 import org.apache.cocoon.xml.XMLConsumer;
 import org.apache.cocoon.xml.XMLMulticaster;
+import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceValidity;
-import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 /**
@@ -46,8 +45,15 @@
  * 
  * <p>The only defined (but not required) configuration for this component is
  * <code>&lt;grammar&gt;<i>...string...</i>&lt;/grammar&gt;</code>
- * indicating the grammar (or optionally the component name) for the
- * {@link Validator} instance providing access to {@link Schema}s.</p>
+ * indicating the default grammar language of the schemas to use.</p>
+ * 
+ * <p>This configuration parameter can be overridden by specifying the
+ * <code>grammar</code> parameter when using this {@link Transformer} in a
+ * pipeline.</p>
+ * 
+ * <p>If no grammar is specified (either as a configuration, or a parameter) this
+ * transformer will instruct the {@link Validator} to try and guess the grammar
+ * of the schema being parsed.</p>
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
@@ -56,9 +62,9 @@
 
     private ServiceManager serviceManager = null;
     private Validator validator = null;
-    private SchemaParser schemaParser = null;
-    private ContentHandler handler = null;
-    private Schema schema = null;
+    private String grammar = null;
+
+    private ValidationHandler handler = null;
     private String key = null;
 
     /**
@@ -79,21 +85,15 @@
      * 
      * <p>The only defined (but not required) configuration for this component is
      * <code>&lt;grammar&gt;<i>...string...</i>&lt;/grammar&gt;</code>
-     * indicating the grammar (or optionally the component name) for the
-     * {@link Validator} instance providing access to {@link Schema}s.</p>
+     * indicating the default grammar used by this transformer used for parsing
+     * schemas.</p>
      *
      * @param configuration a {@link Configuration} instance for this component.
      * @throws ConfigurationException never thrown.
      */
     public void configure(Configuration configuration)
     throws ConfigurationException {
-        String key = configuration.getChild("grammar").getValue();
-        try {
-            this.schemaParser = (SchemaParser) this.validator.select(key);
-        } catch (ServiceException exception) {
-            String message = "Grammar or instance \"" + key + "\" not recognized";
-            throw new ConfigurationException(message, configuration, exception);
-        }
+        this.grammar = configuration.getChild("grammar").getValue(null);
     }
 
     /**
@@ -101,7 +101,6 @@
      * required instances back to the {@link ServiceManager}.</p>
      */
     public void dispose() {
-        this.validator.release(this.schemaParser);
         this.serviceManager.release(this.validator);
     }
 
@@ -117,10 +116,18 @@
     public void setup(SourceResolver resolver, Map objectModel, String source,
                       Parameters parameters)
     throws ProcessingException, SAXException, IOException {
-        this.schema = this.schemaParser.getSchema(source);
-        this.key = this.getClass().getName() + ":" +
-                   this.schemaParser.getClass().getName() + ":" + source;
-        this.handler = this.schema.newValidator();
+        Source s = null;
+        try {
+            s = resolver.resolveURI(source);
+            String g = parameters.getParameter("grammar", this.grammar);
+            if (g == null) {
+                this.handler = this.validator.getValidationHandler(s);
+            } else{
+                this.handler = this.validator.getValidationHandler(s, g);
+            }
+        } finally {
+            if (source != null) resolver.release(s);
+        }
     }
 
     /**
@@ -130,7 +137,7 @@
      * @param consumer the {@link XMLConsumer} to send SAX events to.
      */
     public void setConsumer(XMLConsumer consumer) {
-        XMLConsumer handler = new ContentHandlerWrapper(this.handler);
+        XMLConsumer handler = new ContentHandlerWrapper(this.handler, this.handler);
         super.setConsumer(new XMLMulticaster(handler, consumer));
     }
 
@@ -151,7 +158,7 @@
      * @return a non null {@link SourceValidity} instance.
      */
     public SourceValidity getValidity() {
-        return this.schema.getValidity();
+        return this.handler.getValidity();
     }
 
     /**
@@ -159,7 +166,6 @@
      */
     public void recycle() {
         this.handler = null;
-        this.schema = null;
         this.key = null;
         super.recycle();
     }