1
2
3
4
5
6
7
8
9
10
11 package org.mule.providers.soap.xfire;
12
13 import org.mule.config.MuleProperties;
14 import org.mule.impl.MuleMessage;
15 import org.mule.providers.AbstractMessageDispatcher;
16 import org.mule.providers.FatalConnectException;
17 import org.mule.providers.soap.SoapConstants;
18 import org.mule.providers.soap.i18n.SoapMessages;
19 import org.mule.providers.soap.xfire.i18n.XFireMessages;
20 import org.mule.providers.soap.xfire.transport.MuleUniversalTransport;
21 import org.mule.umo.UMOEvent;
22 import org.mule.umo.UMOMessage;
23 import org.mule.umo.endpoint.UMOEndpointURI;
24 import org.mule.umo.endpoint.UMOImmutableEndpoint;
25 import org.mule.umo.provider.DispatchException;
26 import org.mule.umo.transformer.TransformerException;
27 import org.mule.util.ClassUtils;
28 import org.mule.util.StringUtils;
29 import org.mule.util.TemplateParser;
30
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Properties;
38 import java.util.Set;
39
40 import javax.activation.DataHandler;
41 import javax.xml.namespace.QName;
42
43 import org.codehaus.xfire.XFire;
44 import org.codehaus.xfire.aegis.AegisBindingProvider;
45 import org.codehaus.xfire.aegis.type.TypeMapping;
46 import org.codehaus.xfire.aegis.type.basic.BeanType;
47 import org.codehaus.xfire.client.Client;
48 import org.codehaus.xfire.handler.Handler;
49 import org.codehaus.xfire.service.OperationInfo;
50 import org.codehaus.xfire.service.Service;
51 import org.codehaus.xfire.transport.Transport;
52
53
54
55
56
57 public class XFireMessageDispatcher extends AbstractMessageDispatcher
58 {
59
60
61 protected Client client = null;
62 protected final XFireConnector connector;
63 private final TemplateParser soapActionTemplateParser = TemplateParser.createAntStyleParser();
64
65 public XFireMessageDispatcher(UMOImmutableEndpoint endpoint)
66 {
67 super(endpoint);
68 this.connector = (XFireConnector) endpoint.getConnector();
69 }
70
71 protected void doConnect() throws Exception
72 {
73 if (client == null)
74 {
75 final XFire xfire = connector.getXfire();
76 final String serviceName = getServiceName(endpoint);
77 final Service service = xfire.getServiceRegistry().getService(serviceName);
78
79 if (service == null)
80 {
81 throw new FatalConnectException(XFireMessages.serviceIsNull(serviceName), this);
82 }
83
84 List inList = connector.getServerInHandlers();
85 if (inList != null)
86 {
87 for (int i = 0; i < inList.size(); i++)
88 {
89 Handler handler = (Handler) ClassUtils.instanciateClass(
90 inList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
91 service.addInHandler(handler);
92 }
93 }
94
95 List outList = connector.getServerOutHandlers();
96 if (outList != null)
97 {
98 for (int i = 0; i < outList.size(); i++)
99 {
100 Handler handler = (Handler) ClassUtils.instanciateClass(
101 outList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
102 service.addOutHandler(handler);
103 }
104 }
105
106 try
107 {
108 this.client = createXFireClient(endpoint, service, xfire);
109 }
110 catch (Exception ex)
111 {
112 disconnect();
113 throw ex;
114 }
115 }
116 }
117
118 protected Client createXFireClient(UMOImmutableEndpoint endpoint, Service service, XFire xfire) throws Exception
119 {
120 return createXFireClient(endpoint, service, xfire, null);
121 }
122
123 protected Client createXFireClient(UMOImmutableEndpoint endpoint, Service service, XFire xfire, String transportClass) throws Exception
124 {
125 Class transportClazz;
126
127 if (connector.getClientTransport() == null)
128 {
129 if (!StringUtils.isBlank(transportClass))
130 {
131 transportClazz = ClassUtils.loadClass(transportClass, this.getClass());
132 }
133 else
134 {
135 transportClazz = MuleUniversalTransport.class;
136 }
137 }
138 else
139 {
140 transportClazz = ClassUtils.loadClass(connector.getClientTransport(), this.getClass());
141 }
142
143 Transport transport = (Transport) transportClazz.getConstructor(null).newInstance(null);
144 Client client = new Client(transport, service, endpoint.getEndpointURI().toString());
145 client.setXFire(xfire);
146 client.setEndpointUri(endpoint.getEndpointURI().toString());
147 return configureXFireClient(client);
148 }
149
150 protected Client configureXFireClient(Client client) throws Exception
151 {
152 client.addInHandler(new MuleHeadersInHandler());
153 client.addOutHandler(new MuleHeadersOutHandler());
154
155 List inList = connector.getClientInHandlers();
156 if (inList != null)
157 {
158 for (int i = 0; i < inList.size(); i++)
159 {
160 Handler handler = (Handler) ClassUtils.instanciateClass(
161 inList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
162 client.addInHandler(handler);
163 }
164 }
165
166 List outList = connector.getClientOutHandlers();
167 if (outList != null)
168 {
169 for (int i = 0; i < outList.size(); i++)
170 {
171 Handler handler = (Handler) ClassUtils.instanciateClass(
172 outList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
173 client.addOutHandler(handler);
174 }
175 }
176
177 if (this.connector.getExtraProperties() != null)
178 {
179 Properties props = new Properties();
180 props.putAll(this.connector.getExtraProperties());
181 Object[] keys = props.keySet().toArray();
182 for (int i = 0; i < props.size(); i++)
183 {
184 client.setProperty(keys[i].toString(), props.getProperty((String) keys[i]));
185 }
186 }
187
188 return client;
189 }
190
191 protected void doDisconnect() throws Exception
192 {
193 client = null;
194 }
195
196 protected void doDispose()
197 {
198
199 }
200
201 protected String getMethod(UMOEvent event) throws DispatchException
202 {
203 String method = (String)event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY);
204
205 if (method == null)
206 {
207 UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
208 method = (String)endpointUri.getParams().get(MuleProperties.MULE_METHOD_PROPERTY);
209 }
210
211 if (method == null)
212 {
213 method = (String)event.getEndpoint().getProperties().get(MuleProperties.MULE_METHOD_PROPERTY);
214 }
215
216 if (method == null)
217 {
218 throw new DispatchException(SoapMessages.cannotInvokeCallWithoutOperation(),
219 event.getMessage(), event.getEndpoint());
220 }
221
222 return method;
223 }
224
225 protected Object[] getArgs(UMOEvent event) throws TransformerException
226 {
227 Object payload = event.getTransformedMessage();
228 Object[] args;
229
230 if (payload instanceof Object[])
231 {
232 args = (Object[])payload;
233 }
234 else
235 {
236 args = new Object[]{payload};
237 }
238
239 UMOMessage message = event.getMessage();
240 Set attachmentNames = message.getAttachmentNames();
241 if (attachmentNames != null && !attachmentNames.isEmpty())
242 {
243 List attachments = new ArrayList();
244 for (Iterator i = attachmentNames.iterator(); i.hasNext();)
245 {
246 attachments.add(message.getAttachment((String)i.next()));
247 }
248 List temp = new ArrayList(Arrays.asList(args));
249 temp.add(attachments.toArray(new DataHandler[0]));
250 args = temp.toArray();
251 }
252
253 return args;
254 }
255
256 protected UMOMessage doSend(UMOEvent event) throws Exception
257 {
258 if (event.getEndpoint().getProperty("complexTypes") != null)
259 {
260 configureClientForComplexTypes(this.client, event);
261 }
262 this.client.setTimeout(event.getTimeout());
263 this.client.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
264 String method = getMethod(event);
265
266
267 String soapAction = (String)event.getMessage().getProperty(SoapConstants.SOAP_ACTION_PROPERTY);
268 if (soapAction != null)
269 {
270 soapAction = parseSoapAction(soapAction, new QName(method), event);
271 this.client.setProperty(org.codehaus.xfire.soap.SoapConstants.SOAP_ACTION, soapAction);
272 }
273
274
275 Object[] arr = event.getMessage().getPropertyNames().toArray();
276 String head;
277
278 for (int i = 0; i < arr.length; i++)
279 {
280 head = (String) arr[i];
281 if ((head != null) && (!head.startsWith("MULE")))
282 {
283 this.client.setProperty((String) arr[i], event.getMessage().getProperty((String) arr[i]));
284 }
285 }
286
287 Object[] response = client.invoke(method, getArgs(event));
288
289 UMOMessage result = null;
290 if (response != null && response.length <= 1)
291 {
292 if (response.length == 1)
293 {
294 result = new MuleMessage(response[0], event.getMessage());
295 }
296 }
297 else
298 {
299 result = new MuleMessage(response, event.getMessage());
300 }
301
302 return result;
303 }
304
305 protected void doDispatch(UMOEvent event) throws Exception
306 {
307 this.client.setTimeout(event.getTimeout());
308 this.client.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
309 this.client.invoke(getMethod(event), getArgs(event));
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323 protected UMOMessage doReceive(long timeout) throws Exception
324 {
325 String serviceName = getServiceName(endpoint);
326
327 XFire xfire = connector.getXfire();
328 Service service = xfire.getServiceRegistry().getService(serviceName);
329
330 Client client = new Client(new MuleUniversalTransport(), service, endpoint.getEndpointURI()
331 .toString());
332 client.setXFire(xfire);
333 client.setTimeout((int)timeout);
334 client.setEndpointUri(endpoint.getEndpointURI().toString());
335
336 String method = (String)endpoint.getProperty(MuleProperties.MULE_METHOD_PROPERTY);
337 OperationInfo op = service.getServiceInfo().getOperation(method);
338
339 Properties params = endpoint.getEndpointURI().getUserParams();
340 String args[] = new String[params.size()];
341 int i = 0;
342 for (Iterator iterator = params.values().iterator(); iterator.hasNext(); i++)
343 {
344 args[i] = iterator.next().toString();
345 }
346
347 Object[] response = client.invoke(op, args);
348
349 if (response != null && response.length == 1)
350 {
351 return new MuleMessage(response[0]);
352 }
353 else
354 {
355 return new MuleMessage(response);
356 }
357 }
358
359
360
361
362
363
364 protected String getServiceName(UMOImmutableEndpoint endpoint)
365 {
366 String pathInfo = endpoint.getEndpointURI().getPath();
367
368 if (StringUtils.isEmpty(pathInfo))
369 {
370 return endpoint.getEndpointURI().getHost();
371 }
372
373 String serviceName;
374
375 int i = pathInfo.lastIndexOf('/');
376
377 if (i > -1)
378 {
379 serviceName = pathInfo.substring(i + 1);
380 }
381 else
382 {
383 serviceName = pathInfo;
384 }
385
386 return serviceName;
387 }
388
389 public String parseSoapAction(String soapAction, QName method, UMOEvent event)
390 {
391
392 UMOEndpointURI endpointURI = event.getEndpoint().getEndpointURI();
393 Map properties = new HashMap();
394 UMOMessage msg = event.getMessage();
395 for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
396 {
397 String propertyKey = (String)iterator.next();
398 properties.put(propertyKey, msg.getProperty(propertyKey));
399 }
400 properties.put(MuleProperties.MULE_METHOD_PROPERTY, method.getLocalPart());
401 properties.put("methodNamespace", method.getNamespaceURI());
402 properties.put("address", endpointURI.getAddress());
403 properties.put("scheme", endpointURI.getScheme());
404 properties.put("host", endpointURI.getHost());
405 properties.put("port", String.valueOf(endpointURI.getPort()));
406 properties.put("path", endpointURI.getPath());
407 properties.put("hostInfo", endpointURI.getScheme()
408 + "://"
409 + endpointURI.getHost()
410 + (endpointURI.getPort() > -1
411 ? ":" + String.valueOf(endpointURI.getPort()) : ""));
412 if (event.getComponent() != null)
413 {
414 properties.put("serviceName", event.getComponent().getDescriptor().getName());
415 }
416
417 soapAction = soapActionTemplateParser.parse(properties, soapAction);
418
419 if (logger.isDebugEnabled())
420 {
421 logger.debug("SoapAction for this call is: " + soapAction);
422 }
423
424 return soapAction;
425 }
426
427 protected void configureClientForComplexTypes(Client client, UMOEvent event) throws ClassNotFoundException
428 {
429 Map complexTypes = (Map) event.getEndpoint().getProperty("complexTypes");
430 Object[] beans = complexTypes.keySet().toArray();
431
432 AegisBindingProvider bp = (AegisBindingProvider) client.getService().getBindingProvider();
433 TypeMapping typeMapping = bp.getTypeMapping(client.getService());
434
435
436 for (int i = 0; i < beans.length; i++)
437 {
438 BeanType bt = new BeanType();
439 String[] queue = ((String) complexTypes.get(beans[i])).split(":", 2);
440 bt.setSchemaType(new QName(queue[1], queue[0]));
441 bt.setTypeClass(Class.forName(beans[i].toString()));
442 typeMapping.register(bt);
443 }
444 }
445 }