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 */
017package org.apache.activemq.transport.xstream;
018
019import java.io.IOException;
020import java.io.Reader;
021
022import com.thoughtworks.xstream.converters.Converter;
023import com.thoughtworks.xstream.converters.MarshallingContext;
024import com.thoughtworks.xstream.converters.UnmarshallingContext;
025import com.thoughtworks.xstream.io.HierarchicalStreamReader;
026import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
027
028import org.apache.activemq.command.ConsumerInfo;
029import org.apache.activemq.command.MarshallAware;
030import org.apache.activemq.command.MessageDispatch;
031import org.apache.activemq.command.TransientInitializer;
032import org.apache.activemq.transport.stomp.XStreamSupport;
033import org.apache.activemq.transport.util.TextWireFormat;
034import org.apache.activemq.util.ByteSequence;
035import org.apache.activemq.wireformat.WireFormat;
036
037import com.thoughtworks.xstream.XStream;
038
039/**
040 * A {@link WireFormat} implementation which uses the <a
041 * href="http://xstream.codehaus.org/>XStream</a> library to marshall commands
042 * onto the wire
043 *
044 *
045 */
046public class XStreamWireFormat extends TextWireFormat {
047    private XStream xStream;
048    private int version;
049
050    @Override
051    public int getVersion() {
052        return version;
053    }
054
055    @Override
056    public void setVersion(int version) {
057        this.version = version;
058    }
059
060    public WireFormat copy() {
061        return new XStreamWireFormat();
062    }
063
064    @Override
065    public Object unmarshalText(String text) {
066        return getXStream().fromXML(text);
067    }
068
069    @Override
070    public Object unmarshalText(Reader reader) {
071        Object val = getXStream().fromXML(reader);
072        if (val instanceof TransientInitializer) {
073            ((TransientInitializer)val).initTransients();
074        }
075        return val;
076    }
077
078    @Override
079    public String marshalText(Object command) throws IOException {
080        if (command instanceof MarshallAware) {
081            ((MarshallAware)command).beforeMarshall(this);
082        } else if(command instanceof MessageDispatch) {
083            MessageDispatch dispatch = (MessageDispatch) command;
084            if (dispatch != null && dispatch.getMessage() != null) {
085                dispatch.getMessage().beforeMarshall(this);
086            }
087        }
088
089        return getXStream().toXML(command);
090    }
091
092    /**
093     * Can this wireformat process packets of this version
094     *
095     * @param version the version number to test
096     * @return true if can accept the version
097     */
098    public boolean canProcessWireFormatVersion(int version) {
099        return true;
100    }
101
102    /**
103     * @return the current version of this wire format
104     */
105    public int getCurrentWireFormatVersion() {
106        return 1;
107    }
108
109    // Properties
110    // -------------------------------------------------------------------------
111    public XStream getXStream() {
112        if (xStream == null) {
113            xStream = createXStream();
114            // make it work in OSGi env
115            xStream.setClassLoader(getClass().getClassLoader());
116        }
117        return xStream;
118    }
119
120    public void setXStream(XStream xStream) {
121        this.xStream = xStream;
122    }
123
124    // Implementation methods
125    // -------------------------------------------------------------------------
126    protected XStream createXStream() {
127        final XStream xstream = XStreamSupport.createXStream();
128        xstream.ignoreUnknownElements();
129        xstream.registerConverter(new Converter() {
130            final Converter delegate = xstream.getConverterLookup().lookupConverterForType(ByteSequence.class);
131            @Override
132            public void marshal(Object o, HierarchicalStreamWriter hierarchicalStreamWriter, MarshallingContext marshallingContext) {
133                ByteSequence byteSequence = (ByteSequence)o;
134                byteSequence.compact();
135                delegate.marshal(byteSequence, hierarchicalStreamWriter, marshallingContext);
136            }
137
138            @Override
139            public Object unmarshal(HierarchicalStreamReader hierarchicalStreamReader, UnmarshallingContext unmarshallingContext) {
140                return delegate.unmarshal(hierarchicalStreamReader, unmarshallingContext);
141            }
142
143            @Override
144            public boolean canConvert(Class aClass) {
145                return aClass == ByteSequence.class;
146            }
147        });
148        return xstream;
149    }
150
151}