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 21:29:03 UTC

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

Author: pier
Date: Tue Sep  6 12:28:55 2005
New Revision: 279076

URL: http://svn.apache.org/viewcvs?rev=279076&view=rev
Log:
Better API for Schema parsing / validation

Added:
    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/CachingSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingContext.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingReader.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.java
Removed:
    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/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/SimpleValidator.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/ValidationHandlerImpl.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/impl/JingSchemaParser.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=279076&r1=279075&r2=279076&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 Tue Sep  6 12:28:55 2005
@@ -15,19 +15,63 @@
  */
 package org.apache.cocoon.components.validation;
 
+import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceValidity;
 import org.apache.excalibur.xml.sax.XMLConsumer;
 import org.xml.sax.ErrorHandler;
 
 /**
- * <p>TODO: ...</p>
+ * <p>An interface defining a schema used for validation of XML documents.</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 XMLConsumer}s
+ * that will receive SAX Events and validate them.</p>
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
 public interface Schema {
-    
+
+    /**
+     * <p>Return the {@link SourceValidity} associated with this {@link Schema}.</p>
+     * 
+     * <p>Schema implementations might return simple schema implementations as
+     * returned by {@link Source#getValidity()}, but if the current schema language
+     * allow inclusion of sub-schemas, the {@link SourceValidity} returned by this
+     * method <b>must</b> validate the original schema {@link Source} <b>and</b> all
+     * its sub-schema {@link Source}s.</p>
+     * 
+     * @return a {@link SourceValidity} instance or <b>null</b> if not known.
+     */
     public SourceValidity getValidity();
-    
-    public XMLConsumer createXMLConsumer(ErrorHandler errorHandler); 
+
+    /**
+     * <p>Return a new {@link XMLConsumer} instance that can be used to send SAX
+     * events to for proper validation.</p>
+     *
+     * <p>By default, this method will create a {@link XMLConsumer} 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 XMLConsumer} <b>can not</b> be reused.</p> 
+     * 
+     * @return a <b>non-null</b> {@link XMLConsumer} instance.
+     */
+    public XMLConsumer newValidator();
+
+    /**
+     * <p>Return a new {@link XMLConsumer} 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 XMLConsumer}.</p>
+     * 
+     * <p>Once used, the returned {@link XMLConsumer} <b>can not</b> be reused.</p> 
+     * 
+     * @param errorHandler an {@link ErrorHandler} to notify of validation errors.
+     * @return a <b>non-null</b> {@link XMLConsumer} instance.
+     */
+    public XMLConsumer newValidator(ErrorHandler handler);
 
 }

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=279076&r1=279075&r2=279076&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 Tue Sep  6 12:28:55 2005
@@ -18,19 +18,47 @@
 import java.io.IOException;
 
 import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceValidity;
+import org.xml.sax.ErrorHandler;
 import org.xml.sax.SAXException;
 
 /**
- * <p>TODO: ...</p>
- *
+ * <p>A component parsing schemas usable for XML validation and returning them as
+ * {@link Schema} instances.</p>
+ * 
+ * <p>This interface does not imply any requirement in terms of the language used
+ * to produce {@link Schema} instances. Normally multiple-language selection is
+ * provided looking up the {@link SELECTOR} role, and from there determining
+ * the implementation required.</p>
+ * 
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
 public interface SchemaParser {
     
+    /** <p>Avalon Role name of this component.</p> */
     public static final String ROLE = SchemaParser.class.getName();
+    /** <p>Role name to use when this component is accessed via a selector.</p> */
     public static final String SELECTOR = ROLE + "Selector";
 
-    public Schema parseSchema(Source source)
+    /**
+     * <p>Parse the specified URI and return a {@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#createXMLConsumer(ErrorHandler)}.</p>
+     * 
+     * <p>As different schema languages allow inclusion of sub-schemas, the
+     * {@link SourceValidity} of the resolved schema might not equivalent to the
+     * one returned by {@link Source#getValidity()}. After parsing is complete, the
+     * validity of the parsed schema and its sub-schemas is available calling the 
+     * {@link Schema#getValidity()} method.</p>
+     *
+     * @param source the {@link Source} of the {@link Schema} to return.
+     * @return a <b>non-null</b> {@link Schema} instance.
+     * @throws SAXException if an error occurred parsing the {@link Source}.
+     * @throws IOException if an I/O error occurred parsing the {@link Source}.
+     */
+    public Schema getSchema(String uri)
     throws SAXException, IOException;
 
 }

Added: 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=279076&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/AbstractSchema.java Tue Sep  6 12:28:55 2005
@@ -0,0 +1,86 @@
+/* ========================================================================== *
+ * Copyright (C) 2004-2005 Pier Fumagalli <http://www.betaversion.org/~pier/> *
+ *                            All rights reserved.                            *
+ * ========================================================================== *
+ *                                                                            *
+ * 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.Schema;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.xml.sax.XMLConsumer;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * <p>A simple implementation of the {@link Scema} interface.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public abstract class AbstractSchema implements Schema {
+    
+    protected final SourceValidity validity;
+
+    /**
+     * <p>Create a new {@link AbstractSchema} instance.</p>
+     */
+    public AbstractSchema(SourceValidity validity) {
+        this.validity = validity;
+    }
+
+    /**
+     * <p>Return the {@link SourceValidity} associated with this {@link Schema}.</p>
+     * 
+     * <p>Schema implementations might return simple schema implementations as
+     * returned by {@link Source#getValidity()}, but if the current schema language
+     * allow inclusion of sub-schemas, the {@link SourceValidity} returned by this
+     * method <b>must</b> validate the original schema {@link Source} <b>and</b> all
+     * its sub-schema {@link Source}s.</p>
+     * 
+     * @return a {@link SourceValidity} instance or <b>null</b> if not known.
+     */
+    public SourceValidity getValidity() {
+        return this.validity;
+    }
+
+    /**
+     * <p>Return a new {@link XMLConsumer} instance that can be used to send SAX
+     * events to for proper validation.</p>
+     *
+     * <p>By default, this method will create a {@link XMLConsumer} 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 XMLConsumer} <b>can not</b> be reused.</p> 
+     * 
+     * @return a <b>non-null</b> {@link XMLConsumer} instance.
+     */
+    public XMLConsumer newValidator() {
+        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/CachingSchemaParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingSchemaParser.java?rev=279076&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingSchemaParser.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/CachingSchemaParser.java Tue Sep  6 12:28:55 2005
@@ -0,0 +1,130 @@
+/*
+ * 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.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+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.store.Store;
+import org.apache.excalibur.xml.EntityResolver;
+import org.xml.sax.SAXException;
+
+/**
+ * <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 CachingSchemaParser
+implements Serviceable, Initializable, Disposable, SchemaParser, ThreadSafe {
+
+    /** <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>The {@link Store} used for caching {@link Schema}s.</p> */
+    protected Store transientStore = 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);
+        this.transientStore = (Store) this.serviceManager.lookup(Store.TRANSIENT_STORE);
+    }
+    
+    /**
+     * <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);
+        if (this.transientStore != null) this.serviceManager.release(this.transientStore);
+    }
+
+    /**
+     * <p>Return a cached or freshly parsed {@link Schema} instance.</p>
+     */
+    public final Schema getSchema(String uri)
+    throws IOException, SAXException {
+        Source source = null;
+        try {
+            source = this.sourceResolver.resolveURI(uri); 
+            uri = source.getURI();
+        } finally {
+            if (source != null) this.sourceResolver.release(source);
+        }
+
+        String key = this.getClass().getName() + ":" + uri;
+        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 = this.parseSchema(uri);
+            validity = schema.getValidity();
+            if ((validity != null) && (validity.isValid() == SourceValidity.VALID)) {
+                this.transientStore.store(key, schema);
+            }
+        }
+        
+        return schema;
+    }
+    
+    /**
+     * <p>Freshly parsed a brand new {@link Schema} instance.</p>
+     *
+     * <p>Caching of the parsed {@link Schema} instance will be performed in the
+     * {@link #getSchema(String)} method.</p>
+     */
+    protected abstract Schema parseSchema(String uri)
+    throws IOException, SAXException;
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingContext.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingContext.java?rev=279076&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingContext.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingContext.java Tue Sep  6 12:28:55 2005
@@ -0,0 +1,190 @@
+/*
+ * 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 org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.AggregatedValidity;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+import com.thaiopensource.util.PropertyMap;
+import com.thaiopensource.util.PropertyMapBuilder;
+import com.thaiopensource.validate.ValidateProperty;
+import com.thaiopensource.xml.sax.DraconianErrorHandler;
+import com.thaiopensource.xml.sax.XMLReaderCreator;
+
+/**
+ * <p>A simple context used when parsing RELAX NG schemas through the use of
+ * <a href="http://www.thaiopensource.com/relaxng/jing.html">JING</a>.</p>
+ * 
+ * <p>This is not thread safe and not recyclable. Once used, it <b>must</b> be
+ * garbage collected.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class JingContext implements EntityResolver, XMLReaderCreator {
+
+    /** <p>The current {@link Stack} of {@link InputSource}s being parsed. </p> */
+    private final Stack parsedSourceStack = new Stack();
+    /** <p>The {@link SourceValidity} associated with the schema.</p> */
+    private final AggregatedValidity sourceValidity = new AggregatedValidity();
+    /** <p>The {@link SourceResolver} to resolve URIs to {@link Source}s.</p> */
+    private final SourceResolver sourceResolver;
+    /** <p>The global {@link EntityResolver} for catalog resolution.</p> */
+    private final EntityResolver entityResolver;
+    /** <p>The {@link PropertyMap} to use with JING's factories.</p> */
+    private final PropertyMap validatorProperties;
+
+    /**
+     * <p>Create a new {@link JingContext} instance.</p>
+     */
+    protected JingContext(SourceResolver sourceResolver, EntityResolver entityResolver) {
+        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();
+        this.sourceResolver = sourceResolver;
+        this.entityResolver = entityResolver;
+    }
+
+    /**
+     * <p>Push a new {@link InputSource} in the stack used for relative URIs
+     * resolution.</p>
+     */
+    public void pushInputSource(InputSource inputSource) {
+        this.parsedSourceStack.push(inputSource);
+    }
+
+    /**
+     * <p>Pop the last {@link InputSource} from the stack used for relative URIs
+     * resolution.</p>
+     */
+    public InputSource popInputSource() {
+        if (this.parsedSourceStack.empty()) return null;
+        return (InputSource) this.parsedSourceStack.pop();
+    }
+
+    /**
+     * <p>Return the {@link SourceValidity} of all sources resolved by this
+     * instance through the {@link #resolveEntity(String, String)} method.</p>
+     */
+    public SourceValidity getValidity() {
+        return this.sourceValidity;
+    }
+
+    /**
+     * <p>Return the {@link PropertyMap} associated with this instance and usable
+     * by <a href="http://www.thaiopensource.com/relaxng/jing.html">JING</a>.</p>
+     */
+    public PropertyMap getProperties() {
+        return this.validatorProperties;
+    }
+
+    /* =========================================================================== */
+    /* 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 a hack</i>, but it 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 the {@link EntityResolver} specified at construction
+     * to resolve public IDs, and then the {@link SourceResolver} again specified at
+     * construction to resolve the system IDs and to access the underlying byte
+     * streams of the entities to be parsed.</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());
+            InputSource inputSource = new InputSource();
+            inputSource.setSystemId(source.getURI());
+            inputSource.setPublicId(publicId);
+            inputSource.setByteStream(source.getInputStream());
+            return inputSource;
+        } 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>
+     * 
+     * @see JingReader
+     * @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 JingReader(this);
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingReader.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingReader.java?rev=279076&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingReader.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingReader.java Tue Sep  6 12:28:55 2005
@@ -0,0 +1,118 @@
+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.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+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 com.thaiopensource.xml.sax.DraconianErrorHandler;
+
+/**
+ * <p>A trivial {@link XMLReader} implementation populating and clearing the
+ * {@link Stack} of {@link InputSource}s for URI resolution kept inside
+ * a {@link JingContext}.</p>
+ */
+final class JingReader implements XMLReader {
+    
+    /** <p>The underlying {@link XMLReader} to use.</p> */
+    private final XMLReader reader;
+    /** <p>The {@link JingContext} associated with this instance.</p> */
+    private final JingContext context;
+
+    /**
+     * <p>Create a new {@link JingReader} instance associated with the specified
+     * {@link JingContext}.</p>
+     */
+    protected JingReader(JingContext context)
+    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.setEntityResolver(context);
+            this.setErrorHandler(new DraconianErrorHandler());
+            this.context = context;
+        } 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.context.pushInputSource(source);
+        this.reader.parse(source);
+        this.context.popInputSource();
+    }
+
+    public void parse(String source)
+    throws IOException, SAXException {
+        this.parse(this.getEntityResolver().resolveEntity(null, source));
+    }
+}
\ No newline at end of file

Added: 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=279076&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/JingSchema.java Tue Sep  6 12:28:55 2005
@@ -0,0 +1,62 @@
+package org.apache.cocoon.components.validation.impl;
+
+import org.apache.cocoon.components.validation.Schema;
+import org.apache.excalibur.source.SourceValidity;
+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.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.ext.LexicalHandler;
+
+import com.thaiopensource.util.PropertyMap;
+import com.thaiopensource.util.PropertyMapBuilder;
+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>
+ */
+public class JingSchema extends AbstractSchema {
+
+    /** <p>The original schema instance to wrap.</p> */
+    private final com.thaiopensource.validate.Schema schema;
+
+    /**
+     * <p>Create a new {@link JingSchema} instance.</p>
+     *
+     * @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) {
+        super(validity);
+        this.schema = schema;
+    }
+
+    /**
+     * <p>Return a new {@link XMLConsumer} 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 XMLConsumer}.</p>
+     * 
+     * <p>Once used, the returned {@link XMLConsumer} <b>can not</b> be reused.</p> 
+     * 
+     * @param errorHandler an {@link ErrorHandler} to notify of validation errors.
+     * @return a <b>non-null</b> {@link XMLConsumer} instance.
+     */
+    public XMLConsumer newValidator(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);
+    }
+}
\ No newline at end of file

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=279076&r1=279075&r2=279076&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 Tue Sep  6 12:28:55 2005
@@ -16,343 +16,58 @@
 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>
+ * <p>A {@link SchemaParser} implementation for the RELAX NG language using the
+ * <a href="http://www.thaiopensource.com/relaxng/jing.html">JING</a> validation
+ * engine.</p>
  *
  * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
  */
-public class JingSchemaParser implements EntityResolver, XMLReaderCreator,
-SchemaParser, Serviceable, Disposable, Initializable, Recyclable {
+public class JingSchemaParser extends CachingSchemaParser {
 
-    /** <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.
+     * <p>Create a new {@link JingSchemaParser} instance.</p>
      */
-    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;
+    public JingSchemaParser() {
+        super();
     }
 
-    /* =========================================================================== */
-    /* 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>Parse the specified URI and return a {@link Schema}.</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.
+     * @param source the {@link Source} of the {@link Schema} to return.
+     * @return a <b>non-null</b> {@link Schema} instance.
+     * @throws SAXException if an error occurred parsing the {@link Source}.
+     * @throws IOException if an I/O error occurred parsing the {@link Source}.
      */
-    public InputSource resolveEntity(String publicId, String systemId)
+    public Schema parseSchema(String uri)
     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();
-            }
-        }
+        SchemaReader schemaReader = SAXSchemaReader.getInstance();
+        JingContext context = new JingContext(sourceResolver, entityResolver);
+        InputSource source = context.resolveEntity(null, uri);
 
-        /* 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));
+            final com.thaiopensource.validate.Schema schema;
+            schema = schemaReader.createSchema(source, context.getProperties());
+            return new JingSchema(schema, context.getValidity());
+        } catch (IncorrectSchemaException exception) {
+            String message = "Incorrect schema \"" + uri + "\"";
+            throw new SAXException(message, exception);
         }
     }
 }