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