Skip to content

Commit be011c0

Browse files
committed
SWS-317
1 parent 40ecdfb commit be011c0

File tree

3 files changed

+435
-0
lines changed

3 files changed

+435
-0
lines changed

oxm/pom.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,17 @@
206206
<artifactId>xstream</artifactId>
207207
<optional>true</optional>
208208
</dependency>
209+
<!-- MessageConverter -->
210+
<dependency>
211+
<groupId>javax.jms</groupId>
212+
<artifactId>jms</artifactId>
213+
<optional>true</optional>
214+
</dependency>
215+
<dependency>
216+
<groupId>org.springframework</groupId>
217+
<artifactId>spring-jms</artifactId>
218+
<optional>true</optional>
219+
</dependency>
209220
<!-- Test dependencies -->
210221
<dependency>
211222
<groupId>easymock</groupId>
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
/*
2+
* Copyright 2007 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.oxm.support;
18+
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.io.OutputStream;
22+
import javax.jms.BytesMessage;
23+
import javax.jms.JMSException;
24+
import javax.jms.Message;
25+
import javax.jms.MessageEOFException;
26+
import javax.jms.Session;
27+
import javax.jms.TextMessage;
28+
import javax.xml.transform.Source;
29+
import javax.xml.transform.stream.StreamResult;
30+
import javax.xml.transform.stream.StreamSource;
31+
32+
import org.springframework.beans.factory.InitializingBean;
33+
import org.springframework.jms.support.converter.MessageConversionException;
34+
import org.springframework.jms.support.converter.MessageConverter;
35+
import org.springframework.oxm.Marshaller;
36+
import org.springframework.oxm.MarshallingFailureException;
37+
import org.springframework.oxm.Unmarshaller;
38+
import org.springframework.oxm.UnmarshallingFailureException;
39+
import org.springframework.util.Assert;
40+
import org.springframework.xml.transform.StringResult;
41+
import org.springframework.xml.transform.StringSource;
42+
43+
/**
44+
* Spring JMS {@link MessageConverter} that uses a {@link Marshaller} and {@link Unmarshaller}. Marshals an object to a
45+
* {@link BytesMessage}, or to a {@link TextMessage} if the {@link #setMarshalToTextMessage(boolean)
46+
* marshalToTextMessage} is <code>true</code>. Unmarshals from a {@link TextMessage} or {@link BytesMessage} to an
47+
* object.
48+
*
49+
* @author Arjen Poutsma
50+
*/
51+
public class MarshallingMessageConverter implements MessageConverter, InitializingBean {
52+
53+
private Marshaller marshaller;
54+
55+
private Unmarshaller unmarshaller;
56+
57+
private boolean marshalToTextMessage = false;
58+
59+
/**
60+
* Constructs a new <code>MarshallingMessageConverter</code> with no {@link Marshaller} set. The marshaller must be
61+
* set after construction by invoking {@link #setMarshaller(Marshaller)}.
62+
*/
63+
public MarshallingMessageConverter() {
64+
}
65+
66+
/**
67+
* Constructs a new <code>MarshallingMessageConverter</code> with the given {@link Marshaller} set. If the given
68+
* {@link Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and
69+
* unmarshalling. Otherwise, an exception is thrown.
70+
* <p/>
71+
* Note that all {@link Marshaller} implementations in Spring-WS also implement the {@link Unmarshaller} interface,
72+
* so that you can safely use this constructor.
73+
*
74+
* @param marshaller object used as marshaller and unmarshaller
75+
* @throws IllegalArgumentException when <code>marshaller</code> does not implement the {@link Unmarshaller}
76+
* interface
77+
*/
78+
public MarshallingMessageConverter(Marshaller marshaller) {
79+
Assert.notNull(marshaller, "marshaller must not be null");
80+
if (!(marshaller instanceof Unmarshaller)) {
81+
throw new IllegalArgumentException("Marshaller [" + marshaller + "] does not implement the Unmarshaller " +
82+
"interface. Please set an Unmarshaller explicitely by using the " +
83+
"AbstractMarshallingPayloadEndpoint(Marshaller, Unmarshaller) constructor.");
84+
}
85+
else {
86+
this.marshaller = marshaller;
87+
this.unmarshaller = (Unmarshaller) marshaller;
88+
}
89+
}
90+
91+
/**
92+
* Creates a new <code>MarshallingMessageConverter</code> with the given marshaller and unmarshaller.
93+
*
94+
* @param marshaller the marshaller to use
95+
* @param unmarshaller the unmarshaller to use
96+
*/
97+
public MarshallingMessageConverter(Marshaller marshaller, Unmarshaller unmarshaller) {
98+
Assert.notNull(marshaller, "marshaller must not be null");
99+
Assert.notNull(unmarshaller, "unmarshaller must not be null");
100+
this.marshaller = marshaller;
101+
this.unmarshaller = unmarshaller;
102+
}
103+
104+
/**
105+
* Indicates whether {@link #toMessage(Object,Session)} should marshal to a {@link TextMessage} or a {@link
106+
* BytesMessage}. The default is <code>false</code>, i.e. this converter marshals to a {@link BytesMessage}.
107+
*/
108+
public void setMarshalToTextMessage(boolean marshalToTextMessage) {
109+
this.marshalToTextMessage = marshalToTextMessage;
110+
}
111+
112+
/** Sets the {@link Marshaller} to be used by this message converter. */
113+
public void setMarshaller(Marshaller marshaller) {
114+
this.marshaller = marshaller;
115+
}
116+
117+
/** Sets the {@link Marshaller} to be used by this message converter. */
118+
public void setUnmarshaller(Unmarshaller unmarshaller) {
119+
this.unmarshaller = unmarshaller;
120+
}
121+
122+
public void afterPropertiesSet() throws Exception {
123+
Assert.notNull(marshaller, "Property 'marshaller' is required");
124+
Assert.notNull(unmarshaller, "Property 'unmarshaller' is required");
125+
}
126+
127+
public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
128+
try {
129+
if (marshalToTextMessage) {
130+
TextMessage message = session.createTextMessage();
131+
StringResult result = new StringResult();
132+
marshaller.marshal(object, result);
133+
message.setText(result.toString());
134+
return message;
135+
}
136+
else {
137+
BytesMessage message = session.createBytesMessage();
138+
StreamResult result = new StreamResult(new BytesMessageOutputStream(message));
139+
marshaller.marshal(object, result);
140+
return message;
141+
}
142+
}
143+
catch (MarshallingFailureException ex) {
144+
throw new MessageConversionException("Could not marshal [" + object + "]", ex);
145+
}
146+
catch (MessageConversionException ex) {
147+
handleMessageConversionException(ex);
148+
throw ex;
149+
}
150+
catch (IOException ex) {
151+
throw new MessageConversionException("Could not marshal [" + object + "]", ex);
152+
}
153+
}
154+
155+
public Object fromMessage(Message message) throws JMSException, MessageConversionException {
156+
Source source;
157+
if (message instanceof TextMessage) {
158+
source = new StringSource(((TextMessage) message).getText());
159+
}
160+
else if (message instanceof BytesMessage) {
161+
source = new StreamSource(new BytesMessageInputStream((BytesMessage) message));
162+
}
163+
else {
164+
throw new MessageConversionException(
165+
"MarshallingMessageConverter only supports TextMessages and BytesMessages");
166+
}
167+
try {
168+
return unmarshaller.unmarshal(source);
169+
}
170+
catch (UnmarshallingFailureException ex) {
171+
throw new MessageConversionException("Could not unmarshal message [" + message + "]", ex);
172+
}
173+
catch (MessageConversionException ex) {
174+
handleMessageConversionException(ex);
175+
throw ex;
176+
}
177+
catch (IOException ex) {
178+
throw new MessageConversionException("Could not unmarshal message [" + message + "]", ex);
179+
}
180+
}
181+
182+
private void handleMessageConversionException(MessageConversionException ex) throws JMSException {
183+
if (ex.getCause() instanceof JMSException) {
184+
throw (JMSException) ex.getCause();
185+
}
186+
else {
187+
throw ex;
188+
}
189+
}
190+
191+
/** Input stream that wraps a {@link BytesMessage}. */
192+
private static class BytesMessageInputStream extends InputStream {
193+
194+
private BytesMessage message;
195+
196+
BytesMessageInputStream(BytesMessage message) {
197+
this.message = message;
198+
}
199+
200+
public int read(byte b[]) throws IOException {
201+
try {
202+
return message.readBytes(b);
203+
}
204+
catch (JMSException ex) {
205+
throw new MessageConversionException("Could not read byte array", ex);
206+
}
207+
}
208+
209+
public int read(byte b[], int off, int len) throws IOException {
210+
if (off == 0) {
211+
try {
212+
return message.readBytes(b, len);
213+
}
214+
catch (JMSException ex) {
215+
throw new MessageConversionException("Could not read byte array", ex);
216+
}
217+
}
218+
else {
219+
return super.read(b, off, len);
220+
}
221+
}
222+
223+
public int read() throws IOException {
224+
try {
225+
return message.readByte();
226+
}
227+
catch (MessageEOFException ex) {
228+
return -1;
229+
}
230+
catch (JMSException ex) {
231+
throw new MessageConversionException("Could not read byte", ex);
232+
}
233+
}
234+
}
235+
236+
/** Output stream that wraps a {@link BytesMessage}. */
237+
private static class BytesMessageOutputStream extends OutputStream {
238+
239+
private BytesMessage message;
240+
241+
BytesMessageOutputStream(BytesMessage message) {
242+
this.message = message;
243+
}
244+
245+
public void write(byte b[]) throws IOException {
246+
try {
247+
message.writeBytes(b);
248+
}
249+
catch (JMSException ex) {
250+
throw new MessageConversionException("Could not write byte array", ex);
251+
}
252+
}
253+
254+
public void write(byte b[], int off, int len) throws IOException {
255+
try {
256+
message.writeBytes(b, off, len);
257+
}
258+
catch (JMSException ex) {
259+
throw new MessageConversionException("Could not write byte array", ex);
260+
}
261+
}
262+
263+
public void write(int b) throws IOException {
264+
try {
265+
message.writeByte((byte) b);
266+
}
267+
catch (JMSException ex) {
268+
throw new MessageConversionException("Could not write byte", ex);
269+
}
270+
}
271+
}
272+
}
273+

0 commit comments

Comments
 (0)