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