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 return client;
177 }
178
179 protected void doDisconnect() throws Exception
180 {
181 client = null;
182 }
183
184 protected void doDispose()
185 {
186
187 }
188
189 protected String getMethod(UMOEvent event) throws DispatchException
190 {
191 String method = (String)event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY);
192
193 if (method == null)
194 {
195 UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
196 method = (String)endpointUri.getParams().get(MuleProperties.MULE_METHOD_PROPERTY);
197 }
198
199 if (method == null)
200 {
201 method = (String)event.getEndpoint().getProperties().get(MuleProperties.MULE_METHOD_PROPERTY);
202 }
203
204 if (method == null)
205 {
206 throw new DispatchException(SoapMessages.cannotInvokeCallWithoutOperation(),
207 event.getMessage(), event.getEndpoint());
208 }
209
210 return method;
211 }
212
213 protected Object[] getArgs(UMOEvent event) throws TransformerException
214 {
215 Object payload = event.getTransformedMessage();
216 Object[] args;
217
218 if (payload instanceof Object[])
219 {
220 args = (Object[])payload;
221 }
222 else
223 {
224 args = new Object[]{payload};
225 }
226
227 UMOMessage message = event.getMessage();
228 Set attachmentNames = message.getAttachmentNames();
229 if (attachmentNames != null && !attachmentNames.isEmpty())
230 {
231 List attachments = new ArrayList();
232 for (Iterator i = attachmentNames.iterator(); i.hasNext();)
233 {
234 attachments.add(message.getAttachment((String)i.next()));
235 }
236 List temp = new ArrayList(Arrays.asList(args));
237 temp.add(attachments.toArray(new DataHandler[0]));
238 args = temp.toArray();
239 }
240
241 return args;
242 }
243
244 protected UMOMessage doSend(UMOEvent event) throws Exception
245 {
246 if (event.getEndpoint().getProperty("complexTypes") != null)
247 {
248 configureClientForComplexTypes(this.client, event);
249 }
250 this.client.setTimeout(event.getTimeout());
251 this.client.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
252 String method = getMethod(event);
253
254
255 String soapAction = (String)event.getMessage().getProperty(SoapConstants.SOAP_ACTION_PROPERTY);
256 if (soapAction != null)
257 {
258 soapAction = parseSoapAction(soapAction, new QName(method), event);
259 this.client.setProperty(org.codehaus.xfire.soap.SoapConstants.SOAP_ACTION, soapAction);
260 }
261
262
263 Object[] arr = event.getMessage().getPropertyNames().toArray();
264 String head;
265
266 for (int i = 0; i < arr.length; i++)
267 {
268 head = (String) arr[i];
269 if ((head != null) && (!head.startsWith("MULE")))
270 {
271 this.client.setProperty((String) arr[i], event.getMessage().getProperty((String) arr[i]));
272 }
273 }
274
275 Object[] response = client.invoke(method, getArgs(event));
276
277 UMOMessage result = null;
278 if (response != null && response.length <= 1)
279 {
280 if (response.length == 1)
281 {
282 result = new MuleMessage(response[0], event.getMessage());
283 }
284 }
285 else
286 {
287 result = new MuleMessage(response, event.getMessage());
288 }
289
290 return result;
291 }
292
293 protected void doDispatch(UMOEvent event) throws Exception
294 {
295 this.client.setTimeout(event.getTimeout());
296 this.client.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
297 this.client.invoke(getMethod(event), getArgs(event));
298 }
299
300
301
302
303
304
305
306
307
308
309
310
311 protected UMOMessage doReceive(long timeout) throws Exception
312 {
313 String serviceName = getServiceName(endpoint);
314
315 XFire xfire = connector.getXfire();
316 Service service = xfire.getServiceRegistry().getService(serviceName);
317
318 Client client = new Client(new MuleUniversalTransport(), service, endpoint.getEndpointURI()
319 .toString());
320 client.setXFire(xfire);
321 client.setTimeout((int)timeout);
322 client.setEndpointUri(endpoint.getEndpointURI().toString());
323
324 String method = (String)endpoint.getProperty(MuleProperties.MULE_METHOD_PROPERTY);
325 OperationInfo op = service.getServiceInfo().getOperation(method);
326
327 Properties params = endpoint.getEndpointURI().getUserParams();
328 String args[] = new String[params.size()];
329 int i = 0;
330 for (Iterator iterator = params.values().iterator(); iterator.hasNext(); i++)
331 {
332 args[i] = iterator.next().toString();
333 }
334
335 Object[] response = client.invoke(op, args);
336
337 if (response != null && response.length == 1)
338 {
339 return new MuleMessage(response[0]);
340 }
341 else
342 {
343 return new MuleMessage(response);
344 }
345 }
346
347
348
349
350
351
352 protected String getServiceName(UMOImmutableEndpoint endpoint)
353 {
354 String pathInfo = endpoint.getEndpointURI().getPath();
355
356 if (StringUtils.isEmpty(pathInfo))
357 {
358 return endpoint.getEndpointURI().getHost();
359 }
360
361 String serviceName;
362
363 int i = pathInfo.lastIndexOf('/');
364
365 if (i > -1)
366 {
367 serviceName = pathInfo.substring(i + 1);
368 }
369 else
370 {
371 serviceName = pathInfo;
372 }
373
374 return serviceName;
375 }
376
377 public String parseSoapAction(String soapAction, QName method, UMOEvent event)
378 {
379
380 UMOEndpointURI endpointURI = event.getEndpoint().getEndpointURI();
381 Map properties = new HashMap();
382 UMOMessage msg = event.getMessage();
383 for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
384 {
385 String propertyKey = (String)iterator.next();
386 properties.put(propertyKey, msg.getProperty(propertyKey));
387 }
388 properties.put(MuleProperties.MULE_METHOD_PROPERTY, method.getLocalPart());
389 properties.put("methodNamespace", method.getNamespaceURI());
390 properties.put("address", endpointURI.getAddress());
391 properties.put("scheme", endpointURI.getScheme());
392 properties.put("host", endpointURI.getHost());
393 properties.put("port", String.valueOf(endpointURI.getPort()));
394 properties.put("path", endpointURI.getPath());
395 properties.put("hostInfo", endpointURI.getScheme()
396 + "://"
397 + endpointURI.getHost()
398 + (endpointURI.getPort() > -1
399 ? ":" + String.valueOf(endpointURI.getPort()) : ""));
400 if (event.getComponent() != null)
401 {
402 properties.put("serviceName", event.getComponent().getDescriptor().getName());
403 }
404
405 soapAction = soapActionTemplateParser.parse(properties, soapAction);
406
407 if (logger.isDebugEnabled())
408 {
409 logger.debug("SoapAction for this call is: " + soapAction);
410 }
411
412 return soapAction;
413 }
414
415 protected void configureClientForComplexTypes(Client client, UMOEvent event) throws ClassNotFoundException
416 {
417 Map complexTypes = (Map) event.getEndpoint().getProperty("complexTypes");
418 Object[] beans = complexTypes.keySet().toArray();
419
420 AegisBindingProvider bp = (AegisBindingProvider) client.getService().getBindingProvider();
421 TypeMapping typeMapping = bp.getTypeMapping(client.getService());
422
423
424 for (int i = 0; i < beans.length; i++)
425 {
426 BeanType bt = new BeanType();
427 String[] queue = ((String) complexTypes.get(beans[i])).split(":", 2);
428 bt.setSchemaType(new QName(queue[1], queue[0]));
429 bt.setTypeClass(Class.forName(beans[i].toString()));
430 typeMapping.register(bt);
431 }
432 }
433 }