001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.wsn.jbi;
018    
019    import java.util.concurrent.atomic.AtomicBoolean;
020    
021    import javax.xml.namespace.QName;
022    import javax.xml.XMLConstants;
023    import javax.xml.parsers.ParserConfigurationException;
024    import javax.xml.stream.XMLStreamReader;
025    import javax.xml.stream.XMLStreamException;
026    import javax.xml.transform.Source;
027    import javax.xml.transform.TransformerException;
028    import javax.xml.transform.dom.DOMSource;
029    
030    import org.w3c.dom.Document;
031    import org.w3c.dom.Element;
032    
033    import org.apache.servicemix.common.util.DOMUtil;
034    import org.apache.servicemix.jbi.jaxp.StaxSource;
035    import org.apache.servicemix.jbi.jaxp.FragmentStreamReader;
036    import org.apache.servicemix.jbi.jaxp.StAXSourceTransformer;
037    
038    /**
039     * Helper classes dealing with the WSDL 1.1 JBI wrapper
040     */
041    public class JbiWrapperHelper {
042    
043        public static final String WSDL11_WRAPPER_NAMESPACE = "http://java.sun.com/xml/ns/jbi/wsdl-11-wrapper";
044        public static final String WSDL11_WRAPPER_PREFIX = "jbi";
045        public static final String WSDL11_WRAPPER_MESSAGE_LOCALNAME = "message";
046        public static final QName WSDL11_WRAPPER_MESSAGE = new QName(WSDL11_WRAPPER_NAMESPACE, WSDL11_WRAPPER_MESSAGE_LOCALNAME, WSDL11_WRAPPER_PREFIX);
047        public static final String WSDL11_WRAPPER_MESSAGE_PREFIX = "msg";
048        public static final String WSDL11_WRAPPER_TYPE = "type";
049        public static final String WSDL11_WRAPPER_NAME = "name";
050        public static final String WSDL11_WRAPPER_VERSION = "version";
051        public static final String WSDL11_WRAPPER_PART_LOCALNAME = "part";
052        public static final QName WSDL11_WRAPPER_PART = new QName(WSDL11_WRAPPER_NAMESPACE, WSDL11_WRAPPER_PART_LOCALNAME, WSDL11_WRAPPER_PREFIX);
053    
054        private static final StAXSourceTransformer transformer = new StAXSourceTransformer();
055    
056        public static Document createDocument() throws ParserConfigurationException {
057            return transformer.createDocument();
058        }
059    
060        public static void wrap(Document doc) {
061            wrap(doc, null, null);
062        }
063    
064        public static void wrap(Document doc, QName type, String name) {
065            Element wrapperMsg = doc.createElementNS(WSDL11_WRAPPER_NAMESPACE, WSDL11_WRAPPER_PREFIX + ":" + WSDL11_WRAPPER_MESSAGE_LOCALNAME);
066            wrapperMsg.setAttribute(WSDL11_WRAPPER_VERSION, "1.0");
067            if (type != null) {
068                if (!XMLConstants.NULL_NS_URI.equals(type.getNamespaceURI())) {
069                    wrapperMsg.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, WSDL11_WRAPPER_MESSAGE_PREFIX, type.getNamespaceURI());
070                }
071                wrapperMsg.setAttribute(WSDL11_WRAPPER_TYPE, WSDL11_WRAPPER_MESSAGE_PREFIX + ":" + type.getLocalPart());
072            }
073            if (name != null) {
074                wrapperMsg.setAttribute(WSDL11_WRAPPER_NAME, name);
075            }
076            Element wrapperPart = doc.createElementNS(WSDL11_WRAPPER_NAMESPACE, WSDL11_WRAPPER_PREFIX + ":" + WSDL11_WRAPPER_PART_LOCALNAME);
077            wrapperMsg.appendChild(wrapperPart);
078            Element el = doc.getDocumentElement();
079            doc.replaceChild(wrapperMsg, el);
080            wrapperPart.appendChild(el);
081        }
082    
083        public static Source unwrap(Source source, AtomicBoolean isJbiWrapped) throws XMLStreamException, TransformerException {
084            if (source instanceof DOMSource) {
085                Element el = DOMUtil.getFirstChildElement(((DOMSource) source).getNode());
086                if (el == null) {
087                    throw new IllegalStateException("Unsupported DOMSource with no element");
088                }
089                if (WSDL11_WRAPPER_NAMESPACE.equals(el.getNamespaceURI()) && WSDL11_WRAPPER_MESSAGE_LOCALNAME.equals(el.getLocalName())) {
090                    el = DOMUtil.getFirstChildElement(el);
091                    if (el == null) {
092                        throw new IllegalStateException("JBI wrapper has no child element");
093                    }
094                    el = DOMUtil.getFirstChildElement(el);
095                    if (el == null) {
096                        throw new IllegalStateException("JBI message has no child element");
097                    }
098                    if (!WSDL11_WRAPPER_NAMESPACE.equals(el.getNamespaceURI()) || !WSDL11_WRAPPER_PART_LOCALNAME.equals(el.getLocalName())) {
099                        throw new IllegalStateException("Expected a jbi:part element");
100                    }
101                    isJbiWrapped.set(true);
102                    source = new DOMSource(el);
103                }
104            } else {
105                XMLStreamReader reader = transformer.toXMLStreamReader(source);
106                reader.nextTag();
107                if (!reader.isStartElement()) {
108                     throw new IllegalStateException("expected an element");
109                }
110                QName qname = reader.getName();
111                if (qname.equals(WSDL11_WRAPPER_MESSAGE)) {
112                    reader.nextTag();
113                    if (reader.getName().equals(WSDL11_WRAPPER_PART)) {
114                        reader.nextTag();
115                        isJbiWrapped.set(true);
116                    } else {
117                        throw new IllegalStateException("Expected a jbi:part element");
118                    }
119                }
120                source = new StaxSource(new FragmentStreamReader(reader));
121            }
122            return source;
123        }
124    
125        public static Source unwrap(Source source) throws TransformerException, XMLStreamException {
126            XMLStreamReader reader = new StAXSourceTransformer().toXMLStreamReader(source);
127            reader.nextTag();
128            if (!reader.isStartElement()) {
129                 throw new IllegalStateException("expected an element");
130            }
131            QName qname = reader.getName();
132            if (qname.equals(WSDL11_WRAPPER_MESSAGE)) {
133                reader.nextTag();
134                if (reader.getName().equals(WSDL11_WRAPPER_PART)) {
135                    reader.nextTag();
136                } else {
137                    throw new IllegalStateException("Expected a jbi:part element");
138                }
139            }
140            source = new StaxSource(new FragmentStreamReader(reader));
141            return source;
142        }
143    }