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.components.util.xstream;
018    
019    import javax.jbi.messaging.MessageExchange;
020    import javax.jbi.messaging.MessagingException;
021    import javax.jbi.messaging.NormalizedMessage;
022    import javax.xml.parsers.ParserConfigurationException;
023    import javax.xml.transform.Source;
024    import javax.xml.transform.TransformerException;
025    import javax.xml.transform.dom.DOMResult;
026    import javax.xml.transform.dom.DOMSource;
027    import javax.xml.transform.stream.StreamSource;
028    
029    import org.w3c.dom.Document;
030    
031    import com.thoughtworks.xstream.XStream;
032    import com.thoughtworks.xstream.io.xml.DomReader;
033    import com.thoughtworks.xstream.io.xml.DomWriter;
034    
035    import org.apache.servicemix.jbi.jaxp.SourceTransformer;
036    import org.apache.servicemix.jbi.jaxp.StringSource;
037    import org.apache.servicemix.jbi.messaging.DefaultMarshaler;
038    
039    /**
040     * A {@link PojoMarshaler} for <a href="http://xStream.codehaus.org/">XStream</a> which
041     * streams the object to an a W3C DOM Document so that other components can access
042     * the XML without an extra parse.
043     *
044     * @version $Revision: 564374 $
045     */
046    public class XStreamMarshaler extends DefaultMarshaler {
047        private XStream xStream;
048    
049        private SourceTransformer transformer = new SourceTransformer();
050    
051        private boolean useDOM;
052    
053        public void marshal(MessageExchange exchange, NormalizedMessage message, Object body) throws MessagingException {
054            if (useDOM) {
055                try {
056                    Document document = transformer.createDocument();
057                    getXStream().marshal(body, new DomWriter(document));
058                    message.setContent(new DOMSource(document));
059                } catch (ParserConfigurationException e) {
060                    throw new MessagingException("Failed to marshal: " + body + " to DOM document: " + e, e);
061                }
062            } else {
063                String xml = getXStream().toXML(body);
064                message.setContent(new StringSource(xml));
065            }
066        }
067    
068        public Object unmarshal(MessageExchange exchange, NormalizedMessage message) throws MessagingException {
069            Source content = message.getContent();
070            if (content != null) {
071                if (content instanceof StreamSource) {
072                    StreamSource source = (StreamSource) content;
073                    return getXStream().fromXML(source.getReader());
074                }
075                Document document = null;
076                if (content instanceof DOMSource) {
077                    DOMSource domSource = (DOMSource) content;
078                    document = (Document) domSource.getNode();
079                } else {
080                    DOMResult result = new DOMResult();
081                    try {
082                        transformer.toResult(content, result);
083                    } catch (TransformerException e) {
084                        throw new MessagingException("Failed to transform content: " + content + " to DOMResult: " + e, e);
085                    }
086                    document = (Document) result.getNode();
087                }
088                return getXStream().unmarshal(new DomReader(document));
089            }
090            return super.unmarshal(exchange, message);
091        }
092    
093        // Properties
094        //-------------------------------------------------------------------------
095        public XStream getXStream() {
096            if (xStream == null) {
097                xStream = createXStream();
098            }
099            return xStream;
100        }
101    
102        public void setXStream(XStream xStream) {
103            this.xStream = xStream;
104        }
105    
106        public SourceTransformer getTransformer() {
107            return transformer;
108        }
109    
110        public void setTransformer(SourceTransformer transformer) {
111            this.transformer = transformer;
112        }
113    
114        /**
115         * Whether or not DOM should be used for marshalling XML - which is preferable if another component
116         * in the pipeline will want to parse the body.
117         *
118         * @return
119         */
120        public boolean isUseDOM() {
121            return useDOM;
122        }
123    
124        /**
125         * Enables DOM output when marshalling in case other components in the pipeline wish to perform
126         * parsing.
127         *
128         * @param useDOM
129         */
130        public void setUseDOM(boolean useDOM) {
131            this.useDOM = useDOM;
132        }
133    
134        protected XStream createXStream() {
135            XStream answer = new XStream();
136            try {
137                answer.alias("invoke", Class.forName("org.logicblaze.lingo.LingoInvocation"));
138            } catch (ClassNotFoundException e) {
139                // Ignore
140            }
141            return answer;
142        }
143    
144    }