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/06 18:31:53 UTC

svn commit: r279035 - in /cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components: ./ validation/ validation/impl/

Author: pier
Date: Tue Sep  6 09:31:46 2005
New Revision: 279035

URL: http://svn.apache.org/viewcvs?rev=279035&view=rev
Log:
Initial implementation of the separation between Validation components, Schema parsers and Pipeline components as required by Andreas Hartmann (Lenya)

Added:
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/
    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/ValidationHandler.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/
    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/JingSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/SimpleValidator.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/ValidationHandlerImpl.java

Added: 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=279035&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Schema.java Tue Sep  6 09:31:46 2005
@@ -0,0 +1,33 @@
+/*
+ * 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.apache.excalibur.xml.sax.XMLConsumer;
+import org.xml.sax.ErrorHandler;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public interface Schema {
+    
+    public SourceValidity getValidity();
+    
+    public XMLConsumer createXMLConsumer(ErrorHandler errorHandler); 
+
+}

Added: 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=279035&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/SchemaParser.java Tue Sep  6 09:31:46 2005
@@ -0,0 +1,36 @@
+/*
+ * 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 java.io.IOException;
+
+import org.apache.excalibur.source.Source;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public interface SchemaParser {
+    
+    public static final String ROLE = SchemaParser.class.getName();
+    public static final String SELECTOR = ROLE + "Selector";
+
+    public Schema parseSchema(Source source)
+    throws SAXException, IOException;
+
+}

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=279035&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 Tue Sep  6 09:31:46 2005
@@ -0,0 +1,30 @@
+/*
+ * 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.apache.excalibur.xml.sax.XMLConsumer;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public interface ValidationHandler extends XMLConsumer {
+    
+    public SourceValidity getValidity();
+
+}

Added: 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=279035&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/Validator.java Tue Sep  6 09:31:46 2005
@@ -0,0 +1,57 @@
+/*
+ * 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 java.io.IOException;
+
+import org.apache.excalibur.source.Source;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public interface Validator {
+
+    public static final String ROLE = Validator.class.getName();
+    
+    public void validate(String xmlUri, String schemaUri)
+    throws IOException, SAXException;
+
+    public void validate(String xmlUri, String schemaUri, ErrorHandler errorHandler)
+    throws IOException, SAXException;
+
+    public void validate(Source xmlSource, Source schemaSource)
+    throws IOException, SAXException;
+
+    public void validate(Source xmlSource, Source schemaSource, ErrorHandler errorHandler)
+    throws IOException, SAXException;
+
+    public ValidationHandler getValidationHandler(String schemaUri)
+    throws IOException, SAXException;
+
+    public ValidationHandler getValidationHandler(String schemaUri, ErrorHandler errorHandler)
+    throws IOException, SAXException;
+    
+    public ValidationHandler getValidationHandler(Source schemaSource)
+    throws IOException, SAXException;
+
+    public ValidationHandler getValidationHandler(Source schemaSource, ErrorHandler errorHandler)
+    throws IOException, SAXException;
+
+}

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=279035&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 Tue Sep  6 09:31:46 2005
@@ -0,0 +1,178 @@
+/*
+ * 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.activity.Initializable;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+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.cocoon.components.validation.SchemaParser;
+import org.apache.cocoon.components.validation.ValidationHandler;
+import org.apache.cocoon.components.validation.Validator;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.xml.sax.XMLizable;
+import org.apache.excalibur.xmlizer.XMLizer;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public abstract class AbstractValidator
+implements Validator, Configurable, Serviceable, Initializable, Disposable {
+
+    private boolean ignoreWarning = true;
+    private boolean ignoreError = false;
+    private boolean ignoreFatalError = false;
+    private ServiceSelector serviceSelector = null;
+    private String schemaParserName = null;
+
+    protected ServiceManager serviceManager = null;
+    protected SourceResolver sourceResolver = null;
+    protected SchemaParser schemaParser = null;
+
+    public void service(ServiceManager manager)
+    throws ServiceException {
+        this.serviceManager = manager;
+    }
+
+    public void configure(Configuration configuration)
+    throws ConfigurationException {
+        this.ignoreWarning =    configuration.getChild("ignore-warning").getValueAsBoolean(true);
+        this.ignoreError =      configuration.getChild("ignore-error").getValueAsBoolean(false);
+        this.ignoreFatalError = configuration.getChild("ignore-fatal-error").getValueAsBoolean(false);
+        this.schemaParserName = configuration.getChild("schema-parser").getValue();
+    }
+
+    public void initialize()
+    throws Exception {
+        this.sourceResolver =  (SourceResolver) this.serviceManager.lookup(SourceResolver.ROLE);
+        this.serviceSelector = (ServiceSelector) this.serviceManager.lookup(SchemaParser.SELECTOR);
+        this.schemaParser =    (SchemaParser) this.serviceSelector.select(this.schemaParserName);
+    }
+
+    public void dispose() {
+        if (this.sourceResolver != null)  this.serviceManager.release(this.sourceResolver);
+        if (this.schemaParser != null)    this.serviceSelector.release(this.schemaParser);
+        if (this.serviceSelector != null) this.serviceManager.release(this.serviceSelector);
+    }
+
+    public void validate(String xmlUri, String schemaUri)
+    throws IOException, SAXException {
+        this.validate(xmlUri, schemaUri, new DefaultErrorHandler(this));
+    }
+
+    public void validate(String xmlUri, String schemaUri, ErrorHandler errorHandler)
+    throws IOException, SAXException {
+        Source xmlSource = null;
+        Source schemaSource = null;
+        try {
+            xmlSource = this.sourceResolver.resolveURI(xmlUri);
+            schemaSource = this.sourceResolver.resolveURI(schemaUri);
+            this.validate(xmlSource, schemaSource, errorHandler);
+        } finally {
+            if (xmlSource != null) this.sourceResolver.release(xmlSource);
+            if (schemaSource != null) this.sourceResolver.release(schemaSource);
+        }
+    }
+
+    public void validate(Source xmlSource, Source schemaSource)
+    throws IOException, SAXException {
+        this.validate(xmlSource, schemaSource, new DefaultErrorHandler(this));
+    }
+
+    public void validate(Source xmlSource, Source schemaSource, ErrorHandler errorHandler)
+    throws IOException, SAXException {
+        ValidationHandler validationHandler = this.getValidationHandler(schemaSource, errorHandler);
+        XMLizer xmlizer = null;
+        try {
+            if (xmlSource instanceof XMLizable) {
+                XMLizable xmlizableSource = (XMLizable) xmlSource;
+                xmlizableSource.toSAX(validationHandler);
+            } else {
+                xmlizer = (XMLizer) this.serviceManager.lookup(XMLizer.ROLE);
+                xmlizer.toSAX(xmlSource.getInputStream(), xmlSource.getMimeType(),
+                              xmlSource.getURI(), validationHandler);
+            }
+        } catch (ServiceException exception) {
+            throw new SAXException("Unable to look up XMLizer instance", exception);
+        } finally {
+            if (xmlizer != null) this.serviceManager.release(xmlizer);
+        }
+    }
+
+    public ValidationHandler getValidationHandler(String schemaUri)
+    throws IOException, SAXException {
+        return this.getValidationHandler(schemaUri, new DefaultErrorHandler(this));
+    }
+
+    public ValidationHandler getValidationHandler(String schemaUri, ErrorHandler errorHandler)
+    throws IOException, SAXException {
+        Source schemaSource = null;
+        try {
+            schemaSource = this.sourceResolver.resolveURI(schemaUri);
+            return this.getValidationHandler(schemaSource, errorHandler);
+        } finally {
+            if (schemaSource != null) this.sourceResolver.release(schemaSource);
+        }
+    }
+
+    public ValidationHandler getValidationHandler(Source schemaSource)
+    throws IOException, SAXException {
+        return this.getValidationHandler(schemaSource, new DefaultErrorHandler(this));
+    }
+
+    public abstract ValidationHandler getValidationHandler(Source schemaSource, ErrorHandler errorHandler)
+    throws IOException, SAXException;
+
+    private static final class DefaultErrorHandler implements ErrorHandler {
+        
+        private final AbstractValidator validator;
+        
+        protected DefaultErrorHandler(AbstractValidator validator) {
+            this.validator = validator;
+        }
+
+        public void warning(SAXParseException exception)
+        throws SAXException {
+            if (this.validator.ignoreWarning) return;
+            throw exception;
+        }
+
+        public void error(SAXParseException exception)
+        throws SAXException {
+            if (this.validator.ignoreError) return;
+            throw exception;
+        }
+
+        public void fatalError(SAXParseException exception)
+        throws SAXException {
+            if (this.validator.ignoreFatalError) return;
+            throw exception;
+        }
+    }
+}

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=279035&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 Tue Sep  6 09:31:46 2005
@@ -0,0 +1,86 @@
+/*
+ * 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.ValidationHandler;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.store.Store;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public abstract class CachingValidator extends AbstractValidator {
+
+    private boolean enableCaching = true;
+
+    protected Store transientStore = null;
+
+    public void initialize()
+    throws Exception {
+        try {
+            super.initialize();
+        } finally {
+            this.transientStore = (Store) super.serviceManager.lookup(Store.TRANSIENT_STORE);
+        }
+    }
+    
+    public void dispose() {
+        try {
+            super.dispose();
+        } finally {
+            if (this.transientStore != null) super.serviceManager.release(this.transientStore);
+        }
+    }
+
+    public ValidationHandler getValidationHandler(Source schemaSource,
+                                                  ErrorHandler errorHandler)
+    throws IOException, SAXException {
+
+        String key = this.getClass().getName() + ":" + schemaSource.getURI();
+        Schema schema = (Schema) this.transientStore.get(key);
+        SourceValidity validity = null;
+
+        if (schema != null) {
+            validity = schema.getValidity();
+            if (validity == null) {
+                this.transientStore.remove(key);
+                schema = null;
+            } else if (validity.isValid() != SourceValidity.VALID) {
+                this.transientStore.remove(key);
+                schema = null;
+            }
+        }
+
+        if (schema == null) {
+            schema = super.schemaParser.parseSchema(schemaSource);
+            validity = schema.getValidity();
+            if ((validity != null) && (validity.isValid() == SourceValidity.VALID)) {
+                this.transientStore.store(key, schema);
+            }
+        }
+
+        return new ValidationHandlerImpl(schema.createXMLConsumer(errorHandler),
+                                         schema.getValidity());
+    }
+}

Added: 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=279035&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchemaParser.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchemaParser.java Tue Sep  6 09:31:46 2005
@@ -0,0 +1,358 @@
+/*
+ * 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 java.util.Stack;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.avalon.excalibur.pool.Recyclable;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.activity.Initializable;
+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.environment.SourceResolver;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.AggregatedValidity;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.apache.excalibur.xml.EntityResolver;
+import org.apache.excalibur.xml.sax.NOPLexicalHandler;
+import org.apache.excalibur.xml.sax.XMLConsumer;
+import org.apache.excalibur.xml.sax.XMLConsumerProxy;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.ext.LexicalHandler;
+
+import com.thaiopensource.util.PropertyMap;
+import com.thaiopensource.util.PropertyMapBuilder;
+import com.thaiopensource.validate.IncorrectSchemaException;
+import com.thaiopensource.validate.SchemaReader;
+import com.thaiopensource.validate.ValidateProperty;
+import com.thaiopensource.validate.Validator;
+import com.thaiopensource.validate.rng.SAXSchemaReader;
+import com.thaiopensource.xml.sax.DraconianErrorHandler;
+import com.thaiopensource.xml.sax.XMLReaderCreator;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class JingSchemaParser implements EntityResolver, XMLReaderCreator,
+SchemaParser, Serviceable, Disposable, Initializable, Recyclable {
+
+    /** <p>The {@link SchemaReader} to use for reading RNG schemas.</p> */
+    private final SchemaReader schemaReader = SAXSchemaReader.getInstance();
+    /** <p>The current {@link Stack} of {@link InputSource}s being parsed. </p> */
+    private final Stack parsedSourceStack = new Stack();
+    /** <p>The {@link PropertyMap} to use with JING's factories.</p> */
+    private final PropertyMap validatorProperties;
+    
+    /** <p>The {@link ServiceManager} to resolve other components.</p> */
+    private ServiceManager serviceManager;
+    /** <p>Cocoon's global {@link EntityResolver} for catalog resolution.</p> */
+    private EntityResolver entityResolver;
+    /** <p>The {@link SourceResolver} to use for resolving URIs.</p> */
+    private SourceResolver sourceResolver;
+
+    /** <p>The {@link SourceValidity} associated with the schema.</p> */
+    private AggregatedValidity sourceValidity = null;
+
+    public JingSchemaParser() {
+        PropertyMapBuilder builder = new PropertyMapBuilder();
+        ValidateProperty.ENTITY_RESOLVER.put(builder, this);
+        ValidateProperty.ERROR_HANDLER.put(builder, new DraconianErrorHandler());
+        ValidateProperty.XML_READER_CREATOR.put(builder, this);
+        this.validatorProperties = builder.toPropertyMap();
+    }
+
+    /**
+     * <p>Contextualize this component instance specifying its associated
+     * {@link ServiceManager} instance.</p>
+     * 
+     * @param manager the {@link ServiceManager} to associate with this component.
+     * @throws ServiceException if a dependancy of this could not be resolved.
+     */
+    public void service(ServiceManager manager)
+    throws ServiceException {
+        this.serviceManager = manager;
+    }
+
+    public void initialize()
+    throws Exception {
+        this.entityResolver = (EntityResolver) this.serviceManager.lookup(EntityResolver.ROLE);
+        this.sourceResolver = (SourceResolver) this.serviceManager.lookup(SourceResolver.ROLE);
+    }
+
+    public void dispose() {
+        if (this.sourceResolver != null)  this.serviceManager.release(this.sourceResolver);
+        if (this.entityResolver != null)  this.serviceManager.release(this.entityResolver);
+    }
+
+    public Schema parseSchema(Source source)
+    throws SAXException, IOException {
+        this.sourceValidity = new AggregatedValidity();
+        this.sourceValidity.add(source.getValidity());
+        try {
+            final InputSource input = this.prepareInputSource(source, null);
+            this.parsedSourceStack.push(input);
+            final com.thaiopensource.validate.Schema schema;
+            schema = this.schemaReader.createSchema(input, this.validatorProperties);
+            return null; // TODO
+        } catch (IncorrectSchemaException exception) {
+            String message = "Incorrect schema \"" + source.getURI() + "\"";
+            throw new SAXException(message, exception);
+        }
+    }
+    
+    public void recycle() {
+        this.sourceValidity = null;
+        this.parsedSourceStack.clear();
+    }
+    
+    private InputSource prepareInputSource(Source source, String publicId)
+    throws IOException {
+        InputSource inputSource = new InputSource();
+        inputSource.setSystemId(source.getURI());
+        inputSource.setPublicId(publicId);
+        inputSource.setByteStream(source.getInputStream());
+        return inputSource;
+    }
+
+    /* =========================================================================== */
+    /* SAX2 ENTITY RESOLVER INTERFACE IMPLEMENTATION                               */
+    /* =========================================================================== */
+
+    /**
+     * <p>Resolve an {@link InputSource} from a public ID and/or a system ID.</p>
+     * 
+     * <p>This method can be called only while a schema is being parsed and will
+     * resolve URIs against a dynamic {@link Stack} of {@link InputSource}s.</p>
+     *
+     * <p>Since <a href="http://www.thaiopensource.com/relaxng/jing.html">JING</a>
+     * doesn't offer a complete URI resolution contract, a {@link Stack} is kept
+     * for all the sources parsed while reading a schema. Keeping in mind that the
+     * last {@link InputSource} pushed in the {@link Stack} can be considered to be
+     * the "base URI" for the current resolution, full relative resolution of system
+     * IDs can be achieved this way.<p>
+     * 
+     * <p>Note that this method of resolving URIs by keeping a {@link Stack} of
+     * processed URIs is a <i>sort of</i> a hack, but mimics the internal state of
+     * <a href="http://www.thaiopensource.com/relaxng/jing.html">JING</a> itself:
+     * if URI resolution fails, the {@link Stack} analysis is the first part to
+     * look at.</p>
+     * 
+     * <p>Resolution will use Cocoon's configured {@link EntityResolver} for
+     * resolving public IDs, and Cocoon's {@link SourceResolver} to resolve the
+     * system IDs and accessing the underlying byte streams of the entities.</p>
+     * 
+     * @param publicId the public ID of the entity to resolve.
+     * @param systemId the system ID of the entity to resolve.
+     * @return a <b>non-null</b> {@link InputSource} instance.
+     * @throws IOException if an I/O error occurred resolving the entity.
+     * @throws SAXException if an XML error occurred resolving the entity.
+     */
+    public InputSource resolveEntity(String publicId, String systemId)
+    throws SAXException, IOException {
+        if (this.sourceValidity == null) throw new IllegalStateException();
+
+        /* Try to resolve the public id if we don't have a system id */
+        if (systemId == null) {
+            InputSource source = this.entityResolver.resolveEntity(publicId, null);
+            if ((source == null) || (source.getSystemId() == null)) {
+                throw new IOException("Can't resolve \"" + publicId + "\"");
+            } else {
+                systemId = source.getSystemId();
+            }
+        }
+
+        /* Use Cocoon's SourceResolver to resolve the system id */
+        InputSource parsing = (InputSource) this.parsedSourceStack.peek();
+        String base = parsing != null? parsing.getSystemId(): null;
+        Source source = this.sourceResolver.resolveURI(systemId, base, null);
+        try {
+            this.sourceValidity.add(source.getValidity());
+            return this.prepareInputSource(source, publicId);
+        } finally {
+            this.sourceResolver.release(source);
+        }
+    }
+
+
+    /* =========================================================================== */
+    /* CALL JING TO ACCESS A CACHED OR FRESHLY PARSED SCHEMA INSTANCE              */
+    /* =========================================================================== */
+
+    /**
+     * <p>Create an {@link XMLReader} instance that can be used by
+     * <a href="http://www.thaiopensource.com/relaxng/jing.html">JING</a> for
+     * parsing schemas.</p>
+     * 
+     * <p>The returned {@link XMLReader} will keep track of populating/clearing the
+     * {@link Stack} of {@link InputSource}s kept for URI resolution as explained
+     * in the description of the {@link #resolveEntity(String, String)} method.</p>
+     * 
+     * @return a <b>non-null</b> {@link XMLReader} instance.
+     * @throws SAXException if an error occurrent creating the {@link XMLReader}.
+     */
+    public XMLReader createXMLReader()
+    throws SAXException {
+        return new Reader(this);
+    }
+
+    /* =========================================================================== */
+    /* INNER CLASSES USED TO WRAP JING'S SCHEMA INTO A COCOON VALIDATION ONE       */
+    /* =========================================================================== */
+    
+    /**
+     * <p>The implementation of the {@link Schema} implementation from the
+     * {@link JingSchemaParser} component.</p>
+     */
+    private static final class JingSchema implements Schema {
+
+        private final com.thaiopensource.validate.Schema schema;
+        private final SourceValidity validity;
+        
+        private JingSchema(com.thaiopensource.validate.Schema schema,
+                           SourceValidity validity) {
+            this.validity = validity;
+            this.schema = schema;
+        }
+
+        public SourceValidity getValidity() {
+            return validity;
+        }
+
+        public XMLConsumer createXMLConsumer(ErrorHandler errorHandler) {
+            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);
+            final ContentHandler contentHandler = validator.getContentHandler();
+            final LexicalHandler lexicalHandler = new NOPLexicalHandler();
+            return new XMLConsumerProxy(contentHandler, lexicalHandler);
+        }
+    }
+
+    /* =========================================================================== */
+    /* INNER CLASSES USED TO WRAP XML READER TO USE WITH JING'S RESOLUTION STACK   */
+    /* =========================================================================== */
+
+    /**
+     * <p>A trivial {@link XMLReader} implementation populating and clearing the
+     * {@link Stack} of {@link InputSource}s for URI resolution.</p>
+     */
+    private static final class Reader implements XMLReader {
+        
+        private final XMLReader reader;
+        private final JingSchemaParser parser;
+
+        private Reader(JingSchemaParser parser)
+        throws SAXException {
+            /*
+             * We have to look up the XMLReader using JAXP or SAX, as the SAXParser
+             * supplied by Avalon/Excalibur does not seem to work with JING.
+             */
+            try {
+                SAXParserFactory factory = SAXParserFactory.newInstance();
+                factory.setNamespaceAware(true);
+                factory.setValidating(false);
+                this.reader = factory.newSAXParser().getXMLReader();
+                this.reader.setEntityResolver(parser);
+                this.reader.setErrorHandler(new DraconianErrorHandler());
+                this.parser = parser;
+            } catch (ParserConfigurationException exception) {
+                throw new SAXException("Can't create XML reader instance", exception);
+            }
+        }
+
+        public boolean getFeature(String feature)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+            return this.reader.getFeature(feature);
+        }
+
+        public void setFeature(String feature, boolean value)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+            this.reader.setFeature(feature, value);
+        }
+
+        public Object getProperty(String property)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+            return this.reader.getProperty(property);
+        }
+
+        public void setProperty(String property, Object value)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+            this.reader.setProperty(property, value);
+        }
+
+        public void setEntityResolver(org.xml.sax.EntityResolver resolver) {
+            this.reader.setEntityResolver(resolver);
+        }
+
+        public org.xml.sax.EntityResolver getEntityResolver() {
+            return this.reader.getEntityResolver();
+        }
+
+        public void setDTDHandler(DTDHandler handler) {
+            this.reader.setDTDHandler(handler);
+        }
+
+        public DTDHandler getDTDHandler() {
+            return this.reader.getDTDHandler();
+        }
+
+        public void setContentHandler(ContentHandler handler) {
+            this.reader.setContentHandler(handler);
+        }
+
+        public ContentHandler getContentHandler() {
+            return this.reader.getContentHandler();
+        }
+
+        public void setErrorHandler(ErrorHandler handler) {
+            this.reader.setErrorHandler(handler);
+        }
+
+        public ErrorHandler getErrorHandler() {
+            return this.reader.getErrorHandler();
+        }
+
+        public void parse(InputSource source)
+        throws IOException, SAXException {
+            this.parser.parsedSourceStack.push(source);
+            this.reader.parse(source);
+            this.parser.parsedSourceStack.pop();
+        }
+
+        public void parse(String source)
+        throws IOException, SAXException {
+            this.parse(this.getEntityResolver().resolveEntity(null, source));
+        }
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/SimpleValidator.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/SimpleValidator.java?rev=279035&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/SimpleValidator.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/SimpleValidator.java Tue Sep  6 09:31:46 2005
@@ -0,0 +1,40 @@
+/*
+ * 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.ValidationHandler;
+import org.apache.excalibur.source.Source;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class SimpleValidator extends AbstractValidator {
+
+    public ValidationHandler getValidationHandler(Source schemaSource,
+                                                  ErrorHandler errorHandler)
+    throws IOException, SAXException {
+        final Schema schema = super.schemaParser.parseSchema(schemaSource);
+        return new ValidationHandlerImpl(schema.createXMLConsumer(errorHandler),
+                                         schema.getValidity());
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/ValidationHandlerImpl.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/ValidationHandlerImpl.java?rev=279035&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/ValidationHandlerImpl.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/ValidationHandlerImpl.java Tue Sep  6 09:31:46 2005
@@ -0,0 +1,51 @@
+/*
+ * 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.XMLConsumer;
+import org.apache.excalibur.xml.sax.XMLConsumerProxy;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class ValidationHandlerImpl extends XMLConsumerProxy
+implements ValidationHandler {
+
+    private final SourceValidity sourceValidity;
+
+    public ValidationHandlerImpl(ContentHandler contentHandler,
+                                 LexicalHandler lexicalHandler,
+                                 SourceValidity sourceValidity) {
+        super(contentHandler, lexicalHandler);
+        this.sourceValidity = sourceValidity;
+    }
+
+    public ValidationHandlerImpl(XMLConsumer xmlConsumer,
+                                 SourceValidity sourceValidity) {
+        super(xmlConsumer);
+        this.sourceValidity = sourceValidity;
+    }
+
+    public SourceValidity getValidity() {
+        return this.sourceValidity;
+    }
+}