1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.soap.axis;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.api.MuleEvent;
15 import org.mule.api.MuleMessage;
16 import org.mule.api.config.MuleProperties;
17 import org.mule.api.endpoint.EndpointURI;
18 import org.mule.api.endpoint.ImmutableEndpoint;
19 import org.mule.api.endpoint.OutboundEndpoint;
20 import org.mule.api.transformer.TransformerException;
21 import org.mule.api.transport.DispatchException;
22 import org.mule.config.i18n.CoreMessages;
23 import org.mule.transport.AbstractMessageDispatcher;
24 import org.mule.transport.NullPayload;
25 import org.mule.transport.soap.NamedParameter;
26 import org.mule.transport.soap.SoapConstants;
27 import org.mule.transport.soap.SoapMethod;
28 import org.mule.transport.soap.i18n.SoapMessages;
29 import org.mule.util.BeanUtils;
30 import org.mule.util.StringUtils;
31 import org.mule.util.TemplateParser;
32
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39
40 import javax.activation.DataHandler;
41 import javax.xml.namespace.QName;
42
43 import org.apache.axis.AxisProperties;
44 import org.apache.axis.EngineConfiguration;
45 import org.apache.axis.MessageContext;
46 import org.apache.axis.attachments.AttachmentPart;
47 import org.apache.axis.client.Call;
48 import org.apache.axis.client.Service;
49 import org.apache.axis.configuration.FileProvider;
50 import org.apache.axis.constants.Style;
51 import org.apache.axis.constants.Use;
52 import org.apache.axis.wsdl.fromJava.Namespaces;
53 import org.apache.axis.wsdl.fromJava.Types;
54
55
56
57
58
59 public class AxisMessageDispatcher extends AbstractMessageDispatcher
60 {
61
62 protected EngineConfiguration clientConfig;
63 protected AxisConnector connector;
64 protected Service service;
65 private Map callParameters;
66
67 public AxisMessageDispatcher(OutboundEndpoint endpoint)
68 {
69 super(endpoint);
70 this.connector = (AxisConnector)endpoint.getConnector();
71 AxisProperties.setProperty("axis.doAutoTypes", Boolean.toString(connector.isDoAutoTypes()));
72 }
73
74 protected void doConnect() throws Exception
75 {
76 if (service == null)
77 {
78 service = createService(endpoint);
79 }
80 }
81
82 protected void doDisconnect() throws Exception
83 {
84 if (service != null)
85 {
86 service = null;
87 }
88 }
89
90 protected void doDispose()
91 {
92
93 }
94
95 protected synchronized EngineConfiguration getClientConfig(ImmutableEndpoint endpoint)
96 {
97 if (clientConfig == null)
98 {
99
100 String config;
101 config = (String)endpoint.getProperty(AxisConnector.AXIS_CLIENT_CONFIG_PROPERTY);
102
103 if (config != null)
104 {
105 clientConfig = new FileProvider(config);
106 }
107 else
108 {
109 clientConfig = connector.getClientProvider();
110 }
111 }
112 return clientConfig;
113 }
114
115 protected Service createService(ImmutableEndpoint endpoint) throws Exception
116 {
117
118 EngineConfiguration config = getClientConfig(endpoint);
119 return new Service(config);
120 }
121
122 protected void doDispatch(MuleEvent event) throws Exception
123 {
124 Object[] args = getArgs(event);
125 Call call = getCall(event, args);
126
127
128
129
130 call.setProperty("axis.one.way", Boolean.TRUE);
131 call.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
132 call.invoke(args);
133 }
134
135 protected MuleMessage doSend(MuleEvent event) throws Exception
136 {
137 Call call;
138 Object result;
139 Object[] args = getArgs(event);
140 call = getCall(event, args);
141 result = call.invoke(args);
142 if (result == null)
143 {
144 return null;
145 }
146 else
147 {
148 MuleMessage resultMessage = new DefaultMuleMessage(result, event.getMessage());
149 setMessageContextProperties(resultMessage, call.getMessageContext());
150 return resultMessage;
151 }
152 }
153
154 protected Call getCall(MuleEvent event, Object[] args) throws Exception
155 {
156 EndpointURI endpointUri = event.getEndpoint().getEndpointURI();
157 Object method = getInitialMethod(event);
158 Call call = (Call) service.createCall();
159 parseStyle(event, call);
160 parseUse(event, call);
161
162
163 BeanUtils.populateWithoutFail(call, event.getEndpoint().getProperties(), false);
164 call.setTargetEndpointAddress(endpointUri.getAddress());
165
166 method = refineMethod(event, call, method);
167 String methodNamespace = call.getOperationName().getNamespaceURI();
168
169
170 call.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
171 call.setProperty(MuleProperties.MULE_ENDPOINT_PROPERTY, event.getEndpoint());
172
173 setCustomProperties(event, call);
174 call.setTimeout(new Integer(event.getTimeout()));
175 setUserCredentials(endpointUri, call);
176
177 Map methodCalls = (Map)event.getMessage().getProperty(AxisConnector.SOAP_METHODS);
178 if (methodCalls == null && !(method instanceof SoapMethod))
179 {
180 buildSoapMethods(event, call, method, methodNamespace, args);
181 }
182
183 setCallParams(call, event, call.getOperationName());
184 setSoapAction(event, endpointUri, call);
185 addAttachments(event, call);
186 return call;
187 }
188
189 protected void addAttachments(MuleEvent event, Call call)
190 {
191
192 for (Iterator iterator = event.getMessage().getAttachmentNames().iterator(); iterator.hasNext();)
193 {
194 String name = (String)iterator.next();
195 DataHandler dh = event.getMessage().getAttachment(name);
196 AttachmentPart part = new AttachmentPart(dh);
197 call.addAttachmentPart(part);
198 }
199 }
200
201 protected void setSoapAction(MuleEvent event, EndpointURI endpointUri, Call call)
202 {
203
204 String soapAction = (String)event.getMessage().getProperty(SoapConstants.SOAP_ACTION_PROPERTY);
205 if (soapAction != null)
206 {
207 soapAction = parseSoapAction(soapAction, call.getOperationName(), event);
208 call.setSOAPActionURI(soapAction);
209 call.setUseSOAPAction(Boolean.TRUE.booleanValue());
210 }
211 else
212 {
213 call.setSOAPActionURI(endpointUri.getAddress());
214 }
215 }
216
217 protected void buildSoapMethods(MuleEvent event, Call call, Object method, String methodNamespace, Object[] args)
218 {
219 List params = new ArrayList();
220 for (int i = 0; i < args.length; i++)
221 {
222 if (args[i] == null)
223 {
224 QName qname = call.getTypeMapping().getTypeQName(Object.class);
225 params.add("value" + i + ";qname{" + qname.getPrefix() + ":" + qname.getLocalPart() + ":"
226 + qname.getNamespaceURI() + "};in");
227 }
228 else if (args[i] instanceof DataHandler[])
229 {
230 params.add("attachments;qname{DataHandler:http://xml.apache.org/xml-soap};in");
231
232 }
233 else if (args[i] instanceof Map && connector.isTreatMapAsNamedParams())
234 {
235 for (Iterator iterator = ((Map)args[i]).entrySet().iterator(); iterator.hasNext();)
236 {
237 Map.Entry entry = (Map.Entry)iterator.next();
238 if (call.getTypeMapping().getTypeQName(entry.getValue().getClass()) != null)
239 {
240 QName type = call.getTypeMapping().getTypeQName(entry.getValue().getClass());
241 params.add("qname{" + entry.getKey().toString()
242 + (methodNamespace == null ? "" : ":" + methodNamespace) + "};qname{"
243 + type.getPrefix() + ":" + type.getLocalPart() + ":"
244 + type.getNamespaceURI() + "};in");
245 }
246 else
247 {
248 params.add("value" + i + ";qname{"
249 + Types.getLocalNameFromFullName(args[i].getClass().getName()) + ":"
250 + Namespaces.makeNamespace(args[i].getClass().getName()) + "};in");
251 params.add("qname{" + entry.getKey().toString()
252 + (methodNamespace == null ? "" : ":" + methodNamespace) + "};qname{"
253 + Types.getLocalNameFromFullName(args[i].getClass().getName()) + ":"
254 + Namespaces.makeNamespace(args[i].getClass().getName()) + "};in");
255 }
256
257 }
258 }
259 else if (call.getTypeMapping().getTypeQName(args[i].getClass()) != null)
260 {
261 QName qname = call.getTypeMapping().getTypeQName(args[i].getClass());
262 params.add("value" + i + ";qname{" + qname.getPrefix() + ":" + qname.getLocalPart() + ":"
263 + qname.getNamespaceURI() + "};in");
264 }
265 else
266 {
267 params.add("value" + i + ";qname{"
268 + Types.getLocalNameFromFullName(args[i].getClass().getName()) + ":"
269 + Namespaces.makeNamespace(args[i].getClass().getName()) + "};in");
270 }
271 }
272
273 HashMap map = new HashMap();
274 map.put(method, params);
275 event.getMessage().setProperty(AxisConnector.SOAP_METHODS, map);
276 }
277
278 protected void setUserCredentials(EndpointURI endpointUri, Call call)
279 {
280 if (endpointUri.getUserInfo() != null)
281 {
282 call.setUsername(endpointUri.getUser());
283 call.setPassword(endpointUri.getPassword());
284 }
285 }
286
287 protected void setCustomProperties(MuleEvent event, Call call)
288 {
289 for (Iterator iter = event.getMessage().getPropertyNames().iterator(); iter.hasNext();)
290 {
291 String key = (String)iter.next();
292 if (!(key.startsWith(MuleProperties.PROPERTY_PREFIX)))
293 {
294 Object value = event.getMessage().getProperty(key);
295 if (value != null)
296 {
297 call.setProperty(key, value);
298 }
299 }
300 }
301 }
302
303 protected Object refineMethod(MuleEvent event, Call call, Object method)
304 {
305 if (method instanceof String)
306 {
307
308
309 String methodNamespace = (String)event.getMessage().getProperty(SoapConstants.METHOD_NAMESPACE_PROPERTY);
310 if (methodNamespace != null)
311 {
312 call.setOperationName(new QName(methodNamespace, method.toString()));
313 }
314 else
315 {
316 call.setOperationName(new QName(method.toString()));
317 }
318 }
319 else if (method instanceof QName)
320 {
321 call.setOperationName((QName)method);
322 method = ((QName)method).getLocalPart();
323 }
324 else
325 {
326 call.setOperationName(((SoapMethod)method).getName());
327 }
328 return method;
329 }
330
331 protected void parseUse(MuleEvent event, Call call)
332 {
333
334 String use = event.getMessage().getStringProperty(AxisConnector.USE, null);
335 if (use != null)
336 {
337 Use u = Use.getUse(use);
338 if (u == null)
339 {
340 throw new IllegalArgumentException(
341 CoreMessages.valueIsInvalidFor(use, AxisConnector.USE).toString());
342 }
343 else
344 {
345 call.setOperationUse(u);
346 }
347 }
348 }
349
350 protected void parseStyle(MuleEvent event, Call call)
351 {
352
353
354
355 String style = event.getMessage().getStringProperty(AxisConnector.STYLE, null);
356 if (style != null)
357 {
358 Style s = Style.getStyle(style);
359 if (s == null)
360 {
361 throw new IllegalArgumentException(
362 CoreMessages.valueIsInvalidFor(style, AxisConnector.STYLE).toString());
363 }
364 else
365 {
366 call.setOperationStyle(s);
367 }
368 }
369 }
370
371 protected Object getInitialMethod(MuleEvent event) throws DispatchException
372 {
373 Object method = event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY);
374 if (method == null)
375 {
376 method = event.getEndpoint().getEndpointURI().getParams().getProperty(MuleProperties.MULE_METHOD_PROPERTY);
377 }
378 if (method == null)
379 {
380 throw new DispatchException(
381 SoapMessages.cannotInvokeCallWithoutOperation(), event.getMessage(),
382 event.getEndpoint());
383 }
384 else if (method instanceof SoapMethod)
385 {
386 synchronized (this)
387 {
388 if (callParameters == null)
389 {
390 callParameters = new HashMap();
391 }
392 callParameters.put(((SoapMethod)method).getName().getLocalPart(), method);
393 }
394 }
395 return method;
396 }
397
398 private Object[] getArgs(MuleEvent event) throws TransformerException
399 {
400 Object payload = event.transformMessage();
401 Object[] args;
402 if (payload instanceof Object[])
403 {
404 args = (Object[])payload;
405 }
406 else
407 {
408 args = new Object[]{payload};
409 }
410 if (event.getMessage().getAttachmentNames() != null
411 && event.getMessage().getAttachmentNames().size() > 0)
412 {
413 ArrayList attachments = new ArrayList();
414 Iterator i = event.getMessage().getAttachmentNames().iterator();
415 while (i.hasNext())
416 {
417 attachments.add(event.getMessage().getAttachment((String)i.next()));
418 }
419 ArrayList temp = new ArrayList(Arrays.asList(args));
420 temp.add(attachments.toArray(new DataHandler[0]));
421 args = temp.toArray();
422 }
423 return args;
424 }
425
426 protected void setMessageContextProperties(MuleMessage message, MessageContext ctx)
427 {
428 String temp = ctx.getStrProp(MuleProperties.MULE_CORRELATION_ID_PROPERTY);
429 if (StringUtils.isNotBlank(temp))
430 {
431 message.setCorrelationId(temp);
432 }
433 temp = ctx.getStrProp(MuleProperties.MULE_CORRELATION_GROUP_SIZE_PROPERTY);
434 if (StringUtils.isNotBlank(temp))
435 {
436 message.setCorrelationGroupSize(Integer.parseInt(temp));
437 }
438 temp = ctx.getStrProp(MuleProperties.MULE_CORRELATION_SEQUENCE_PROPERTY);
439 if (StringUtils.isNotBlank(temp))
440 {
441 message.setCorrelationSequence(Integer.parseInt(temp));
442 }
443 temp = ctx.getStrProp(MuleProperties.MULE_REPLY_TO_PROPERTY);
444 if (StringUtils.isNotBlank(temp))
445 {
446 message.setReplyTo(temp);
447 }
448 }
449
450 protected void setMessageContextAttachments(MuleMessage message, MessageContext ctx) throws Exception
451 {
452 int x = 0;
453 for (Iterator iterator = ctx.getMessage().getAttachments(); iterator.hasNext(); x++)
454 {
455 message.addAttachment(String.valueOf(x),
456 ((AttachmentPart)iterator.next()).getActivationDataHandler());
457 }
458 }
459
460 protected static MuleMessage createMessage(Object result, Call call)
461 {
462 if (result == null)
463 {
464 result = NullPayload.getInstance();
465 }
466 Map props = new HashMap();
467 Iterator iter = call.getMessageContext().getPropertyNames();
468 Object key;
469 while (iter.hasNext())
470 {
471 key = iter.next();
472 props.put(key, call.getMessageContext().getProperty(key.toString()));
473 }
474 props.put("soap.message", call.getMessageContext().getMessage());
475 call.clearHeaders();
476 call.clearOperation();
477 return new DefaultMuleMessage(result, props);
478 }
479
480 public String parseSoapAction(String soapAction, QName method, MuleEvent event)
481 {
482 EndpointURI endpointURI = event.getEndpoint().getEndpointURI();
483 Map properties = new HashMap();
484 MuleMessage msg = event.getMessage();
485 for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
486 {
487 String propertyKey = (String)iterator.next();
488 properties.put(propertyKey, msg.getProperty(propertyKey));
489 }
490 properties.put(MuleProperties.MULE_METHOD_PROPERTY, method.getLocalPart());
491 properties.put("methodNamespace", method.getNamespaceURI());
492 properties.put("address", endpointURI.getAddress());
493 properties.put("scheme", endpointURI.getScheme());
494 properties.put("host", endpointURI.getHost());
495 properties.put("port", String.valueOf(endpointURI.getPort()));
496 properties.put("path", endpointURI.getPath());
497 properties.put("hostInfo", endpointURI.getScheme()
498 + "://"
499 + endpointURI.getHost()
500 + (endpointURI.getPort() > -1
501 ? ":" + String.valueOf(endpointURI.getPort()) : ""));
502 if (event.getService() != null)
503 {
504 properties.put("serviceName", event.getService().getName());
505 }
506
507 TemplateParser tp = TemplateParser.createSquareBracesStyleParser();
508 soapAction = tp.parse(properties, soapAction);
509
510 if (logger.isDebugEnabled())
511 {
512 logger.debug("SoapAction for this call is: " + soapAction);
513 }
514 return soapAction;
515 }
516
517 private void setCallParams(Call call, MuleEvent event, QName method) throws ClassNotFoundException
518 {
519 synchronized (this)
520 {
521 if (callParameters == null)
522 {
523 loadCallParams(event, method.getNamespaceURI());
524 }
525 }
526
527 SoapMethod soapMethod = (SoapMethod)event.getMessage()
528 .removeProperty(MuleProperties.MULE_SOAP_METHOD);
529 if (soapMethod == null)
530 {
531 soapMethod = (SoapMethod)callParameters.get(method.getLocalPart());
532 }
533
534 if (soapMethod != null)
535 {
536 for (Iterator iterator = soapMethod.getNamedParameters().iterator(); iterator.hasNext();)
537 {
538 NamedParameter parameter = (NamedParameter)iterator.next();
539 call.addParameter(parameter.getName(), parameter.getType(), parameter.getMode());
540 }
541
542 if (soapMethod.getReturnType() != null)
543 {
544 call.setReturnType(soapMethod.getReturnType());
545 }
546 else if (soapMethod.getReturnClass() != null)
547 {
548 call.setReturnClass(soapMethod.getReturnClass());
549 }
550
551 call.setOperationName(soapMethod.getName());
552 }
553 }
554
555 private void loadCallParams(MuleEvent event, String namespace) throws ClassNotFoundException
556 {
557 Map methodCalls = (Map)event.getMessage().getProperty(AxisConnector.SOAP_METHODS);
558 if (methodCalls == null)
559 {
560 return;
561 }
562
563 Map.Entry entry;
564 SoapMethod soapMethod;
565 callParameters = new HashMap();
566
567 for (Iterator iterator = methodCalls.entrySet().iterator(); iterator.hasNext();)
568 {
569 entry = (Map.Entry)iterator.next();
570 if (StringUtils.isEmpty(namespace))
571 {
572 if (entry.getValue() instanceof List)
573 {
574 soapMethod = new SoapMethod(entry.getKey().toString(), (List)entry.getValue());
575 }
576 else
577 {
578 soapMethod = new SoapMethod(entry.getKey().toString(), entry.getValue().toString());
579 }
580 }
581 else
582 {
583 if (entry.getValue() instanceof List)
584 {
585 soapMethod = new SoapMethod(new QName(namespace, entry.getKey().toString()),
586 (List)entry.getValue());
587 }
588 else
589 {
590 soapMethod = new SoapMethod(new QName(namespace, entry.getKey().toString()),
591 entry.getValue().toString());
592 }
593 }
594 callParameters.put(soapMethod.getName().getLocalPart(), soapMethod);
595 }
596 }
597
598 }