1
2
3
4
5
6
7 package org.mule.module.cxf;
8
9 import org.mule.api.DefaultMuleException;
10 import org.mule.api.ExceptionPayload;
11 import org.mule.api.MessagingException;
12 import org.mule.api.MuleEvent;
13 import org.mule.api.MuleException;
14 import org.mule.api.MuleMessage;
15 import org.mule.api.endpoint.EndpointNotFoundException;
16 import org.mule.api.endpoint.EndpointURI;
17 import org.mule.api.lifecycle.InitialisationException;
18 import org.mule.api.lifecycle.Lifecycle;
19 import org.mule.api.transformer.TransformerException;
20 import org.mule.api.transport.OutputHandler;
21 import org.mule.config.i18n.MessageFactory;
22 import org.mule.message.DefaultExceptionPayload;
23 import org.mule.module.cxf.support.DelegatingOutputStream;
24 import org.mule.module.xml.stax.StaxSource;
25 import org.mule.processor.AbstractInterceptingMessageProcessor;
26 import org.mule.transformer.types.DataTypeFactory;
27 import org.mule.transport.http.HttpConnector;
28 import org.mule.transport.http.HttpConstants;
29 import org.mule.util.StringUtils;
30
31 import java.io.ByteArrayInputStream;
32 import java.io.ByteArrayOutputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.io.Reader;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41
42 import javax.xml.stream.XMLStreamReader;
43 import javax.xml.transform.Source;
44 import javax.xml.transform.dom.DOMSource;
45
46 import org.apache.commons.logging.Log;
47 import org.apache.commons.logging.LogFactory;
48 import org.apache.cxf.Bus;
49 import org.apache.cxf.binding.soap.SoapBindingConstants;
50 import org.apache.cxf.endpoint.Server;
51 import org.apache.cxf.message.ExchangeImpl;
52 import org.apache.cxf.message.Message;
53 import org.apache.cxf.message.MessageImpl;
54 import org.apache.cxf.service.model.EndpointInfo;
55 import org.apache.cxf.staxutils.StaxUtils;
56 import org.apache.cxf.transport.DestinationFactory;
57 import org.apache.cxf.transport.DestinationFactoryManager;
58 import org.apache.cxf.transport.local.LocalConduit;
59 import org.apache.cxf.transports.http.QueryHandler;
60 import org.apache.cxf.transports.http.QueryHandlerRegistry;
61 import org.apache.cxf.wsdl.http.AddressType;
62 import org.w3c.dom.Document;
63 import org.w3c.dom.Node;
64
65
66
67
68
69
70
71 public class CxfInboundMessageProcessor extends AbstractInterceptingMessageProcessor implements Lifecycle
72 {
73
74
75
76 protected transient Log logger = LogFactory.getLog(getClass());
77
78 protected Bus bus;
79
80
81 protected String transportClass;
82
83 protected Server server;
84
85 private boolean proxy;
86
87 private boolean onFaultInvokeStrategy = false;
88
89 public void initialise() throws InitialisationException
90 {
91 if (bus == null)
92 {
93 throw new InitialisationException(
94 MessageFactory.createStaticMessage("No CXF bus instance, this component has not been initialized properly."),
95 this);
96 }
97 }
98
99 public void stop() throws MuleException
100 {
101 if (server != null)
102 {
103 server.stop();
104 }
105 }
106
107 public void start() throws MuleException
108 {
109
110 if (server != null)
111 {
112 server.start();
113 }
114 }
115
116 public void dispose()
117 {
118 }
119
120 public MuleEvent process(MuleEvent event) throws MuleException
121 {
122
123 String requestPath = parseHttpRequestProperty(event.getMessage().getInboundProperty(
124 HttpConnector.HTTP_REQUEST_PROPERTY, StringUtils.EMPTY));
125 try
126 {
127 if (requestPath.indexOf('?') > -1)
128 {
129 return generateWSDLOrXSD(event, requestPath);
130 }
131 else
132 {
133 return sendToDestination(event);
134 }
135 }
136 catch (IOException e)
137 {
138 throw new DefaultMuleException(e);
139 }
140 }
141
142 private String parseHttpRequestProperty(String request)
143 {
144 String uriBase = "";
145
146 if (!(request.contains("?wsdl")) && (!(request.contains("?xsd"))))
147 {
148 int qIdx = request.indexOf('?');
149 if (qIdx > -1)
150 {
151 uriBase = request.substring(0, qIdx);
152 }
153 }
154 else
155 {
156 uriBase = request;
157 }
158
159 return uriBase;
160 }
161
162 protected MuleEvent generateWSDLOrXSD(MuleEvent event, String req)
163 throws EndpointNotFoundException, IOException
164 {
165
166 String ctxUri = event.getMessage().getInboundProperty(HttpConnector.HTTP_CONTEXT_PATH_PROPERTY);
167 String wsdlUri = getUri(event);
168 String serviceUri = wsdlUri.substring(0, wsdlUri.indexOf('?'));
169
170 EndpointInfo ei = getServer().getEndpoint().getEndpointInfo();
171
172 if (serviceUri != null)
173 {
174 ei.setAddress(serviceUri);
175
176 if (ei.getExtensor(AddressType.class) != null)
177 {
178 ei.getExtensor(AddressType.class).setLocation(serviceUri);
179 }
180 }
181
182 ByteArrayOutputStream out = new ByteArrayOutputStream();
183 String ct = null;
184
185 for (QueryHandler qh : bus.getExtension(QueryHandlerRegistry.class).getHandlers())
186 {
187 if (qh.isRecognizedQuery(wsdlUri, ctxUri, ei))
188 {
189 ct = qh.getResponseContentType(wsdlUri, ctxUri);
190 qh.writeResponse(wsdlUri, ctxUri, ei, out);
191 out.flush();
192 }
193 }
194
195 String msg;
196 if (ct == null)
197 {
198 ct = "text/plain";
199 msg = "No query handler found for URL.";
200 }
201 else
202 {
203 msg = out.toString();
204 }
205
206 event.getMessage().setPayload(msg);
207 event.getMessage().setOutboundProperty(HttpConstants.HEADER_CONTENT_TYPE, ct);
208 return event;
209 }
210
211 private String getUri(MuleEvent event)
212 {
213 EndpointURI epUri = event.getEndpoint().getEndpointURI();
214 String host = event.getMessage().getInboundProperty("Host", epUri.getHost());
215 String ctx = event.getMessage().getInboundProperty(HttpConnector.HTTP_REQUEST_PROPERTY);
216
217 return epUri.getScheme() + "://" + host + ctx;
218 }
219
220 protected MuleEvent sendToDestination(MuleEvent event) throws MuleException, IOException
221 {
222 try
223 {
224 final MessageImpl m = new MessageImpl();
225 final MuleMessage muleReqMsg = event.getMessage();
226 String method = muleReqMsg.getInboundProperty(HttpConnector.HTTP_METHOD_PROPERTY);
227
228 String ct = muleReqMsg.getInboundProperty(HttpConstants.HEADER_CONTENT_TYPE);
229 if (ct != null)
230 {
231 m.put(Message.CONTENT_TYPE, ct);
232 }
233
234 String path = muleReqMsg.getInboundProperty(HttpConnector.HTTP_REQUEST_PATH_PROPERTY);
235 if (path == null)
236 {
237 path = "";
238 }
239
240 if (method != null)
241 {
242 m.put(Message.HTTP_REQUEST_METHOD, method);
243 m.put(Message.PATH_INFO, path);
244 Object basePath = muleReqMsg.getInboundProperty(HttpConnector.HTTP_CONTEXT_PATH_PROPERTY);
245 m.put(Message.BASE_PATH, basePath);
246
247 method = method.toUpperCase();
248 }
249
250 if (!"GET".equals(method))
251 {
252 Object payload = event.getMessage().getPayload();
253
254 setPayload(event, m, payload);
255 }
256
257
258 String soapAction = getSoapAction(event.getMessage());
259 m.put(org.mule.module.cxf.SoapConstants.SOAP_ACTION_PROPERTY_CAPS, soapAction);
260
261
262 Map<String, List<String>> protocolHeaders = new HashMap<String, List<String>>();
263 List<String> soapActions = new ArrayList<String>();
264 if (soapAction != null && !"".equals(soapAction))
265 {
266 soapActions.add(soapAction);
267 }
268 protocolHeaders.put(SoapBindingConstants.SOAP_ACTION, soapActions);
269 m.put(Message.PROTOCOL_HEADERS, protocolHeaders);
270
271 org.apache.cxf.transport.Destination d;
272
273 if (server != null)
274 {
275 d = server.getDestination();
276 }
277 else
278 {
279 String serviceUri = getUri(event);
280
281 DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class);
282 DestinationFactory df = dfm.getDestinationFactoryForUri(serviceUri);
283
284 EndpointInfo ei = new EndpointInfo();
285 ei.setAddress(serviceUri);
286 d = df.getDestination(ei);
287 }
288
289
290 m.put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
291 m.setDestination(d);
292
293 ExchangeImpl exchange = new ExchangeImpl();
294 exchange.setInMessage(m);
295
296
297
298 exchange.put(CxfConstants.MULE_EVENT, event);
299
300
301
302 d.getMessageObserver().onMessage(m);
303
304
305 MuleEvent responseEvent = (MuleEvent) exchange.get(CxfConstants.MULE_EVENT);
306
307 if (responseEvent == null)
308 {
309 return null;
310 }
311
312 MuleMessage muleResMsg = responseEvent.getMessage();
313 muleResMsg.setPayload(getRessponseOutputHandler(m));
314
315
316 Message faultMsg = m.getExchange().getOutFaultMessage();
317 if (faultMsg != null)
318 {
319 Exception ex = faultMsg.getContent(Exception.class);
320 if (ex != null)
321 {
322 ExceptionPayload exceptionPayload = new DefaultExceptionPayload(ex);
323 event.getMessage().setExceptionPayload(exceptionPayload);
324 muleResMsg.setOutboundProperty(HttpConnector.HTTP_STATUS_PROPERTY, 500);
325 }
326 }
327
328
329 if (isOnFaultInvokeStrategy())
330 {
331 Object o = exchange.get(Exception.class);
332 if (o != null && o instanceof Exception)
333 {
334 muleResMsg.setPayload(getSoapFaultMessage(muleResMsg));
335 throw new MessagingException(responseEvent, (Exception)o);
336 }
337 }
338
339 if(!event.getEndpoint().getExchangePattern().hasResponse())
340 {
341 return null;
342 }
343
344 return responseEvent;
345 }
346 catch (MuleException e)
347 {
348 logger.warn("Could not dispatch message to CXF!", e);
349 throw e;
350 }
351 }
352
353 @Override
354 public MuleEvent processNext(MuleEvent event) throws MuleException
355 {
356 return super.processNext(event);
357 }
358
359 private Object getSoapFaultMessage(MuleMessage message)
360 {
361 try
362 {
363 return message.getPayloadAsString();
364 }
365 catch(Exception e)
366 {
367 return message.getPayload();
368 }
369 }
370
371 protected OutputHandler getRessponseOutputHandler(final MessageImpl m)
372 {
373 OutputHandler outputHandler = new OutputHandler()
374 {
375 public void write(MuleEvent event, OutputStream out) throws IOException
376 {
377 Message outFaultMessage = m.getExchange().getOutFaultMessage();
378 Message outMessage = m.getExchange().getOutMessage();
379
380 Message contentMsg = null;
381 if (outFaultMessage != null && outFaultMessage.getContent(OutputStream.class) != null)
382 {
383 contentMsg = outFaultMessage;
384 }
385 else if (outMessage != null)
386 {
387 contentMsg = outMessage;
388 }
389
390 if (contentMsg == null)
391 {
392 return;
393 }
394
395 DelegatingOutputStream delegate = contentMsg.getContent(DelegatingOutputStream.class);
396 if (delegate.getOutputStream() instanceof ByteArrayOutputStream)
397 {
398 out.write(((ByteArrayOutputStream) delegate.getOutputStream()).toByteArray());
399 }
400 delegate.setOutputStream(out);
401
402 out.flush();
403
404 contentMsg.getInterceptorChain().resume();
405 }
406
407 };
408 return outputHandler;
409 }
410
411 private void setPayload(MuleEvent ctx, final MessageImpl m, Object payload) throws TransformerException
412 {
413 if (payload instanceof InputStream)
414 {
415 m.put(Message.ENCODING, ctx.getEncoding());
416 m.setContent(InputStream.class, payload);
417 }
418 else if (payload instanceof Reader)
419 {
420 m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader((Reader) payload));
421 }
422 else if (payload instanceof byte[])
423 {
424 m.setContent(InputStream.class, new ByteArrayInputStream((byte[]) payload));
425 }
426 else if (payload instanceof StaxSource)
427 {
428 m.setContent(XMLStreamReader.class, ((StaxSource) payload).getXMLStreamReader());
429 }
430 else if (payload instanceof Source)
431 {
432 m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader((Source) payload));
433 }
434 else if (payload instanceof XMLStreamReader)
435 {
436 m.setContent(XMLStreamReader.class, payload);
437 }
438 else if (payload instanceof Document)
439 {
440 DOMSource source = new DOMSource((Node) payload);
441 m.setContent(XMLStreamReader.class, StaxUtils.createXMLStreamReader(source));
442 }
443 else
444 {
445 InputStream is = (InputStream) ctx.transformMessage(DataTypeFactory.create(InputStream.class));
446 m.put(Message.ENCODING, ctx.getEncoding());
447 m.setContent(InputStream.class, is);
448 }
449 }
450
451
452
453
454
455
456
457
458 protected InputStream getMessageStream(MuleEvent context) throws MuleException
459 {
460 InputStream is;
461 Object eventMsgPayload = context.getMessage().getPayload();
462
463 if (eventMsgPayload instanceof InputStream)
464 {
465 is = (InputStream) eventMsgPayload;
466 }
467 else
468 {
469 is = context.transformMessage(DataTypeFactory.create(InputStream.class));
470 }
471 return is;
472 }
473
474 protected String getSoapAction(MuleMessage message)
475 {
476 String action = message.getInboundProperty(SoapConstants.SOAP_ACTION_PROPERTY);
477
478 if (action != null && action.startsWith("\"") && action.endsWith("\"") && action.length() >= 2)
479 {
480 action = action.substring(1, action.length() - 1);
481 }
482
483 return action;
484 }
485
486 public Bus getBus()
487 {
488 return bus;
489 }
490
491 public void setBus(Bus bus)
492 {
493 this.bus = bus;
494 }
495
496 public Server getServer()
497 {
498 return server;
499 }
500
501 public void setServer(Server server)
502 {
503 this.server = server;
504 }
505
506 public void setProxy(boolean proxy)
507 {
508 this.proxy = proxy;
509 }
510
511 public boolean isProxy()
512 {
513 return proxy;
514 }
515
516 public void setOnFaultInvokeStrategy(boolean onFaultInvokeStrategy)
517 {
518 this.onFaultInvokeStrategy = onFaultInvokeStrategy;
519 }
520
521 public boolean isOnFaultInvokeStrategy()
522 {
523 return onFaultInvokeStrategy;
524 }
525 }