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