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/07 21:47:02 UTC

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

Author: pier
Date: Wed Sep  7 12:46:58 2005
New Revision: 279408

URL: http://svn.apache.org/viewcvs?rev=279408&view=rev
Log:
Storing my initial implementation of the XSD validator (yes, XML Schema using Xerces!) before my hard disk collapses and dies!

Added:
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesComponentManager.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesEntityResolver.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesErrorWrapper.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java
    cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesValidationHandler.java

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesComponentManager.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesComponentManager.java?rev=279408&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesComponentManager.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesComponentManager.java Wed Sep  7 12:46:58 2005
@@ -0,0 +1,113 @@
+/*
+ * 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.xerces.impl.Constants;
+import org.apache.xerces.impl.XMLEntityManager;
+import org.apache.xerces.impl.XMLErrorReporter;
+import org.apache.xerces.impl.validation.ValidationManager;
+import org.apache.xerces.impl.xs.XSMessageFormatter;
+import org.apache.xerces.util.NamespaceSupport;
+import org.apache.xerces.util.ParserConfigurationSettings;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.xml.sax.ErrorHandler;
+
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class XercesComponentManager extends ParserConfigurationSettings {
+
+    private static final String P_ENTITY_MANAGER =        
+            Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
+    private static final String P_ENTITY_RESOLVER =       
+            Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
+    private static final String P_ERROR_REPORTER =        
+            Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
+    private static final String P_NAMESPACE_CONTEXT =     
+            Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
+    private static final String P_SYMBOL_TABLE =          
+            Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
+    private static final String P_VALIDATION_MANAGER =    
+            Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
+    private static final String P_XMLGRAMMAR_POOL =       
+            Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+    private static final String P_ERROR_HANDLER =
+            Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
+
+    private static final String PROPERTIES[] = {
+                P_ENTITY_MANAGER,
+                P_ENTITY_RESOLVER,
+                P_ERROR_REPORTER,
+                P_NAMESPACE_CONTEXT,
+                P_SYMBOL_TABLE,
+                P_VALIDATION_MANAGER,
+                P_XMLGRAMMAR_POOL,
+                P_ERROR_HANDLER
+            };       
+
+    private static final String F_SCHEMA_VALIDATION =     
+            Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
+    private static final String F_VALIDATION =            
+            Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
+    private static final String F_USE_GRAMMAR_POOL_ONLY = 
+            Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
+    private static final String F_PARSER_SETTINGS = 
+            Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
+    
+    private static final String FEATURES[] = {
+                F_SCHEMA_VALIDATION,
+                F_VALIDATION,
+                F_USE_GRAMMAR_POOL_ONLY,
+                F_PARSER_SETTINGS
+            };
+
+    public XercesComponentManager(XMLGrammarPool grammarPool,
+                                  XMLEntityResolver entityResolver,
+                                  final ErrorHandler errorHandler) {
+
+        super.addRecognizedFeatures(FEATURES);
+        super.addRecognizedProperties(PROPERTIES);
+        
+        XMLErrorReporter errorReporter = new XMLErrorReporter();
+        errorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN,
+                                          new XSMessageFormatter());
+        XMLErrorHandler xercesHandler = new XercesErrorWrapper(errorHandler);
+
+        super.setProperty(P_XMLGRAMMAR_POOL,    grammarPool);
+        super.setProperty(P_ENTITY_RESOLVER,    entityResolver);
+        super.setProperty(P_ERROR_REPORTER,     errorReporter);
+        super.setProperty(P_ERROR_HANDLER,      xercesHandler);
+
+        super.setProperty(P_ENTITY_MANAGER,     new XMLEntityManager());
+        super.setProperty(P_NAMESPACE_CONTEXT,  new NamespaceSupport());
+        super.setProperty(P_VALIDATION_MANAGER, new ValidationManager());
+        super.setProperty(P_SYMBOL_TABLE,       new SymbolTable());
+
+        super.setFeature(F_USE_GRAMMAR_POOL_ONLY, true);
+        super.setFeature(F_PARSER_SETTINGS,       true);
+        super.setFeature(F_VALIDATION,            true);
+        super.setFeature(F_SCHEMA_VALIDATION,     true);
+
+        /* Initialize the configured Error Reporter */
+        errorReporter.reset(this);
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesEntityResolver.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesEntityResolver.java?rev=279408&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesEntityResolver.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesEntityResolver.java Wed Sep  7 12:46:58 2005
@@ -0,0 +1,84 @@
+/*
+ * 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.excalibur.source.SourceValidity;
+import org.apache.xerces.xni.XMLResourceIdentifier;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLEntityResolver;
+import org.apache.xerces.xni.parser.XMLInputSource;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class XercesEntityResolver implements XMLEntityResolver {
+    
+    public SourceValidity getSourceValidity() {
+        return null;
+    }
+
+    public XMLInputSource resolveEntity(String location)
+    throws XNIException, IOException {
+        /*
+        try {
+            URI base = new URI("file://" + System.getProperty("user.dir") + "/");
+            System.err.println("BASE URI: " + base.toASCIIString());
+            URI relative = new URI(location);
+            System.err.println("RELATIVE: " + relative.toASCIIString());
+            URI resolved = base.resolve(relative);
+            System.err.println("RELATIVE: " + resolved.toASCIIString());
+            location = resolved.toASCIIString();
+            XMLInputSource source = new XMLInputSource(null, location, location);
+            source.setByteStream(resolved.toURL().openStream());
+            return source;
+        } catch (URISyntaxException exception) {
+            String message = "Cannot resolve " + location;
+            Throwable throwable = new IOException(message);
+            throw (IOException) throwable.initCause(exception);
+        }
+        */
+        throw new IOException("Not implemented"); 
+    }
+
+    public XMLInputSource resolveEntity(XMLResourceIdentifier identifier)
+    throws XNIException, IOException {
+        /*
+        System.err.println("Resolving Identifier: "
+                           + identifier.getLiteralSystemId()
+                           + " from " + identifier.getBaseSystemId()
+                           + " [exp=" + identifier.getExpandedSystemId() + "]");
+        try {
+            URI base = new URI(identifier.getBaseSystemId());
+            URI relative = new URI(identifier.getLiteralSystemId());
+            URI resolved = base.resolve(relative);
+            XMLInputSource source = new XMLInputSource(identifier.getPublicId(),
+                    resolved.toASCIIString(),
+                    base.toASCIIString());
+            source.setByteStream(resolved.toURL().openStream());
+            return source;
+        } catch (URISyntaxException exception) {
+            String message = "Cannot resolve " + identifier.getLiteralSystemId();
+            Throwable throwable = new IOException(message);
+            throw (IOException) throwable.initCause(exception);
+        }
+        */
+        throw new IOException("Not implemented"); 
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesErrorWrapper.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesErrorWrapper.java?rev=279408&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesErrorWrapper.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesErrorWrapper.java Wed Sep  7 12:46:58 2005
@@ -0,0 +1,75 @@
+/*
+ * 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.xerces.xni.XNIException;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLParseException;
+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 class XercesErrorWrapper implements XMLErrorHandler {
+    
+    private final ErrorHandler errorHandler;
+    
+    public XercesErrorWrapper(ErrorHandler errorHandler) {
+        this.errorHandler = errorHandler;
+    }
+    
+    public void warning(String domain, String key, XMLParseException exception)
+    throws XNIException {
+        if (this.errorHandler != null) try {
+            this.errorHandler.warning(this.makeException(exception));
+        } catch (SAXException saxException) {
+            throw new XNIException(saxException);
+        }
+    }
+
+    public void error(String domain, String key, XMLParseException exception)
+    throws XNIException {
+        if (this.errorHandler != null) try {
+            this.errorHandler.warning(this.makeException(exception));
+        } catch (SAXException saxException) {
+            throw new XNIException(saxException);
+        }
+    }
+
+    public void fatalError(String domain, String key, XMLParseException exception)
+    throws XNIException {
+        if (this.errorHandler != null) try {
+            this.errorHandler.warning(this.makeException(exception));
+        } catch (SAXException saxException) {
+            throw new XNIException(saxException);
+        }
+    }
+    
+    private SAXParseException makeException(XMLParseException exception) {
+        final SAXParseException saxParseException;
+        saxParseException = new SAXParseException(exception.getMessage(),
+                                                  exception.getPublicId(),
+                                                  exception.getLiteralSystemId(),
+                                                  exception.getLineNumber(),
+                                                  exception.getColumnNumber(),
+                                                  exception);
+        return (SAXParseException) saxParseException.initCause(exception);
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java?rev=279408&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchema.java Wed Sep  7 12:46:58 2005
@@ -0,0 +1,41 @@
+/*
+ * 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.excalibur.source.SourceValidity;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class XercesSchema extends AbstractSchema {
+    
+    private final XMLGrammarPool grammarPool;
+
+    public XercesSchema(XMLGrammarPool grammarPool, SourceValidity validity) {
+        super(validity);
+        this.grammarPool = grammarPool;
+        grammarPool.lockPool();
+    }
+
+    public ContentHandler newValidator(ErrorHandler handler) {
+        return new XercesValidationHandler(this.grammarPool);
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java?rev=279408&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesSchemaParser.java Wed Sep  7 12:46:58 2005
@@ -0,0 +1,109 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.components.validation.impl;
+
+import java.io.IOException;
+
+import org.apache.cocoon.components.validation.Schema;
+import org.apache.cocoon.components.validation.SchemaParser;
+import org.apache.cocoon.components.validation.Validator;
+import org.apache.xerces.impl.Constants;
+import org.apache.xerces.impl.xs.XMLSchemaLoader;
+import org.apache.xerces.util.XMLGrammarPoolImpl;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>The implementation of the {@link SchemaParser} interface for the XML Schema
+ * grammar using <a href="http://xml.apache.org/xerces2-j/">Xerces</a>.</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class XercesSchemaParser extends CachingSchemaParser  implements SchemaParser {
+
+    private static final String F_SCHEMA_FULL_CHECK = 
+            Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
+    private static final String P_XML_GRAMMAR_POOL =
+            Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
+    private static final String[] GRAMMARS =
+            new String[] { Validator.GRAMMAR_XML_SCHEMA };
+
+    /**
+     * <p>Create a new {@link XercesSchemaParser} instance.</p>
+     */
+    public XercesSchemaParser() {
+        super();
+    }
+
+    /**
+     * <p>Parse the specified URI and return a {@link Schema}.</p>
+     *
+     * @param uri the URI of the {@link Schema} to return.
+     * @return a <b>non-null</b> {@link Schema} instance.
+     * @throws SAXException if an error occurred parsing the schema.
+     * @throws IOException if an I/O error occurred parsing the schema.
+     */
+    protected Schema parseSchema(String uri)
+    throws IOException, SAXException {
+        /* Create a Xerces Grammar Pool */
+        XMLGrammarPool pool = new XMLGrammarPoolImpl();
+        
+        /* Create a new XML Schema Loader and set the pool into it */
+        XMLSchemaLoader loader = new XMLSchemaLoader();
+        loader.setFeature(F_SCHEMA_FULL_CHECK, true);
+        loader.setProperty(P_XML_GRAMMAR_POOL, pool);
+
+        /* Set up the entity resolver (from Cocoon) used to resolve URIs */
+        XercesEntityResolver resolver = new XercesEntityResolver();
+        loader.setEntityResolver(resolver);
+
+        /* Default Error Handler: fail always! */
+        loader.setErrorHandler(new XMLErrorHandler() {
+            public void warning(String domain, String key, XMLParseException e)
+            throws XNIException {
+                throw e;
+            }
+            public void error(String domain, String key, XMLParseException e)
+            throws XNIException {
+                throw e;
+            }
+            public void fatalError(String domain, String key, XMLParseException e)
+            throws XNIException {
+                throw e;
+            }
+        });
+
+        /* Load (parse and interpret) the grammar */
+        loader.loadGrammar(resolver.resolveEntity(uri));
+        
+        /* Return a new Schema instance */
+        return new XercesSchema(pool, resolver.getSourceValidity());
+    }
+
+    /**
+     * <p>Return an array of {@link String}s containing all schema grammars
+     * supported by this {@link SchemaParser}.</p>
+     * 
+     * <p>The {@link XercesSchemaParser} supports only the
+     * {@link Validator#GRAMMAR_XML_SCHEMA} grammar.</p>
+     */
+    public String[] getSupportedGrammars() {
+        return GRAMMARS;
+    }
+}

Added: cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesValidationHandler.java
URL: http://svn.apache.org/viewcvs/cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesValidationHandler.java?rev=279408&view=auto
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesValidationHandler.java (added)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/validation/java/org/apache/cocoon/components/validation/impl/XercesValidationHandler.java Wed Sep  7 12:46:58 2005
@@ -0,0 +1,135 @@
+/*
+ * 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.xerces.impl.xs.XMLSchemaValidator;
+import org.apache.xerces.util.NamespaceSupport;
+import org.apache.xerces.util.SAXLocatorWrapper;
+import org.apache.xerces.util.XMLAttributesImpl;
+import org.apache.xerces.util.XMLSymbols;
+import org.apache.xerces.xni.NamespaceContext;
+import org.apache.xerces.xni.QName;
+import org.apache.xerces.xni.XMLAttributes;
+import org.apache.xerces.xni.XMLString;
+import org.apache.xerces.xni.grammars.XMLGrammarPool;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/**
+ * <p>TODO: ...</p>
+ *
+ * @author <a href="mailto:pier@betaversion.org">Pier Fumagalli</a>
+ */
+public class XercesValidationHandler implements ContentHandler {
+    
+    private final XMLSchemaValidator validator = new XMLSchemaValidator();
+    private final NamespaceContext namespaceContext = new NamespaceSupport();
+    
+    private SAXLocatorWrapper locator = new SAXLocatorWrapper();
+    
+    public XercesValidationHandler(XMLGrammarPool grammarPool) {
+        this.validator.reset(new XercesComponentManager(grammarPool, new XercesEntityResolver(), null));
+    }
+
+    public void setDocumentLocator(Locator locator) {
+        System.err.println("SETTING LOCATOR");
+        this.locator.setLocator(locator);
+    }
+
+    public void startDocument()
+    throws SAXException {
+        System.err.println("START DOCUMENT");
+        this.validator.startDocument(this.locator,
+                                     this.locator.getEncoding(),
+                                     this.namespaceContext,
+                                     null);
+    }
+
+    public void endDocument()
+    throws SAXException {
+        this.validator.endDocument(null);
+    }
+
+    public void startPrefixMapping(String pfx, String uri)
+    throws SAXException {
+        String nsPfx = pfx != null? pfx: XMLSymbols.EMPTY_STRING;
+        String nsUri = (uri != null && uri.length() > 0)? uri : null;
+        this.namespaceContext.declarePrefix(nsPfx, nsUri);
+    }
+
+    public void endPrefixMapping(String arg0)
+    throws SAXException {
+        // Do nothing! Handled by popContext in endElement!
+    }
+
+    public void startElement(String namespace, String local, String qualified,
+                             Attributes attributes)
+    throws SAXException {
+        System.err.println("STAR ELEM " + this.locator.getLiteralSystemId());
+        QName qname = this.qname(namespace, local, qualified);
+        XMLAttributes xmlatts = new XMLAttributesImpl(attributes.getLength());
+        for (int x = 0; x < attributes.getLength(); x ++) {
+            final String aNamespace = attributes.getURI(x);
+            final String aLocalName = attributes.getLocalName(x);
+            final String aQualified = attributes.getQName(x);
+            final String aType = attributes.getType(x);
+            final String aValue = attributes.getValue(x);
+            QName aQname = this.qname(aNamespace, aLocalName, aQualified);
+            xmlatts.addAttribute(aQname, aType, aValue);
+        }
+        this.namespaceContext.pushContext();
+        this.validator.startElement(qname, xmlatts, null);
+    }
+
+    public void endElement(String namespace, String local, String qualified)
+    throws SAXException {
+        QName qname = this.qname(namespace, local, qualified);
+        this.validator.endElement(qname, null);
+        this.namespaceContext.popContext();
+    }
+
+    public void characters(char buffer[], int offset, int length)
+    throws SAXException {
+        XMLString data = new XMLString(buffer, offset, length);
+        this.validator.characters(data, null);
+    }
+
+    public void ignorableWhitespace(char buffer[], int offset, int length)
+    throws SAXException {
+        XMLString data = new XMLString(buffer, offset, length);
+        this.validator.ignorableWhitespace(data, null);
+    }
+
+    public void processingInstruction(String target, String extra)
+    throws SAXException {
+        XMLString data = new XMLString(extra.toCharArray(), 0, extra.length());
+        this.validator.processingInstruction(target, data, null);
+    }
+
+    public void skippedEntity(String arg0)
+    throws SAXException {
+        // Do nothing for skipped entities!
+    }
+
+    private QName qname(String namespace, String local, String qualified) {
+        String prefix = XMLSymbols.EMPTY_STRING;
+        int index = qualified.indexOf(':');
+        if (index != -1) prefix = qualified.substring(0, index);
+        return new  QName(prefix, local, qualified, namespace);
+    }
+}