summaryrefslogtreecommitdiffstats
path: root/sca-java-2.x/tags/2.0.1-RC1/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/stax/StAXHelper.java
diff options
context:
space:
mode:
Diffstat (limited to 'sca-java-2.x/tags/2.0.1-RC1/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/stax/StAXHelper.java')
-rw-r--r--sca-java-2.x/tags/2.0.1-RC1/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/stax/StAXHelper.java573
1 files changed, 573 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0.1-RC1/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/stax/StAXHelper.java b/sca-java-2.x/tags/2.0.1-RC1/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/stax/StAXHelper.java
new file mode 100644
index 0000000000..d7c85f01b5
--- /dev/null
+++ b/sca-java-2.x/tags/2.0.1-RC1/modules/common-xml/src/main/java/org/apache/tuscany/sca/common/xml/stax/StAXHelper.java
@@ -0,0 +1,573 @@
+/*
+ * 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.common.xml.stax;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.stream.StreamFilter;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tuscany.sca.common.xml.dom.DOMHelper;
+import org.apache.tuscany.sca.common.xml.stax.impl.StAX2SAXAdapter;
+import org.apache.tuscany.sca.common.xml.stax.impl.XMLStreamSerializer;
+import org.apache.tuscany.sca.common.xml.stax.reader.DOMXMLStreamReader;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.FactoryExtensionPoint;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * Helper class for StAX
+ * @tuscany.spi.extension.asclient
+ */
+public class StAXHelper {
+ private final XMLInputFactory inputFactory;
+ private final XMLOutputFactory outputFactory;
+ private final DOMHelper domHelper;
+
+ public StAXHelper(ExtensionPointRegistry registry) {
+ FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class);
+ factories.getFactory(XMLInputFactory.class);
+ inputFactory = factories.getFactory(XMLInputFactory.class);
+ outputFactory = factories.getFactory(XMLOutputFactory.class);
+ outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ domHelper = utilities.getUtility(DOMHelper.class);
+ }
+
+ public static StAXHelper getInstance(ExtensionPointRegistry registry) {
+ UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+ return utilities.getUtility(StAXHelper.class);
+ }
+
+ /**
+ * @param inputFactory
+ * @param outputFactory
+ * @param domHelper
+ */
+ public StAXHelper(XMLInputFactory inputFactory, XMLOutputFactory outputFactory, DOMHelper domHelper) {
+ super();
+ this.inputFactory = inputFactory;
+ this.outputFactory = outputFactory;
+ if (outputFactory != null) {
+ this.outputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
+ }
+ this.domHelper = domHelper;
+ }
+
+ public XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException {
+ return inputFactory.createXMLStreamReader(inputStream);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException {
+ return inputFactory.createXMLStreamReader(reader);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException {
+ return inputFactory.createXMLStreamReader(source);
+ }
+
+ public XMLStreamReader createXMLStreamReader(Node node) throws XMLStreamException {
+ /*
+ // DOMSource is not supported by the XMLInputFactory from JDK 6
+ DOMSource source = new DOMSource(node);
+ return createXMLStreamReader(source);
+ */
+ return new DOMXMLStreamReader(node);
+ }
+
+ public XMLStreamReader createXMLStreamReader(String string) throws XMLStreamException {
+ StringReader reader = new StringReader(string);
+ return createXMLStreamReader(reader);
+ }
+
+ private static InputStream openStream(URL url) throws IOException {
+ URLConnection connection = url.openConnection();
+ if (connection instanceof JarURLConnection) {
+ // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5041014
+ connection.setUseCaches(false);
+ }
+ InputStream is = connection.getInputStream();
+ return is;
+ }
+
+ public XMLStreamReader createXMLStreamReader(URL url) throws XMLStreamException {
+ try {
+ // Set up a StreamSource from the url, since this has an associated URL that
+ // can be used by the parser to find references to other files such as DTDs
+ StreamSource scdlSource = new StreamSource( openStream(url), url.toString() );
+ return inputFactory.createXMLStreamReader(scdlSource);
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ public String saveAsString(XMLStreamReader reader) throws XMLStreamException {
+ StringWriter writer = new StringWriter();
+ save(reader, writer);
+ return writer.toString();
+ }
+
+ public void save(XMLStreamReader reader, OutputStream outputStream) throws XMLStreamException {
+ XMLStreamWriter streamWriter = createXMLStreamWriter(outputStream);
+ save(reader, streamWriter);
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(OutputStream outputStream) throws XMLStreamException {
+ return outputFactory.createXMLStreamWriter(outputStream);
+ }
+
+ public void save(XMLStreamReader reader, Writer writer) throws XMLStreamException {
+ XMLStreamWriter streamWriter = createXMLStreamWriter(writer);
+ save(reader, streamWriter);
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(Writer writer) throws XMLStreamException {
+ return outputFactory.createXMLStreamWriter(writer);
+ }
+
+ public Node saveAsNode(XMLStreamReader reader) throws XMLStreamException {
+ // woodstox 3.2.4 fails due to http://jira.codehaus.org/browse/WSTX-144
+ // this issue has been fixed in woodstox 3.2.9
+ // We can use the commented code once we move to woodstox 3.2.9
+ /*
+ XMLStreamSerializer serializer = new XMLStreamSerializer();
+ Document document = domHelper.newDocument();
+ DOMResult result = new DOMResult(document);
+ XMLStreamWriter streamWriter = createXMLStreamWriter(result);
+ serializer.serialize(reader, streamWriter);
+ streamWriter.flush();
+ return result.getNode();
+ */
+ Document root = domHelper.newDocument();
+ ContentHandler handler = domHelper.createContentHandler(root);
+ try {
+ saveAsSAX(reader, handler);
+ } catch (SAXException e) {
+ throw new XMLStreamException(e);
+ }
+ return root;
+ }
+
+ public XMLStreamWriter createXMLStreamWriter(Result result) throws XMLStreamException {
+ return outputFactory.createXMLStreamWriter(result);
+ }
+
+ public void save(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
+ XMLStreamSerializer serializer = new XMLStreamSerializer(isReparingNamespaces());
+ serializer.serialize(reader, writer);
+ writer.flush();
+ }
+
+ public void saveAsSAX(XMLStreamReader reader, ContentHandler contentHandler) throws XMLStreamException,
+ SAXException {
+ new StAX2SAXAdapter(false).parse(reader, contentHandler);
+ }
+
+ /**
+ * @param url
+ * @param element
+ * @param attribute
+ * @param rootOnly
+ * @return
+ * @throws IOException
+ * @throws XMLStreamException
+ */
+ public String readAttribute(URL url, QName element, String attribute) throws IOException, XMLStreamException {
+ if (attribute == null) {
+ attribute = "targetNamespace";
+ }
+ XMLStreamReader reader = createXMLStreamReader(url);
+ try {
+ return readAttributeFromRoot(reader, element, attribute);
+ } finally {
+ reader.close();
+ }
+ }
+
+ public List<String> readAttributes(URL url, QName element, String attribute) throws IOException, XMLStreamException {
+ if (attribute == null) {
+ attribute = "targetNamespace";
+ }
+ XMLStreamReader reader = createXMLStreamReader(url);
+ try {
+ Attribute attr = new Attribute(element, attribute);
+ return readAttributes(reader, attr)[0].getValues();
+ } finally {
+ reader.close();
+ }
+ }
+
+ /**
+ * Returns the boolean value of an attribute.
+ * @param reader
+ * @param name
+ * @return
+ */
+ public static Boolean getAttributeAsBoolean(XMLStreamReader reader, String name) {
+ String value = reader.getAttributeValue(null, name);
+ if (value == null) {
+ return null;
+ }
+ return Boolean.valueOf(value);
+ }
+
+ /**
+ * Returns the QName value of an attribute.
+ * @param reader
+ * @param name
+ * @return
+ */
+ public static QName getAttributeAsQName(XMLStreamReader reader, String name) {
+ String qname = reader.getAttributeValue(null, name);
+ return getValueAsQName(reader, qname);
+ }
+
+ /**
+ * Returns the value of an attribute as a list of QNames.
+ * @param reader
+ * @param name
+ * @return
+ */
+ public static List<QName> getAttributeAsQNames(XMLStreamReader reader, String name) {
+ String value = reader.getAttributeValue(null, name);
+ if (value != null) {
+ List<QName> qnames = new ArrayList<QName>();
+ for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) {
+ qnames.add(getValueAsQName(reader, tokens.nextToken()));
+ }
+ return qnames;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * Returns a QName from a string.
+ * @param reader
+ * @param value
+ * @return
+ */
+ public static QName getValueAsQName(XMLStreamReader reader, String value) {
+ if (value != null) {
+ int index = value.indexOf(':');
+ String prefix = index == -1 ? "" : value.substring(0, index);
+ String localName = index == -1 ? value : value.substring(index + 1);
+ String ns = reader.getNamespaceContext().getNamespaceURI(prefix);
+ if (ns == null) {
+ ns = "";
+ }
+ return new QName(ns, localName, prefix);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns the string value of an attribute.
+ * @param reader
+ * @param name
+ * @return
+ */
+ public static String getAttributeAsString(XMLStreamReader reader, String name) {
+ return reader.getAttributeValue(null, name);
+ }
+
+ /**
+ * TUSCANY-242
+ *
+ * Returns the URI value of an attribute as a string and first applies the
+ * URI whitespace processing as defined in section 4.3.6 of XML Schema Part2: Datatypes
+ * [http://www.w3.org/TR/xmlschema-2/#rf-facets]. anyURI is defined with the following
+ * XSD:
+ * <xs:simpleType name="anyURI" id="anyURI">
+ * <xs:restriction base="xs:anySimpleType">
+ * <xs:whiteSpace value="collapse" fixed="true" id="anyURI.whiteSpace"/>
+ * </xs:restriction>
+ * </xs:simpleType>
+ *
+ * The <xs:whiteSpace value="collapse"/> constraining facet is defined as follows
+ *
+ * replace
+ * All occurrences of #x9 (tab), #xA (line feed) and #xD (carriage return) are replaced with #x20 (space)
+ * collapse
+ * After the processing implied by replace, contiguous sequences of #x20's are collapsed to a single #x20,
+ * and leading and trailing #x20's are removed
+ *
+ * It seems that the StAX parser does apply this rule so we do it here.
+ *
+ * @param reader
+ * @param name
+ * @return
+ */
+ public static String getAttributeAsURIString(XMLStreamReader reader, String name) {
+ // get the basic string value
+ String uri = reader.getAttributeValue(null, name);
+
+ // apply the "collapse" rule
+ if (uri != null){
+ // turn tabs, line feeds and carriage returns into spaces
+ uri = uri.replace('\t', ' ');
+ uri = uri.replace('\n', ' ');
+ uri = uri.replace('\r', ' ');
+
+ // remote leading and trailing spaces. Other whitespace
+ // has already been converted to spaces above
+ uri = uri.trim();
+
+ // collapse any contiguous spaces into a single space
+ StringBuilder sb= new StringBuilder(uri.length());
+ boolean spaceFound= false;
+ for(int i=0; i< uri.length(); ++i){
+ char c= uri.charAt(i);
+ if(c == ' '){
+ if(!spaceFound){
+ sb.append(c);
+ spaceFound = true;
+ } else {
+ // collapse the space by ignoring it
+ }
+ }else{
+ sb.append(c);
+ spaceFound= false;
+ }
+ }
+ uri = sb.toString();
+ }
+
+ return uri;
+ }
+
+ /**
+ * Returns the value of xsi:type attribute
+ * @param reader The XML stream reader
+ * @return The QName of the type, if the attribute is not present, null is
+ * returned.
+ */
+ public static QName getXSIType(XMLStreamReader reader) {
+ String qname = reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
+ return getValueAsQName(reader, qname);
+ }
+
+ /**
+ * Test if an attribute is explicitly set
+ * @param reader
+ * @param name
+ * @return
+ */
+ public static boolean isAttributePresent(XMLStreamReader reader, String name) {
+ return reader.getAttributeValue(null, name) != null;
+ }
+
+ /**
+ * Advance the stream to the next END_ELEMENT event skipping any nested
+ * content.
+ * @param reader the reader to advance
+ * @throws XMLStreamException if there was a problem reading the stream
+ */
+ public static void skipToEndElement(XMLStreamReader reader) throws XMLStreamException {
+ int depth = 0;
+ while (reader.hasNext()) {
+ int event = reader.next();
+ if (event == XMLStreamConstants.START_ELEMENT) {
+ depth++;
+ } else if (event == XMLStreamConstants.END_ELEMENT) {
+ if (depth == 0) {
+ return;
+ }
+ depth--;
+ }
+ }
+ }
+
+ private Attribute[] readAttributes(XMLStreamReader reader, AttributeFilter filter) throws XMLStreamException {
+ XMLStreamReader newReader = inputFactory.createFilteredReader(reader, filter);
+ while (filter.proceed() && newReader.hasNext()) {
+ newReader.next();
+ }
+ return filter.attributes;
+ }
+
+ public Attribute[] readAttributes(URL url, Attribute... attributes) throws XMLStreamException {
+ XMLStreamReader reader = createXMLStreamReader(url);
+ try {
+ return readAttributes(reader, attributes);
+ } finally {
+ reader.close();
+ }
+ }
+
+ public Attribute[] readAttributes(XMLStreamReader reader, Attribute... attributes) throws XMLStreamException {
+ return readAttributes(reader, new AttributeFilter(false, attributes));
+ }
+
+ private String readAttributeFromRoot(XMLStreamReader reader, Attribute filter) throws XMLStreamException {
+ Attribute[] attrs = readAttributes(reader, new AttributeFilter(true, filter));
+ List<String> values = attrs[0].getValues();
+ if (values.isEmpty()) {
+ return null;
+ } else {
+ return values.get(0);
+ }
+ }
+
+ public String readAttributeFromRoot(XMLStreamReader reader, QName element, String attributeName)
+ throws XMLStreamException {
+ Attribute filter = new Attribute(element, attributeName);
+ return readAttributeFromRoot(reader, filter);
+ }
+
+ /**
+ *
+ * @tuscany.spi.extension.asclient
+ *
+ */
+ public static class Attribute {
+ private QName element;
+ private String name;
+ private List<String> values = new ArrayList<String>();
+
+ /**
+ * @param element
+ * @param name
+ */
+ public Attribute(QName element, String name) {
+ super();
+ this.element = element;
+ this.name = name;
+ }
+
+ public List<String> getValues() {
+ return values;
+ }
+
+ }
+
+ private static class AttributeFilter implements StreamFilter {
+ private boolean proceed = true;
+ private Attribute[] attributes;
+ private boolean rootOnly;
+
+ /**
+ * @param rootOnly
+ */
+ public AttributeFilter(boolean rootOnly, Attribute... attributes) {
+ super();
+ this.rootOnly = rootOnly;
+ this.attributes = attributes;
+ }
+
+ public boolean accept(XMLStreamReader reader) {
+ if (attributes == null || attributes.length == 0) {
+ proceed = false;
+ return true;
+ }
+ if (reader.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ QName name = reader.getName();
+ for (Attribute attr : attributes) {
+ if (attr.element.equals(name)) {
+ attr.values.add(reader.getAttributeValue(null, attr.name));
+ }
+ }
+ if (rootOnly) {
+ proceed = false;
+ }
+ }
+ return true;
+ }
+
+ public boolean proceed() {
+ return proceed;
+ }
+
+ }
+
+ public XMLInputFactory getInputFactory() {
+ return inputFactory;
+ }
+
+ private boolean isReparingNamespaces() {
+ if (outputFactory == null) {
+ return Boolean.TRUE;
+ }
+ return outputFactory.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES) == Boolean.TRUE;
+ }
+
+ public XMLOutputFactory getOutputFactory() {
+ return outputFactory;
+ }
+
+ public String writeAttribute(XMLStreamWriter writer, QName name, String value) throws XMLStreamException {
+ return writeAttribute(writer, name.getPrefix(), name.getLocalPart(), name.getNamespaceURI(), value);
+ }
+
+ public String writeAttribute(XMLStreamWriter writer,
+ String prefix,
+ String localName,
+ String namespaceURI,
+ String value) throws XMLStreamException {
+ if (value == null) {
+ return null;
+ }
+ XMLStreamSerializer serializer = new XMLStreamSerializer(isReparingNamespaces());
+ return serializer.writeAttribute(writer, prefix, localName, namespaceURI, value);
+ }
+
+ public void writeStartElement(XMLStreamWriter writer, QName name) throws XMLStreamException {
+ writeStartElement(writer, name.getPrefix(), name.getLocalPart(), name.getNamespaceURI());
+ }
+
+ public void writeStartElement(XMLStreamWriter writer, String prefix, String localName, String namespaceURI)
+ throws XMLStreamException {
+ XMLStreamSerializer serializer = new XMLStreamSerializer(isReparingNamespaces());
+ serializer.writeStartElement(writer, prefix, localName, namespaceURI);
+ }
+
+ public String writeNamespace(XMLStreamWriter writer, String prefix, String namespaceURI) throws XMLStreamException {
+ XMLStreamSerializer serializer = new XMLStreamSerializer(isReparingNamespaces());
+ return serializer.writeNamespace(writer, prefix, namespaceURI);
+ }
+
+}