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