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