1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers.soap.xfire.transport;
12
13 import org.mule.config.MuleProperties;
14 import org.mule.impl.MuleEvent;
15 import org.mule.impl.MuleMessage;
16 import org.mule.impl.RequestContext;
17 import org.mule.impl.endpoint.MuleEndpoint;
18 import org.mule.providers.http.HttpConnector;
19 import org.mule.providers.http.HttpConstants;
20 import org.mule.providers.streaming.StreamMessageAdapter;
21 import org.mule.umo.UMOEvent;
22 import org.mule.umo.UMOException;
23 import org.mule.umo.UMOMessage;
24 import org.mule.umo.endpoint.UMOEndpoint;
25 import org.mule.umo.provider.OutputHandler;
26 import org.mule.umo.provider.UMOStreamMessageAdapter;
27
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import java.util.Map;
34
35 import javax.activation.DataHandler;
36 import javax.mail.MessagingException;
37 import javax.xml.stream.XMLStreamException;
38 import javax.xml.stream.XMLStreamWriter;
39
40 import org.apache.commons.io.output.ByteArrayOutputStream;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.codehaus.xfire.MessageContext;
44 import org.codehaus.xfire.XFireException;
45 import org.codehaus.xfire.XFireRuntimeException;
46 import org.codehaus.xfire.attachments.Attachments;
47 import org.codehaus.xfire.attachments.ByteDataSource;
48 import org.codehaus.xfire.attachments.JavaMailAttachments;
49 import org.codehaus.xfire.attachments.SimpleAttachment;
50 import org.codehaus.xfire.exchange.AbstractMessage;
51 import org.codehaus.xfire.exchange.InMessage;
52 import org.codehaus.xfire.exchange.OutMessage;
53 import org.codehaus.xfire.soap.Soap12;
54 import org.codehaus.xfire.soap.SoapConstants;
55 import org.codehaus.xfire.soap.SoapVersion;
56 import org.codehaus.xfire.transport.AbstractChannel;
57 import org.codehaus.xfire.transport.Channel;
58 import org.codehaus.xfire.transport.Transport;
59 import org.codehaus.xfire.util.STAXUtils;
60
61
62
63
64
65
66
67
68
69 public class MuleUniversalChannel extends AbstractChannel
70 {
71
72
73
74 protected final transient Log logger = LogFactory.getLog(getClass());
75
76 public MuleUniversalChannel(String uri, Transport transport)
77 {
78 setTransport(transport);
79 setUri(uri);
80 }
81
82 public void open()
83 {
84
85 }
86
87 public void send(MessageContext context, OutMessage message) throws XFireException
88 {
89 if (message.getUri().equals(Channel.BACKCHANNEL_URI))
90 {
91 final OutputStream out = (OutputStream)context.getProperty(Channel.BACKCHANNEL_URI);
92 if (out != null)
93 {
94 final XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(out, message.getEncoding(),
95 context);
96
97 message.getSerializer().writeMessage(message, writer, context);
98 }
99 else
100 {
101 throw new XFireRuntimeException("No backchannel exists for message");
102 }
103
104 try
105 {
106 Attachments atts = message.getAttachments();
107 if (atts != null && atts.size() > 0)
108 {
109 writeAttachmentBody(context, message);
110
111 atts.write(out);
112 }
113 else
114 {
115
116 writeWithoutAttachments(context, message, out);
117 }
118 }
119 catch (IOException e)
120 {
121 throw new XFireException("Couldn't send message.", e);
122 }
123 }
124 else
125 {
126 try
127 {
128 sendViaClient(context, message);
129 }
130 catch (Exception e)
131 {
132 throw new XFireException("Failed to Send via MuleUniversalChannel: " + e.getMessage(), e);
133 }
134 }
135 }
136
137 void writeWithoutAttachments(MessageContext context, OutMessage message, OutputStream out)
138 throws XFireException
139 {
140 XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(out, message.getEncoding(), context);
141
142 message.getSerializer().writeMessage(message, writer, context);
143
144 try
145 {
146 writer.flush();
147 }
148 catch (XMLStreamException e)
149 {
150 logger.error(e);
151 throw new XFireException("Couldn't send message.", e);
152 }
153 }
154
155 void writeAttachmentBody(MessageContext context, OutMessage message) throws XFireException
156 {
157 ByteArrayOutputStream bos = new ByteArrayOutputStream();
158 writeWithoutAttachments(context, message, bos);
159
160 Attachments atts = message.getAttachments();
161
162 ByteDataSource ds = new ByteDataSource(bos.toByteArray());
163 ds.setContentType(getSoapMimeType(message));
164 DataHandler dh = new DataHandler(ds);
165
166 SimpleAttachment att = new SimpleAttachment("soap-message.xml", dh);
167
168 atts.setSoapMessage(att);
169 }
170
171 String getMimeType(AbstractMessage msg)
172 {
173 Attachments atts = msg.getAttachments();
174
175 if (atts != null && atts.size() > 0)
176 {
177 return atts.getContentType();
178 }
179 else
180 {
181 return getSoapMimeType(msg);
182 }
183 }
184
185 static String getSoapMimeType(AbstractMessage msg)
186 {
187 SoapVersion soap = msg.getSoapVersion();
188 String encoding = msg.getEncoding();
189 StringBuffer soapMimeType = new StringBuffer(40);
190
191 if (soap instanceof Soap12)
192 {
193 soapMimeType.append("application/soap+xml; charset=");
194 }
195 else
196 {
197
198 soapMimeType.append("text/xml; charset=");
199 }
200
201 return soapMimeType.append(encoding).toString();
202 }
203
204 private void sendViaClient(final MessageContext context, final OutMessage message) throws Exception
205 {
206 OutputHandler handler = new OutputHandler()
207 {
208 public void write(UMOEvent event, OutputStream out) throws IOException
209 {
210 try
211 {
212 Attachments atts = message.getAttachments();
213 if (atts != null && atts.size() > 0)
214 {
215 atts.write(out);
216 }
217 else
218 {
219 XMLStreamWriter writer = STAXUtils.createXMLStreamWriter(out, message.getEncoding(),
220 context);
221 message.getSerializer().writeMessage(message, writer, context);
222 try
223 {
224 writer.flush();
225 }
226 catch (XMLStreamException e)
227 {
228 logger.error(e);
229 throw new XFireException("Couldn't send message.", e);
230 }
231 }
232 }
233 catch (XFireException e)
234 {
235 logger.error("Couldn't send message.", e);
236 throw new IOException(e.getMessage());
237 }
238 }
239
240 public Map getHeaders(UMOEvent event)
241 {
242 Map headers = new HashMap();
243 headers.put(HttpConstants.HEADER_CONTENT_TYPE, getSoapMimeType(message));
244 headers.put(SoapConstants.SOAP_ACTION, message.getProperty(SoapConstants.SOAP_ACTION));
245 UMOMessage msg = event.getMessage();
246 for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
247 {
248 String headerName = (String)iterator.next();
249 Object headerValue = msg.getStringProperty(headerName, null);
250
251
252
253
254 if ((!headerName.startsWith(MuleProperties.PROPERTY_PREFIX) || (MuleProperties.MULE_USER_PROPERTY.compareTo(headerName) == 0))
255 && (!HttpConstants.HEADER_CONTENT_TYPE.equalsIgnoreCase(headerName))
256 && (!HttpConstants.HEADER_CONTENT_LENGTH.equalsIgnoreCase(headerName)))
257 {
258 headers.put(headerName, headerValue);
259 }
260 }
261
262 return headers;
263 }
264 };
265
266
267
268 UMOStreamMessageAdapter sp = new StreamMessageAdapter(handler);
269 sp.setProperty(HttpConnector.HTTP_METHOD_PROPERTY, HttpConstants.METHOD_POST);
270
271
272 UMOMessage msg = RequestContext.getEvent().getMessage();
273 for (Iterator i = msg.getPropertyNames().iterator(); i.hasNext();)
274 {
275 String propertyName = (String)i.next();
276 sp.setProperty(propertyName, msg.getProperty(propertyName));
277 }
278
279 UMOStreamMessageAdapter result = null;
280
281 try
282 {
283 result = sendStream(getUri(), sp);
284 if (result != null)
285 {
286 InMessage inMessage;
287 String contentType = sp.getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, "text/xml");
288 InputStream in = result.getInputStream();
289 if (contentType.toLowerCase().indexOf("multipart/related") != -1)
290 {
291 try
292 {
293 Attachments atts = new JavaMailAttachments(in, contentType);
294 InputStream msgIs = atts.getSoapMessage().getDataHandler().getInputStream();
295 inMessage = new InMessage(STAXUtils.createXMLStreamReader(msgIs,
296 message.getEncoding(), context), getUri());
297 inMessage.setAttachments(atts);
298 }
299 catch (MessagingException e)
300 {
301 throw new IOException(e.getMessage());
302 }
303 }
304 else
305 {
306 inMessage = new InMessage(STAXUtils.createXMLStreamReader(in, message.getEncoding(),
307 context), getUri());
308 }
309 getEndpoint().onReceive(context, inMessage);
310 }
311 }
312 finally
313 {
314 sp.release();
315 if (result != null)
316 {
317 result.release();
318 }
319 }
320 }
321
322 public void close()
323 {
324
325 }
326
327 public boolean isAsync()
328 {
329 return false;
330 }
331
332 protected UMOStreamMessageAdapter sendStream(String uri, UMOStreamMessageAdapter sa) throws UMOException
333 {
334
335 UMOEndpoint ep = MuleEndpoint.getOrCreateEndpointForUri(uri, UMOEndpoint.ENDPOINT_TYPE_SENDER);
336 ep.setStreaming(true);
337 UMOMessage message = new MuleMessage(sa);
338 UMOEvent event = new MuleEvent(message, ep, RequestContext.getEventContext().getSession(), true);
339 UMOMessage result = ep.send(event);
340 if (result != null)
341 {
342 if (result.getAdapter() instanceof UMOStreamMessageAdapter)
343 {
344 return (UMOStreamMessageAdapter) result.getAdapter();
345 }
346 else
347 {
348
349 throw new IllegalStateException(
350 "Mismatch of stream states. A stream was used for outbound channel, but a stream was not used for the response");
351 }
352 }
353 return null;
354 }
355
356 }