Subversion Repositories XServices

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

/*
 *   Copyright 2013 Brian Rosenberger (Brutex Network)
 *
 *   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 net.brutex.xservices.ws.impl;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.jws.WebService;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import net.brutex.xservices.types.NamespaceListType;
import net.brutex.xservices.types.NamespaceType;
import net.brutex.xservices.types.ant.FileResource;
import net.brutex.xservices.ws.XServicesFault;
import net.brutex.xservices.ws.XmlService;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMCloneOptions;
import org.apache.axiom.om.OMContainer;
import org.apache.axiom.om.OMDocument;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.log4j.Logger;
import org.jaxen.JaxenException;
import org.jaxen.SimpleNamespaceContext;

/**
 * @author Brian Rosenberger, bru(at)brutex.de
 * 
 */
@WebService(targetNamespace = "http://ws.xservices.brutex.net", endpointInterface = "net.brutex.xservices.ws.XmlService", serviceName = "XmlService")
public class XmlServiceImpl implements XmlService {
        final Logger logger = Logger.getLogger(XmlServiceImpl.class);

        public String insertNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
                try {
                        AXIOMXPath axp = new AXIOMXPath(xpath);
                        InputStream is = res.getAntResource(null).getInputStream();
                        OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
                                        .getDocument();
                        OMDocument fragdoc = null;
                        if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
                                fragdoc = OMXMLBuilderFactory.createOMBuilder(
                                                new StringReader("<XS>" + xmlFragment + "</XS>"))
                                                .getDocument();
                        } else {
                                throw new XServicesFault("No xmldata to insert.");
                        }

                        // Initialize XPath context
                        SimpleNamespaceContext context = new SimpleNamespaceContext();
                        for (NamespaceType ns : nsList.getNamespaces()) {
                                context.addNamespace(ns.getPrefix(), ns.getUri().toString());
                                this.logger.debug(Messages.getString("XmlService.0")
                                                + ns.getPrefix() + "=\"" + ns.getUri().toString()
                                                + "\"'");
                        }
                        axp.setNamespaceContext(context);
                        axp.addNamespaces(fragdoc.getOMDocumentElement());

                        OMDocument document = insertNodes(sourcedoc, axp, fragdoc);

                        StringWriter sw = new StringWriter();
                        XMLOutputFactory xof = XMLOutputFactory.newInstance();
                        XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
                        document.serialize(writer);

                        this.logger.trace(sw.getBuffer().toString());
                        return sw.getBuffer().toString();
                } catch (JaxenException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                } catch (IOException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                } catch (XMLStreamException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                }
        }

        public String replaceNodesFromFile(FileResource res, NamespaceListType nsList, String xpath, String replace) throws XServicesFault {
                try {
                        AXIOMXPath axp = new AXIOMXPath(xpath);

                        InputStream is = res.getAntResource(null).getInputStream();

                        XMLStreamReader reader = OMXMLBuilderFactory.createOMBuilder(is)
                                        .getDocument().getXMLStreamReader(false);
                        StringWriter sw = new StringWriter();
                        OMAbstractFactory.getOMFactory();

                        while (reader.hasNext()) {
                                if (reader.getEventType() == 1) {
                                        OMElement element = OMXMLBuilderFactory
                                                        .createStAXOMBuilder(reader).getDocumentElement();
                                        element.build();

                                        SimpleNamespaceContext context = new SimpleNamespaceContext();
                                        for (NamespaceType ns : nsList.getNamespaces()) {
                                                context.addNamespace(ns.getPrefix(), ns.getUri()
                                                                .toString());
                                                this.logger.debug(Messages.getString(
                                                                "XmlService.adding_namespace",
                                                                new Object[] { ns.getPrefix(),
                                                                                ns.getUri().toString() }));
                                        }
                                        axp.setNamespaceContext(context);
                                        axp.addNamespaces(element);

                                        OMDocument xfrag = OMXMLBuilderFactory.createOMBuilder(
                                                        new StringReader("<XS>" + replace + "</XS>"))
                                                        .getDocument();
                                        xfrag.build();

                                        List list = axp.selectNodes(element);
                                        for (Iterator localIterator2 = list.iterator(); localIterator2
                                                        .hasNext();) {
                                                Object o = localIterator2.next();
                                                if (!(o instanceof OMNode))
                                                        throw new XServicesFault(
                                                                        "You must match a node to be replaced, but you matched something differen (attribute, etc.");
                                                OMNode node = (OMNode) o;

                                                Iterator<?> children = xfrag.getOMDocumentElement()
                                                                .getChildren();
                                                while (children.hasNext()) {
                                                        OMNode container = (OMNode) children.next();
                                                        node.insertSiblingAfter((OMNode) container
                                                                        .clone(new OMCloneOptions()));
                                                }
                                                node.detach();

                                                // node.insertSiblingAfter(AXIOMUtil.stringToOM(replace));

                                        }
                                        XMLOutputFactory xof = XMLOutputFactory.newInstance();
                                        XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
                                        element.serialize(writer);
                                        sw.flush();
                                } else {
                                        reader.next();
                                }
                        }
                        this.logger.trace(sw.getBuffer().toString());
                        return sw.getBuffer().toString();
                } catch (JaxenException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                } catch (IOException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                } catch (XMLStreamException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                }
        }

        public String replaceNodes(String source, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
                try {
                        AXIOMXPath axp = new AXIOMXPath(xpath);
                        InputStream is = new ByteArrayInputStream(source.getBytes());
                        OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
                                        .getDocument();
                        OMDocument fragdoc = null;
                        if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
                                fragdoc = OMXMLBuilderFactory.createOMBuilder(
                                                new StringReader("<XS>" + xmlFragment + "</XS>"))
                                                .getDocument();
                        } else {
                                throw new XServicesFault("No xmldata to insert.");
                        }

                        // Initialize XPath context
                        SimpleNamespaceContext context = new SimpleNamespaceContext();
                        for (NamespaceType ns : nsList.getNamespaces()) {
                                context.addNamespace(ns.getPrefix(), ns.getUri().toString());
                                this.logger.debug(Messages.getString("XmlService.0")
                                                + ns.getPrefix() + "=\"" + ns.getUri().toString()
                                                + "\"'");
                        }
                        axp.setNamespaceContext(context);
                        axp.addNamespaces(fragdoc.getOMDocumentElement());

                        OMDocument document = replaceNodes(sourcedoc, axp, fragdoc);

                        StringWriter sw = new StringWriter();
                        XMLOutputFactory xof = XMLOutputFactory.newInstance();
                        XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
                        document.serialize(writer);

                        this.logger.trace(sw.getBuffer().toString());
                        return sw.getBuffer().toString();
                } catch (JaxenException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                } catch (XMLStreamException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                }
        }
        
        public String insertNodes(String source, NamespaceListType nsList, String xpath, String xmlFragment) throws XServicesFault {
                try {
                        AXIOMXPath axp = new AXIOMXPath(xpath);
                        InputStream is = new ByteArrayInputStream(source.getBytes());
                        OMDocument sourcedoc = OMXMLBuilderFactory.createOMBuilder(is)
                                        .getDocument();
                        OMDocument fragdoc = null;
                        if ((xmlFragment != null) && (new String(xmlFragment).length() > 0)) {
                                fragdoc = OMXMLBuilderFactory.createOMBuilder(
                                                new StringReader("<XS>" + xmlFragment + "</XS>"))
                                                .getDocument();
                        } else {
                                throw new XServicesFault("No xmldata to insert.");
                        }

                        // Initialize XPath context
                        SimpleNamespaceContext context = new SimpleNamespaceContext();
                        for (NamespaceType ns : nsList.getNamespaces()) {
                                context.addNamespace(ns.getPrefix(), ns.getUri().toString());
                                this.logger.debug(Messages.getString("XmlService.0")
                                                + ns.getPrefix() + "=\"" + ns.getUri().toString()
                                                + "\"'");
                        }
                        axp.setNamespaceContext(context);
                        axp.addNamespaces(fragdoc.getOMDocumentElement());

                        OMDocument document = insertNodes(sourcedoc, axp, fragdoc);

                        StringWriter sw = new StringWriter();
                        XMLOutputFactory xof = XMLOutputFactory.newInstance();
                        XMLStreamWriter writer = xof.createXMLStreamWriter(sw);
                        document.serialize(writer);

                        this.logger.trace(sw.getBuffer().toString());
                        return sw.getBuffer().toString();
                } catch (JaxenException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                } catch (XMLStreamException e) {
                        e.printStackTrace();
                        throw new XServicesFault(e);
                }
        }

        public String wrapInCDATA(String data) throws XServicesFault {
                String result ="";
                String[] tokens = data.split("\\]\\]>", -1);
                
                for(int i=0; i<tokens.length; i++) {
                        result +=  tokens[i];
                        if (i+1 < tokens.length ) result += "]]]]><![CDATA[>";
                }
                
                result = "<![CDATA[" + result + "]]>";
                return result;
        }
        private OMDocument insertNodes(OMDocument xmldocument, AXIOMXPath axp,OMDocument xmlfragment) throws XServicesFault {
                List<?> olist = null;
                try {
                        olist = axp.selectNodes(xmldocument.getOMDocumentElement());
                        this.logger.debug("XPath '" + axp.toString() + "' has "
                                        + olist.size() + " matches.");
                        this.logger.trace("XPath root expression is: '" + axp.debug()
                                        + "'.");
                } catch (JaxenException e) {
                        throw new XServicesFault(e.getMessage(), e);
                }
                if (olist.size() == 0)
                        throw new XServicesFault(Messages.getString("XmlService.no_match",
                                        new Object[] { axp.toString() }));

                // Prepare children to insert
                xmlfragment.build();

                // Determine what has been matched
                OMContainer match = null;
                for (Object o : olist) {
                        Iterator<?> children = xmlfragment.getOMDocumentElement()
                                        .getChildren();
                        if ((o instanceof OMNode)) {
                                OMNode node = (OMNode) o;
                                switch (node.getType()) {
                                case OMNode.ELEMENT_NODE:
                                        if ((o instanceof OMElement))
                                                match = (OMElement) o;
                                        if ((o instanceof OMDocument))
                                                match = ((OMDocument) o).getOMDocumentElement();
                                        this.logger.debug(Messages.getString("XmlService.8"));
                                        break;
                                case OMNode.TEXT_NODE:
                                        match = ((OMText) o).getParent();
                                        this.logger.debug(Messages.getString("XmlService.9"));
                                        break;
                                case OMNode.COMMENT_NODE:
                                        // match = node.getParent();
                                        match = (OMContainer) node;
                                        this.logger.debug(Messages.getString("XmlService.10"));
                                        break;
                                default:
                                        this.logger.error("XPath matched "
                                                        + o.getClass().getCanonicalName() + " Node Type:"
                                                        + node.getType());
                                        this.logger.error(Messages.getString("XmlService.11"));
                                        throw new XServicesFault(
                                                        Messages.getString("XmlService.12"));
                                }
                        } else {
                                this.logger.error("XPath matched "
                                                + o.getClass().getCanonicalName());
                                this.logger.error(Messages.getString("XmlService.11"));
                                throw new XServicesFault(Messages.getString("XmlService.12"));
                        }

                        while (children.hasNext()) {
                                OMNode container = (OMNode) children.next();
                                match.addChild((OMNode) container.clone(new OMCloneOptions()));
                        }
                }

                xmldocument.build();
                return xmldocument;
        }


        private OMDocument replaceNodes(OMDocument xmldocument, AXIOMXPath axp, OMDocument xmlfragment) throws XServicesFault {
                List<?> olist = null;
                try {
                        olist = axp.selectNodes(xmldocument.getOMDocumentElement());
                        this.logger.debug("XPath '" + axp.toString() + "' has "
                                        + olist.size() + " matches.");
                        this.logger.trace("XPath root expression is: '" + axp.debug()
                                        + "'.");
                } catch (JaxenException e) {
                        throw new XServicesFault(e.getMessage(), e);
                }
                if (olist.size() == 0)
                        throw new XServicesFault(Messages.getString("XmlService.no_match",
                                        new Object[] { axp.toString() }));

                // Prepare children to insert
                xmlfragment.build();

                // Determine what has been matched
                OMNode match = null;
                for (Object o : olist) {
                        Iterator<?> children = xmlfragment.getOMDocumentElement()
                                        .getChildren();
                        if ((o instanceof OMNode)) {
                                OMNode node = (OMNode) o;
                                switch (node.getType()) {
                                case OMNode.ELEMENT_NODE:
                                        if ((o instanceof OMElement))
                                                match = (OMElement) o;
                                        if ((o instanceof OMDocument))
                                                match = ((OMDocument) o).getOMDocumentElement();
                                        this.logger.debug(Messages.getString("XmlService.8"));
                                        break;
                                default:
                                        this.logger.error("XPath matched "
                                                        + o.getClass().getCanonicalName() + " Node Type:"
                                                        + node.getType());
                                        this.logger.error(Messages.getString("XmlService.11"));
                                        throw new XServicesFault(
                                                        Messages.getString("XmlService.12"));
                                }
                        } else {
                                this.logger.error("XPath matched "
                                                + o.getClass().getCanonicalName());
                                this.logger.error(Messages.getString("XmlService.11"));
                                throw new XServicesFault(Messages.getString("XmlService.12"));
                        }

                        while (children.hasNext()) {
                                OMNode container = (OMNode) children.next();
                                match.insertSiblingAfter((OMNode) container.clone(new OMCloneOptions()));
                        }
                        match.detach();
                }
                xmldocument.build();
                return xmldocument;
        }
}