From 132aa8a77685ec92bc90c03f987650d275a7b639 Mon Sep 17 00:00:00 2001 From: lresende Date: Mon, 30 Sep 2013 06:59:11 +0000 Subject: 2.0.1 RC1 release tag git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1527464 13f79535-47bb-0310-9956-ffa450edef68 --- .../DefaultValidatingXMLInputFactory.java | 465 +++++++++++++++++++++ 1 file changed, 465 insertions(+) create mode 100644 sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java') diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java new file mode 100644 index 0000000000..cf8c8fbf17 --- /dev/null +++ b/sca-java-2.x/tags/2.0.1-RC1/modules/contribution/src/main/java/org/apache/tuscany/sca/contribution/processor/DefaultValidatingXMLInputFactory.java @@ -0,0 +1,465 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.tuscany.sca.contribution.processor; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.EventFilter; +import javax.xml.stream.StreamFilter; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLReporter; +import javax.xml.stream.XMLResolver; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.XMLEventAllocator; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.apache.tuscany.sca.assembly.xsd.Constants; +import org.apache.tuscany.sca.common.xml.XMLDocumentHelper; +import org.apache.tuscany.sca.common.xml.stax.StAXHelper; +import org.apache.tuscany.sca.core.DefaultExtensionPointRegistry; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.extensibility.ClassLoaderContext; +import org.apache.tuscany.sca.monitor.Monitor; +import org.apache.tuscany.sca.monitor.MonitorFactory; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSResourceResolver; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * Default implementation of an XMLInputFactory that creates validating + * XMLStreamReaders. + * + * @version $Rev$ $Date$ + */ +public class DefaultValidatingXMLInputFactory extends ValidatingXMLInputFactory implements LSResourceResolver { + private ExtensionPointRegistry registry; + private XMLInputFactory inputFactory; + private DocumentBuilderFactory documentBuilderFactory; + private DOMImplementationLS ls; + private ValidationSchemaExtensionPoint schemas; + private MonitorFactory monitorFactory; + private boolean initialized; + private boolean hasSchemas; + private Schema aggregatedSchema; + private StAXHelper helper; + + public DefaultValidatingXMLInputFactory(ExtensionPointRegistry registry) { + this.registry = registry; + FactoryExtensionPoint factoryExtensionPoint = registry.getExtensionPoint(FactoryExtensionPoint.class); + this.inputFactory = factoryExtensionPoint.getFactory(XMLInputFactory.class); + this.documentBuilderFactory = factoryExtensionPoint.getFactory(DocumentBuilderFactory.class); + this.schemas = registry.getExtensionPoint(ValidationSchemaExtensionPoint.class); + this.monitorFactory = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(MonitorFactory.class); + this.helper = StAXHelper.getInstance(registry); + } + + /** + * Constructs a new XMLInputFactory. + * + * @param inputFactory + * @param schemas + */ + // FOR Test only + public DefaultValidatingXMLInputFactory(XMLInputFactory inputFactory, ValidationSchemaExtensionPoint schemas) { + this.inputFactory = inputFactory; + this.schemas = schemas; + this.registry = new DefaultExtensionPointRegistry(); + } + + /** + * Report a exception. + * + * @param problems + * @param message + * @param model + */ + private void error(Monitor monitor, String message, Object model, Throwable ex) { + Monitor.error(monitor, this, "contribution-validation-messages", message, ex); + } + + private void warn(Monitor monitor, String message, Object model, Throwable ex) { + Monitor.warning(monitor, this, "contribution-validation-messages", message, ex); + } + + public static final QName XSD = new QName(XMLConstants.W3C_XML_SCHEMA_NS_URI, "schema"); + + private Collection aggregate(URL... urls) throws IOException, XMLStreamException { + if (urls.length == 1) { + return Collections.singletonList(new SAXSource(XMLDocumentHelper.getInputSource(urls[0]))); + } + Map> map = new HashMap>(); + + for (URL url : urls) { + String tns = helper.readAttribute(url, XSD, "targetNamespace"); + Collection collection = map.get(tns); + if (collection == null) { + collection = new HashSet(); + map.put(tns, collection); + } + collection.add(url); + } + List sources = new ArrayList(); + for (Map.Entry> e : map.entrySet()) { + if (e.getValue().size() == 1) { + sources.add(new SAXSource(XMLDocumentHelper.getInputSource(e.getValue().iterator().next()))); + } else { + StringBuffer xsd = new StringBuffer(""); + for (URL url : e.getValue()) { + xsd.append(""); + } + xsd.append(""); + SAXSource source = new SAXSource(new InputSource(new StringReader(xsd.toString()))); + sources.add(source); + } + } + return sources; + } + + /** + * Initialize the registered schemas and create an aggregated schema for + * validation. + * + * @param monitor TODO + */ + private synchronized void initializeSchemas(Monitor monitor) { + if (initialized) { + return; + } + initialized = true; + + // Load the XSDs registered in the validation schema extension point + try { + List uris = schemas.getSchemas(); + int n = uris.size(); + if (n == 0) { + return; + } else { + hasSchemas = true; + } + + // For bundleresource: URL(s), this URL constructor + // can require org.osgi.framework.AdminPermission + final List urisCopy = uris; + + URL[] urls = null; + try { + urls = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public URL[] run() throws MalformedURLException { + URL[] urlsTemp = new URL[urisCopy.size()]; + for (int i = 0; i < urlsTemp.length; i++) { + urlsTemp[i] = new URL(urisCopy.get(i)); + } + return urlsTemp; + } + }); + } catch (PrivilegedActionException e) { + warn(monitor, "PrivilegedActionException", schemas, (MalformedURLException)e.getException()); + throw (MalformedURLException)e.getException(); + } + + final Collection sources = aggregate(urls); + + final SchemaFactory schemaFactory = newSchemaFactory(); + + DOMImplementation impl = null; + try { + impl = documentBuilderFactory.newDocumentBuilder().getDOMImplementation(); + } catch (ParserConfigurationException e) { + // Ignore + } + if (impl instanceof DOMImplementationLS) { + ls = (DOMImplementationLS)impl; + schemaFactory.setResourceResolver(this); + } + // Allow privileged access to check files. Requires FilePermission + // in security policy. + try { + aggregatedSchema = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Schema run() throws SAXException { + return schemaFactory.newSchema(sources.toArray(new Source[sources.size()])); + } + }); + + } catch (PrivilegedActionException e) { + warn(monitor, "PrivilegedActionException", schemaFactory, (SAXException)e.getException()); + hasSchemas = false; + throw (SAXException)e.getException(); + } + + } catch (SAXException e) { + // IllegalStateException ie = new IllegalStateException(e); + // error("IllegalStateException", schemas, ie); + // throw ie; + } catch (Throwable e) { + // FIXME Log this, some old JDKs don't support XMLSchema validation + warn(monitor, e.getMessage(), schemas, e); + hasSchemas = false; + } + } + + /** + * For OSGi: Create a SchemaFactory in the context of service provider + * classloaders + * + * @return + */ + private SchemaFactory newSchemaFactory() { + + SchemaFactory retVal = AccessController.doPrivileged(new PrivilegedAction() { + public SchemaFactory run() { + ClassLoader cl = ClassLoaderContext.setContextClassLoader(getClass().getClassLoader(), + registry.getServiceDiscovery(), + SchemaFactory.class, + TransformerFactory.class, + SAXParserFactory.class, + DocumentBuilderFactory.class + ); + + try { + // Create an aggregated validation schemas from all the XSDs + return SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + } finally { + if (cl != null) { + Thread.currentThread().setContextClassLoader(cl); + } + } + } + }); + + return retVal; + } + + @Override + public XMLEventReader createFilteredReader(XMLEventReader arg0, EventFilter arg1) throws XMLStreamException { + return inputFactory.createFilteredReader(arg0, arg1); + } + + @Override + public XMLStreamReader createFilteredReader(XMLStreamReader arg0, StreamFilter arg1) throws XMLStreamException { + return inputFactory.createFilteredReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream arg0, String arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(InputStream arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLEventReader createXMLEventReader(Reader arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLEventReader createXMLEventReader(Source arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLEventReader createXMLEventReader(String arg0, InputStream arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(String arg0, Reader arg1) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0, arg1); + } + + @Override + public XMLEventReader createXMLEventReader(XMLStreamReader arg0) throws XMLStreamException { + return inputFactory.createXMLEventReader(arg0); + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream arg0, String arg1) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, + monitor); + } else { + return inputFactory.createXMLStreamReader(arg0, arg1); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(InputStream arg0) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(Reader arg0) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(Source arg0) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0), aggregatedSchema, monitor); + } else { + return inputFactory.createXMLStreamReader(arg0); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(String arg0, InputStream arg1) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, + monitor); + } else { + return inputFactory.createXMLStreamReader(arg0, arg1); + } + } + + @Override + public XMLStreamReader createXMLStreamReader(String arg0, Reader arg1) throws XMLStreamException { + Monitor monitor = monitorFactory.getContextMonitor(); + initializeSchemas(monitor); + if (hasSchemas) { + return new ValidatingXMLStreamReader(inputFactory.createXMLStreamReader(arg0, arg1), aggregatedSchema, + monitor); + } else { + return inputFactory.createXMLStreamReader(arg0, arg1); + } + } + + @Override + public XMLEventAllocator getEventAllocator() { + return inputFactory.getEventAllocator(); + } + + @Override + public Object getProperty(String arg0) throws IllegalArgumentException { + return inputFactory.getProperty(arg0); + } + + @Override + public XMLReporter getXMLReporter() { + return inputFactory.getXMLReporter(); + } + + @Override + public XMLResolver getXMLResolver() { + return inputFactory.getXMLResolver(); + } + + @Override + public boolean isPropertySupported(String arg0) { + return inputFactory.isPropertySupported(arg0); + } + + @Override + public void setEventAllocator(XMLEventAllocator arg0) { + inputFactory.setEventAllocator(arg0); + } + + @Override + public void setProperty(String arg0, Object arg1) throws IllegalArgumentException { + inputFactory.setProperty(arg0, arg1); + } + + @Override + public void setXMLReporter(XMLReporter arg0) { + inputFactory.setXMLReporter(arg0); + } + + @Override + public void setXMLResolver(XMLResolver arg0) { + inputFactory.setXMLResolver(arg0); + } + + public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) { + String key = null; + if ("http://www.w3.org/2001/XMLSchema".equals(type)) { + key = namespaceURI; + } else if ("http://www.w3.org/TR/REC-xml".equals(type)) { + key = publicId; + } + URL url = Constants.CACHED_XSDS.get(key); + if (url != null && !Constants.SCA11_NS.equals(namespaceURI)) { + systemId = url.toString(); + } else if (url != null && systemId == null) { + systemId = url.toString(); + } + + LSInput input = ls.createLSInput(); + input.setBaseURI(baseURI); + input.setPublicId(publicId); + input.setSystemId(systemId); + return input; + } + +} -- cgit v1.2.3