Package org.apache.tuscany.sca.common.xml.stax

Source Code of org.apache.tuscany.sca.common.xml.stax.StAXHelper$Attribute

/*
* 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);
    }

}
TOP

Related Classes of org.apache.tuscany.sca.common.xml.stax.StAXHelper$Attribute

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.