Package org.objectweb.celtix.configuration.impl

Source Code of org.objectweb.celtix.configuration.impl.TypeSchema$TypeSchemaErrorHandler

package org.objectweb.celtix.configuration.impl;


import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;

import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import org.objectweb.celtix.common.i18n.Message;
import org.objectweb.celtix.common.logging.LogUtils;
import org.objectweb.celtix.configuration.ConfigurationException;
import org.objectweb.celtix.configuration.ConfigurationItemMetadata;
import org.objectweb.celtix.jaxb.JAXBUtils;
import org.objectweb.celtix.resource.DefaultResourceManager;

public class TypeSchema {

    static final Logger LOG = LogUtils.getL7dLogger(TypeSchema.class);
   
    private Schema schema;
    private Validator validator;
    private final String namespaceURI;
    private String packageName;
    private final Map<String, QName> elementDefinitions;
    private final Map<String, String> typeDefinitions;
    private final boolean forceDefaults;
   
    /**
     * prevent instantiation
     */
    protected TypeSchema(String nsuri, String baseURI, String location, Boolean fd) {
        forceDefaults = fd;
        namespaceURI = nsuri;
        elementDefinitions = new HashMap<String, QName>();
        typeDefinitions = new HashMap<String, String>();  
       
        LOG.fine("Creating type schema for namespace " + namespaceURI);

        InputSource is = getSchemaInputSource(baseURI, location);

        Document document = null;
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder parser = factory.newDocumentBuilder();
            document = parser.parse(is);
        } catch (ParserConfigurationException ex) {
            throw new ConfigurationException(new Message("PARSER_CONFIGURATION_ERROR_EXC",
                                                         LOG, location), ex);
        } catch (SAXException ex) {
            throw new ConfigurationException(new Message("PARSE_ERROR_EXC", LOG), ex);
        } catch (IOException ex) {
            throw new ConfigurationException(new Message("FILE_OPEN_ERROR_EXC", LOG, location), ex);
        }

        deserialize(document);

        Source src = new DOMSource(document);
        src.setSystemId(is.getSystemId());

        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final LSResourceResolver oldResolver = factory.getResourceResolver();
    
        LSResourceResolver resolver = new LSResourceResolver() {

            public LSInput resolveResource(String type, String nsURI,
                                           String publicId, String systemId, String baseURI) {
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.fine("resolving resource type: " + type + "\n"
                            + "                   namespaceURI:" + nsURI + "\n"
                            + "                   publicId:" + publicId + "\n"
                            + "                   systemId:" + systemId + "\n"
                            + "                   baseURI:" + baseURI);
                }
               
                if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(type)) {
                    LSInput lsi = new SchemaInput(type, nsURI, publicId, systemId, baseURI);
                    String resourceName = systemId;
                   
                    InputSource src = getSchemaInputSource(baseURI, resourceName);
                    lsi.setByteStream(src.getByteStream());
                    lsi.setSystemId(src.getSystemId());
                    return lsi;
                }
                return oldResolver == null ? null
                    : oldResolver.resolveResource(type, nsURI, publicId, systemId, baseURI);
            }
        };
       
        factory.setResourceResolver(resolver);       
        try {
            schema = factory.newSchema(src);
        } catch (SAXException ex) {
            throw new ConfigurationException(new Message("SCHEMA_CREATION_ERROR_EXC", LOG, location), ex);
        }
        document = null;
       
        LOG.fine("Created type schema for namespace " + namespaceURI);
    }

    public Validator getValidator() {
        if (null == validator) {
            Schema s = getSchema();
            validator = s.newValidator();
            validator.setErrorHandler(new TypeSchemaErrorHandler());
        }
        return validator;
    }

    public Collection<String> getTypes() {
        return typeDefinitions.keySet();
    }

    public boolean hasType(String typeName) {
        return typeDefinitions.containsKey(typeName);
    }
   
    public Collection<String> getElements() {
        return elementDefinitions.keySet();
    }
   
    public boolean hasElement(String elementName) {
        return elementDefinitions.containsKey(elementName);
    }

    public QName getDeclaredType(String typeName) {
        return elementDefinitions.get(typeName);
    }

    public String getXMLSchemaBaseType(String typeName) {
        if (!hasType(typeName)) {
            throw new ConfigurationException(new Message("TYPE_NOT_DEFINED_IN_NAMESPACE_EXC", LOG,
                                                         typeName, namespaceURI));
                                                     
        }
        return typeDefinitions.get(typeName);
    }

    public String getPackageName() {
        return packageName;
    }

    public Schema getSchema() {
        return schema;
    }
   
    public Object unmarshalDefaultValue(ConfigurationItemMetadata item, Element data) {
        return unmarshalDefaultValue(item, data, false);
    }

    public Object unmarshalDefaultValue(ConfigurationItemMetadata item, Element data, boolean doValidate) {
        try {
            return unmarshal(item.getType(), data, doValidate);
        } catch (JAXBException ex) {
            if (forceDefaults) {
                Message msg = new Message("DEFAULT_VALUE_UNMARSHAL_ERROR_EXC", LOG, item.getName());
                throw new ConfigurationException(msg, ex);
            }
            return null;
        }
    }
   
    public Object unmarshal(QName type, Element data) throws JAXBException {
        return unmarshal(type, data, true);
    }

    public Object unmarshal(QName type, Element data, boolean doValidate) throws JAXBException {
       
        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("unmarshalling: element namespaceURI: " + data.getNamespaceURI() + "\n"
                     + "                       localName: " + data.getLocalName() + "\n"
                     + "             type: " + type  + "\n"
                     + "             type schema package name: " + packageName);           
        }
        JAXBContext context = null;
        Object obj = null;

        context = JAXBContext.newInstance(packageName, getClass().getClassLoader());
        Unmarshaller u = context.createUnmarshaller();
        if (doValidate) {
            u.setSchema(schema);
        }
        obj = u.unmarshal(data);
        if (obj instanceof JAXBElement<?>) {
            JAXBElement<?> el = (JAXBElement<?>)obj;
            obj = el.getValue();
            /*
             * if (el.getName().equals(type)) { obj = el.getValue(); }
             */
        }

        if (null != obj && LOG.isLoggable(Level.FINE)) {
            LOG.fine("Unmarshaled default value into object of type: " + obj.getClass().getName()
                     + "    value: " + obj);
        }
        return obj;
    }

    private void deserialize(Document document) {
        deseralizePackageName(document);
        deserializeTypes(document);
        deserializeElements(document);
    }

    private void deserializeElements(Document document) {
        Element root = document.getDocumentElement();
        for (Node nd = root.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
            if (Node.ELEMENT_NODE == nd.getNodeType() && "element".equals(nd.getLocalName())) {
                String elementName = ((Element)nd).getAttribute("name");

                QName type = ConfigurationMetadataUtils
                    .elementAttributeToQName(document, (Element)nd, "type");

                elementDefinitions.put(elementName, type);
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.fine("Added type " + type + "  for key: " + elementName);
                }
            }
        }
    }

    private void deserializeTypes(Document document) {
        Element root = document.getDocumentElement();
        for (Node nd = root.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
            if (Node.ELEMENT_NODE == nd.getNodeType()
                && ("simpleType".equals(nd.getLocalName()) || ("complexType".equals(nd.getLocalName())))) {

                String typeName = ((Element)nd).getAttribute("name");

                String baseType = null;
                if ("simpleType".equals(nd.getLocalName())) {
                    baseType = getBaseType(document, typeName);
                }

                if (!typeDefinitions.containsKey(typeName)) {
                    typeDefinitions.put(typeName, baseType);
                    if (LOG.isLoggable(Level.FINE)) {
                        LOG.fine("Added base type " + baseType + "  for key: " + typeName);
                    }
                }

            }
        }
    }

    private String getBaseType(Document document, String typeName) {
        String currentType = typeName;
        QName baseType;
        do {
            baseType = getBaseTypeInternal(document, currentType);
            if (null == baseType) {
                LOG.severe(new Message("UNDEFINED_SIMPLE_TYPE_MSG", LOG, typeName).toString());
                return null;
            } else if (XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(baseType.getNamespaceURI())) {
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.fine("Base type for " + typeName + ": " + baseType);
                }
                return baseType.getLocalPart();
            } else if (!namespaceURI.equals(baseType.getNamespaceURI())) {
                LOG.severe(new Message("SIMPLE_TYPE_DEFINED_IN_OTHER_NAMESPACE_MSG", LOG, typeName,
                                       namespaceURI).toString());
                return null;
            }
            currentType = baseType.getLocalPart();
        } while (true);
    }

    private QName getBaseTypeInternal(Document document, String type) {
        Element root = document.getDocumentElement();
        Element simpleTypeElement = null;

        for (Node nd = root.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
            if (Node.ELEMENT_NODE == nd.getNodeType() && "simpleType".equals(nd.getLocalName())
                && ((Element)nd).getAttribute("name").equals(type)) {
                simpleTypeElement = (Element)nd;
            }
        }
        if (null == simpleTypeElement) {
            return null;
        }

        for (Node nd = simpleTypeElement.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
            if (Node.ELEMENT_NODE == nd.getNodeType() && "restriction".equals(nd.getLocalName())) {
                // TODO restriction element can have base attribute OR
                // simpleType
                // child element. Currently we only handle the base attribute
                // case.

                return ConfigurationMetadataUtils.elementAttributeToQName(document, (Element)nd, "base");
            }
        }
        return null;
    }

    private void deseralizePackageName(Document document) {
        Element root = document.getDocumentElement();
        Element annotationElement = null;
        for (Node nd = root.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
            if (Node.ELEMENT_NODE == nd.getNodeType() && "annotation".equals(nd.getLocalName())) {
                annotationElement = (Element)nd;
                break;
            }
        }
        Element appInfoElement = null;
        if (null != annotationElement) {
            for (Node nd = annotationElement.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
                if (Node.ELEMENT_NODE == nd.getNodeType() && "appinfo".equals(nd.getLocalName())) {
                    appInfoElement = (Element)nd;
                    break;
                }
            }
        }
        Element schemaBindingsElement = null;
        if (null != appInfoElement) {
            for (Node nd = appInfoElement.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
                if (Node.ELEMENT_NODE == nd.getNodeType() && "schemaBindings".equals(nd.getLocalName())) {
                    schemaBindingsElement = (Element)nd;
                    break;
                }
            }
        }
        Element packageElement = null;
        if (null != schemaBindingsElement) {
            for (Node nd = schemaBindingsElement.getFirstChild(); nd != null; nd = nd.getNextSibling()) {
                if (Node.ELEMENT_NODE == nd.getNodeType() && "package".equals(nd.getLocalName())) {
                    packageElement = (Element)nd;
                    break;
                }
            }
        }

        if (null != packageElement) {
            packageName = packageElement.getAttribute("name");
        } else {
            packageName = JAXBUtils.namespaceURIToPackage(namespaceURI);
        }

        if (null == packageName) {
            throw new ConfigurationException(new Message("MISSING_PACKAGE_NAME_EXC", LOG, namespaceURI));
        }

    }
   
    static InputSource getSchemaInputSource(String baseURI, String location) {
        URI uri = null;
        URI base = null;
        URI resolved = null;
        try {
            uri = new URI(location);
            if (baseURI != null) {
                try {
                    base = new URI(baseURI);
                    resolved = base.resolve(uri);
                } catch (URISyntaxException ex) {
                    base = null;
                    resolved = null;
                }
            }
        } catch (URISyntaxException ex) {
            Message msg = new Message("SCHEMA_LOCATION_ERROR_EXC", LOG, location);
            throw new ConfigurationException(msg, ex);
        }

        if (!uri.isAbsolute() && resolved != null && resolved.isAbsolute()) {
            uri = resolved;
        }

        if (uri.isAbsolute()) {
            if ("file".equals(uri.getScheme())) {
                String path = uri.getPath();
                if (null == path) {
                    Message msg = new Message("FILE_OPEN_ERROR_EXC", LOG, location);
                    throw new ConfigurationException(msg);
                }
                File file = new File(path);
                if (file.exists()) {
                    return new InputSource(file.toURI().toString());
                }
            } else {
                //TODO - other protocols like HTTP?               
            }
        }
       
        // uri path is a system resource            
        URL url = DefaultResourceManager.instance().resolveResource(location, URL.class);
        if (null != url) {
            return new InputSource(url.toString());
        }
       
        //ok, try URL resolving
        if (baseURI != null) {
            try {
                url = new URL(baseURI);
                url = new URL(url, location);
                InputStream ins = url.openStream();
                if (ins != null) {
                    InputSource src = new InputSource(ins);
                    src.setSystemId(url.toString());
                    return src;
                }
            } catch (MalformedURLException e) {
                //ignore
            } catch (IOException e) {
                //ignore
            }
        }
       
        /*
        System.out.println(baseURI);
        System.out.println(location);
        System.out.println(uri);
        if (baseURI != null) {
            System.out.println(base);
            System.out.println(resolved);
        }
        */
       
        throw new ConfigurationException(new Message("SCHEMA_LOCATION_ERROR_EXC", LOG, location));
    }

    // ErrorHandler interface

    static class TypeSchemaErrorHandler implements ErrorHandler {

        public void error(SAXParseException exception) throws SAXParseException {
            throw exception;
        }

        public void fatalError(SAXParseException exception) throws SAXParseException {
            throw exception;
        }

        public void warning(SAXParseException exception) throws SAXParseException {
            throw exception;
        }
    }
   
    static final class SchemaInput implements LSInput {
        String type;
        String namespaceURI;
        String publicId;
        String systemId;
        String baseURI;
        InputStream is;
       
        SchemaInput(String t, String nsuri, String pid, String sid, String buri) {
            type = t;
            namespaceURI = nsuri;
            publicId = pid;
            systemId = sid;
            baseURI = buri;
        }
       
        public String getBaseURI() {
            return baseURI;
        }

        public InputStream getByteStream() {
            return is;
        }

        public boolean getCertifiedText() {
            return false;
        }

        public Reader getCharacterStream() {
            return null;
        }

        public String getEncoding() {
            return null;
        }

        public String getPublicId() {
            return publicId;
        }

        public String getStringData() {
            return null;
        }

        public String getSystemId() {
            return systemId;
        }

        public void setBaseURI(String buri) {
            baseURI = buri;
        }

        public void setByteStream(InputStream byteStream) {
            is = byteStream;
        }

        public void setCertifiedText(boolean certifiedText) {
        }

        public void setCharacterStream(Reader characterStream) {
        }

        public void setEncoding(String encoding) {
        }

        public void setPublicId(String pid) {
            publicId = pid;
        }

        public void setStringData(String stringData) {
        }

        public void setSystemId(String sid) {
            systemId = sid;
        }
           
    }
}
TOP

Related Classes of org.objectweb.celtix.configuration.impl.TypeSchema$TypeSchemaErrorHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.