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 }