1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.cxf.transport;
12
13 import static org.apache.cxf.message.Message.DECOUPLED_CHANNEL_MESSAGE;
14
15 import org.mule.DefaultMuleEvent;
16 import org.mule.DefaultMuleMessage;
17 import org.mule.DefaultMuleSession;
18 import org.mule.RegistryContext;
19 import org.mule.RequestContext;
20 import org.mule.api.MuleEvent;
21 import org.mule.api.MuleEventContext;
22 import org.mule.api.MuleException;
23 import org.mule.api.MuleMessage;
24 import org.mule.api.MuleSession;
25 import org.mule.api.endpoint.OutboundEndpoint;
26 import org.mule.api.transport.MessageAdapter;
27 import org.mule.api.transport.OutputHandler;
28 import org.mule.transport.DefaultMessageAdapter;
29 import org.mule.transport.cxf.CxfConnector;
30 import org.mule.transport.cxf.CxfConstants;
31 import org.mule.transport.cxf.support.DelegatingOutputStream;
32 import org.mule.transport.cxf.support.MuleProtocolHeadersOutInterceptor;
33 import org.mule.transport.http.HttpConstants;
34
35 import java.io.ByteArrayOutputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.net.HttpURLConnection;
40 import java.net.MalformedURLException;
41 import java.util.logging.Logger;
42
43 import org.apache.cxf.interceptor.Fault;
44 import org.apache.cxf.message.Exchange;
45 import org.apache.cxf.message.ExchangeImpl;
46 import org.apache.cxf.message.Message;
47 import org.apache.cxf.message.MessageImpl;
48 import org.apache.cxf.phase.AbstractPhaseInterceptor;
49 import org.apache.cxf.phase.Phase;
50 import org.apache.cxf.service.model.EndpointInfo;
51 import org.apache.cxf.transport.AbstractConduit;
52 import org.apache.cxf.transport.Destination;
53 import org.apache.cxf.transport.MessageObserver;
54 import org.apache.cxf.ws.addressing.AttributedURIType;
55 import org.apache.cxf.ws.addressing.EndpointReferenceType;
56 import org.apache.cxf.wsdl.EndpointReferenceUtils;
57
58
59
60
61
62
63 public class MuleUniversalConduit extends AbstractConduit
64 {
65
66 private static final Logger LOGGER = Logger.getLogger(MuleUniversalConduit.class.getName());
67
68 private EndpointInfo endpoint;
69
70 private CxfConnector connector;
71
72 private Destination decoupledDestination;
73
74 private String decoupledEndpoint;
75
76 private MuleUniversalTransport transport;
77
78 private int decoupledDestinationRefCount;
79
80
81
82
83
84 public MuleUniversalConduit(MuleUniversalTransport transport,
85 CxfConnector connector,
86 EndpointInfo ei,
87 EndpointReferenceType t)
88 {
89 super(getTargetReference(ei, t));
90 this.transport = transport;
91 this.endpoint = ei;
92 this.connector = connector;
93 }
94
95 @Override
96 protected Logger getLogger()
97 {
98 return LOGGER;
99 }
100
101 public synchronized Destination getBackChannel()
102 {
103 if (decoupledDestination == null && decoupledEndpoint != null)
104 {
105 setUpDecoupledDestination();
106 }
107 return decoupledDestination;
108 }
109
110 private void setUpDecoupledDestination()
111 {
112 EndpointInfo ei = new EndpointInfo();
113 ei.setAddress(decoupledEndpoint);
114 try
115 {
116 decoupledDestination = transport.getDestination(ei);
117 decoupledDestination.setMessageObserver(new InterposedMessageObserver());
118 duplicateDecoupledDestination();
119 }
120 catch (IOException e)
121 {
122 throw new RuntimeException(e);
123 }
124 }
125
126
127
128
129 public void prepare(final Message message) throws IOException
130 {
131
132 final ByteArrayOutputStream cache = new ByteArrayOutputStream();
133 final DelegatingOutputStream delegating = new DelegatingOutputStream(cache);
134 message.setContent(OutputStream.class, delegating);
135
136 AbstractPhaseInterceptor<Message> i = new AbstractPhaseInterceptor<Message>(Phase.PRE_STREAM)
137 {
138 public void handleMessage(Message m) throws Fault
139 {
140 try
141 {
142 dispatchMuleMessage(m);
143 }
144 catch (IOException e)
145 {
146 throw new Fault(e);
147 }
148 }
149 };
150 i.getAfter().add(MuleProtocolHeadersOutInterceptor.class.getName());
151 message.getInterceptorChain().add(i);
152
153 OutputHandler handler = new OutputHandler()
154 {
155 public void write(MuleEvent event, OutputStream out) throws IOException
156 {
157 out.write(cache.toByteArray());
158
159 delegating.setOutputStream(out);
160
161
162 message.getInterceptorChain().doIntercept(message);
163 }
164 };
165
166
167
168 DefaultMessageAdapter req = new DefaultMessageAdapter(handler);
169 message.getExchange().put(CxfConstants.MULE_MESSAGE, req);
170 }
171
172 protected void dispatchMuleMessage(Message m) throws IOException {
173 String uri = setupURL(m);
174
175 LOGGER.info("Sending message to " + uri);
176 try
177 {
178 OutboundEndpoint ep = RegistryContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(uri);
179
180 MessageAdapter req = (MessageAdapter) m.getExchange().get(CxfConstants.MULE_MESSAGE);
181
182 MuleMessage result = sendStream(req, ep);
183
184
185 if (result != null && !isOneway(m.getExchange()))
186 {
187 Message inMessage = new MessageImpl();
188 String contentType = req.getStringProperty(HttpConstants.HEADER_CONTENT_TYPE, "text/xml");
189
190 inMessage.put(Message.ENCODING, result.getEncoding());
191 inMessage.put(Message.CONTENT_TYPE, contentType);
192 inMessage.setContent(InputStream.class, result.getPayload(InputStream.class));
193
194
195 inMessage.setExchange(m.getExchange());
196 getMessageObserver().onMessage(inMessage);
197 }
198 }
199 catch (Exception e)
200 {
201 if (e instanceof IOException)
202 {
203 throw (IOException) e;
204 }
205
206 IOException ex = new IOException("Could not send message to Mule.");
207 ex.initCause(e);
208 throw ex;
209 }
210 }
211
212 private boolean isOneway(Exchange exchange)
213 {
214 return exchange != null && exchange.isOneWay();
215 }
216
217 private String setupURL(Message message) throws MalformedURLException
218 {
219 String value = (String) message.get(Message.ENDPOINT_ADDRESS);
220 String pathInfo = (String) message.get(Message.PATH_INFO);
221 String queryString = (String) message.get(Message.QUERY_STRING);
222
223 String result = value != null ? value : getTargetOrEndpoint();
224
225
226 if (null != pathInfo && !result.endsWith(pathInfo))
227 {
228 result = result + pathInfo;
229 }
230 if (queryString != null)
231 {
232 result = result + "?" + queryString;
233 }
234 return result;
235 }
236
237 private String getTargetOrEndpoint()
238 {
239 if (target != null)
240 {
241 return target.getAddress().getValue();
242 }
243
244 return endpoint.getAddress().toString();
245 }
246
247 public void onClose(final Message m) throws IOException
248 {
249 }
250
251 protected MuleMessage sendStream(MessageAdapter sa, OutboundEndpoint ep) throws MuleException
252 {
253 MuleEventContext eventContext = RequestContext.getEventContext();
254 MuleSession session = null;
255 if (eventContext != null)
256 {
257 session = eventContext.getSession();
258 }
259
260 MuleMessage message = new DefaultMuleMessage(sa);
261 if (session == null)
262 {
263 session = new DefaultMuleSession(message, connector.getSessionHandler(), connector.getMuleContext());
264 }
265
266 MuleEvent event = new DefaultMuleEvent(message, ep, session, true);
267 event.setTimeout(MuleEvent.TIMEOUT_NOT_SET_VALUE);
268 RequestContext.setEvent(event);
269
270 return ep.send(event);
271 }
272
273 public void close()
274 {
275
276
277
278 if (decoupledDestination != null)
279 {
280 releaseDecoupledDestination();
281 }
282 }
283
284 private synchronized void duplicateDecoupledDestination()
285 {
286 decoupledDestinationRefCount++;
287 }
288
289 private synchronized void releaseDecoupledDestination()
290 {
291 if (--decoupledDestinationRefCount == 0)
292 {
293
294 decoupledDestination.shutdown();
295 }
296 }
297
298 public String getDecoupledEndpoint()
299 {
300 return decoupledEndpoint;
301 }
302
303 public void setDecoupledEndpoint(String decoupledEndpoint)
304 {
305 this.decoupledEndpoint = decoupledEndpoint;
306 }
307
308
309
310
311
312
313
314
315
316 protected static EndpointReferenceType getTargetReference(EndpointInfo ei, EndpointReferenceType t)
317 {
318 EndpointReferenceType ref = null;
319 if (null == t)
320 {
321 ref = new EndpointReferenceType();
322 AttributedURIType address = new AttributedURIType();
323 address.setValue(ei.getAddress());
324 ref.setAddress(address);
325 if (ei.getService() != null)
326 {
327 EndpointReferenceUtils.setServiceAndPortName(ref, ei.getService().getName(), ei.getName()
328 .getLocalPart());
329 }
330 }
331 else
332 {
333 ref = t;
334 }
335 return ref;
336 }
337
338
339
340
341
342
343 protected class InterposedMessageObserver implements MessageObserver
344 {
345
346
347
348
349
350 public void onMessage(Message inMessage)
351 {
352
353 inMessage.setExchange(new ExchangeImpl());
354 inMessage.put(DECOUPLED_CHANNEL_MESSAGE, Boolean.TRUE);
355 inMessage.put(Message.RESPONSE_CODE, HttpURLConnection.HTTP_OK);
356 inMessage.remove(Message.ASYNC_POST_RESPONSE_DISPATCH);
357
358 incomingObserver.onMessage(inMessage);
359 }
360 }
361 }