KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mule > providers > soap > axis > AxisMessageDispatcher


1 /*
2  * $Id: AxisMessageDispatcher.java 3982 2006-11-22 14:28:01Z lajos $
3  * --------------------------------------------------------------------------------------
4  * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
5  *
6  * The software in this package is published under the terms of the MuleSource MPL
7  * license, a copy of which has been included with this distribution in the
8  * LICENSE.txt file.
9  */

10
11 package org.mule.providers.soap.axis;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.List JavaDoc;
18 import java.util.Map JavaDoc;
19 import java.util.Properties JavaDoc;
20
21 import javax.activation.DataHandler JavaDoc;
22 import javax.xml.namespace.QName JavaDoc;
23 import javax.xml.soap.SOAPEnvelope JavaDoc;
24
25 import org.apache.axis.AxisProperties;
26 import org.apache.axis.EngineConfiguration;
27 import org.apache.axis.Message;
28 import org.apache.axis.MessageContext;
29 import org.apache.axis.attachments.AttachmentPart;
30 import org.apache.axis.client.Call;
31 import org.apache.axis.client.Service;
32 import org.apache.axis.configuration.FileProvider;
33 import org.apache.axis.constants.Style;
34 import org.apache.axis.constants.Use;
35 import org.apache.axis.wsdl.fromJava.Namespaces;
36 import org.apache.axis.wsdl.fromJava.Types;
37 import org.apache.commons.lang.StringUtils;
38 import org.mule.config.MuleProperties;
39 import org.mule.config.i18n.Messages;
40 import org.mule.impl.MuleMessage;
41 import org.mule.impl.endpoint.MuleEndpointURI;
42 import org.mule.providers.AbstractMessageDispatcher;
43 import org.mule.providers.NullPayload;
44 import org.mule.providers.soap.NamedParameter;
45 import org.mule.providers.soap.SoapConstants;
46 import org.mule.providers.soap.SoapMethod;
47 import org.mule.umo.UMOEvent;
48 import org.mule.umo.UMOException;
49 import org.mule.umo.UMOMessage;
50 import org.mule.umo.endpoint.UMOEndpointURI;
51 import org.mule.umo.endpoint.UMOImmutableEndpoint;
52 import org.mule.umo.provider.DispatchException;
53 import org.mule.umo.transformer.TransformerException;
54 import org.mule.util.BeanUtils;
55 import org.mule.util.TemplateParser;
56
57 /**
58  * <code>AxisMessageDispatcher</code> is used to make soap requests via the Axis
59  * soap client.
60  */

61 public class AxisMessageDispatcher extends AbstractMessageDispatcher
62 {
63
64     protected EngineConfiguration clientConfig;
65     protected AxisConnector connector;
66     protected Service service;
67     private Map JavaDoc callParameters;
68
69     public AxisMessageDispatcher(UMOImmutableEndpoint endpoint)
70     {
71         super(endpoint);
72         this.connector = (AxisConnector)endpoint.getConnector();
73         AxisProperties.setProperty("axis.doAutoTypes", Boolean.toString(connector.isDoAutoTypes()));
74     }
75
76     protected void doConnect(UMOImmutableEndpoint endpoint) throws Exception JavaDoc
77     {
78         if (service == null)
79         {
80             service = createService(endpoint);
81         }
82     }
83
84     protected void doDisconnect() throws Exception JavaDoc
85     {
86         if (service != null)
87         {
88             service = null;
89         }
90     }
91
92     protected void doDispose()
93     {
94         // template method
95
}
96
97     protected synchronized EngineConfiguration getClientConfig(UMOImmutableEndpoint endpoint)
98     {
99         if (clientConfig == null)
100         {
101             // Allow the client config to be set on the endpoint
102
String JavaDoc config;
103             config = (String JavaDoc)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(UMOImmutableEndpoint endpoint) throws Exception JavaDoc
118     {
119         // Create a simple axis service without wsdl
120
EngineConfiguration config = getClientConfig(endpoint);
121         return new Service(config);
122     }
123
124     protected void doDispatch(UMOEvent event) throws Exception JavaDoc
125     {
126         Object JavaDoc[] args = getArgs(event);
127         Call call = getCall(event, args);
128         // dont use invokeOneWay here as we are already in a thread pool.
129
// Axis creates a new thread for every invoke one way call. nasty!
130
// Mule overides the default Axis HttpSender to return immediately if
131
// the axis.one.way property is set
132
call.setProperty("axis.one.way", Boolean.TRUE);
133         call.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
134         call.invoke(args);
135
136     }
137
138     protected UMOMessage doSend(UMOEvent event) throws Exception JavaDoc
139     {
140         Call call;
141         Object JavaDoc result;
142         Object JavaDoc[] args = getArgs(event);
143         call = getCall(event, args);
144         result = call.invoke(args);
145         if (result == null)
146         {
147             return null;
148         }
149         else
150         {
151             UMOMessage resultMessage = new MuleMessage(result, event.getMessage());
152             setMessageContextProperties(resultMessage, call.getMessageContext());
153             return resultMessage;
154         }
155     }
156
157     protected Call getCall(UMOEvent event, Object JavaDoc[] args) throws Exception JavaDoc
158     {
159         UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
160         Object JavaDoc method = event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY);
161         if (method == null)
162         {
163             method = event.getEndpoint().getEndpointURI().getParams().getProperty(
164                 MuleProperties.MULE_METHOD_PROPERTY);
165         }
166         if (method == null)
167         {
168             throw new DispatchException(new org.mule.config.i18n.Message("soap", 4), event.getMessage(),
169                 event.getEndpoint());
170         }
171         else if (method instanceof SoapMethod)
172         {
173             synchronized (this)
174             {
175                 if (callParameters == null)
176                 {
177                     callParameters = new HashMap JavaDoc();
178                 }
179                 callParameters.put(((SoapMethod)method).getName().getLocalPart(), method);
180             }
181         }
182
183         Call call = (Call)service.createCall();
184
185         String JavaDoc style = event.getMessage().getStringProperty("style", null);
186         String JavaDoc use = event.getMessage().getStringProperty("use", null);
187
188         // Note that Axis has specific rules to how these two variables are
189
// combined. This is handled for us
190
// Set style: RPC/wrapped/Doc/Message
191
if (style != null)
192         {
193             Style s = Style.getStyle(style);
194             if (s == null)
195             {
196                 throw new IllegalArgumentException JavaDoc(new org.mule.config.i18n.Message(
197                     Messages.VALUE_X_IS_INVALID_FOR_X, style, "style").toString());
198             }
199             else
200             {
201                 call.setOperationStyle(s);
202             }
203         }
204         // Set use: Endcoded/Literal
205
if (use != null)
206         {
207             Use u = Use.getUse(use);
208             if (u == null)
209             {
210                 throw new IllegalArgumentException JavaDoc(new org.mule.config.i18n.Message(
211                     Messages.VALUE_X_IS_INVALID_FOR_X, use, "use").toString());
212             }
213             else
214             {
215                 call.setOperationUse(u);
216             }
217         }
218
219         // set properties on the call from the endpoint properties
220
BeanUtils.populateWithoutFail(call, event.getEndpoint().getProperties(), false);
221         call.setTargetEndpointAddress(endpointUri.getAddress());
222
223         String JavaDoc methodNamespace = null;
224         if (method instanceof String JavaDoc)
225         {
226             // Set a custome method namespace if one is set. This will be used forthe
227
// parameters too
228
methodNamespace = (String JavaDoc)event.getMessage().getProperty(SoapConstants.METHOD_NAMESPACE_PROPERTY);
229             if (methodNamespace != null)
230             {
231                 call.setOperationName(new QName JavaDoc(methodNamespace, method.toString()));
232             }
233             else
234             {
235                 call.setOperationName(new QName JavaDoc(method.toString()));
236             }
237         }
238         else if (method instanceof QName JavaDoc)
239         {
240             call.setOperationName((QName JavaDoc)method);
241             method = ((QName JavaDoc)method).getLocalPart();
242         }
243         else
244         {
245             call.setOperationName(((SoapMethod)method).getName());
246         }
247
248         methodNamespace = call.getOperationName().getNamespaceURI();
249
250         // set Mule event here so that handlers can extract info
251
call.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
252         call.setProperty(MuleProperties.MULE_ENDPOINT_PROPERTY, event.getEndpoint());
253         // Set timeout
254
call.setTimeout(new Integer JavaDoc(event.getTimeout()));
255
256         // Add User Creds
257
if (endpointUri.getUserInfo() != null)
258         {
259             call.setUsername(endpointUri.getUsername());
260             call.setPassword(endpointUri.getPassword());
261         }
262
263         Map JavaDoc methodCalls = (Map JavaDoc)event.getMessage().getProperty("soapMethods");
264         if (methodCalls == null && !(method instanceof SoapMethod))
265         {
266             List JavaDoc params = new ArrayList JavaDoc();
267             for (int i = 0; i < args.length; i++)
268             {
269                 if (args[i] == null)
270                 {
271                     QName JavaDoc qname = call.getTypeMapping().getTypeQName(Object JavaDoc.class);
272                     params.add("value" + i + ";qname{" + qname.getPrefix() + ":" + qname.getLocalPart() + ":"
273                                + qname.getNamespaceURI() + "};in");
274                 }
275                 else if (args[i] instanceof DataHandler JavaDoc[])
276                 {
277                     params.add("attachments;qname{DataHandler:http://xml.apache.org/xml-soap};in");
278                     // Convert key/value pairs into the parameters
279
}
280                 else if (args[i] instanceof Map JavaDoc && connector.isTreatMapAsNamedParams())
281                 {
282                     for (Iterator JavaDoc iterator = ((Map JavaDoc)args[i]).entrySet().iterator(); iterator.hasNext();)
283                     {
284                         Map.Entry JavaDoc entry = (Map.Entry JavaDoc)iterator.next();
285                         if (call.getTypeMapping().getTypeQName(entry.getValue().getClass()) != null)
286                         {
287                             QName JavaDoc type = call.getTypeMapping().getTypeQName(entry.getValue().getClass());
288                             params.add("qname{" + entry.getKey().toString()
289                                        + (methodNamespace == null ? "" : ":" + methodNamespace) + "};qname{"
290                                        + type.getPrefix() + ":" + type.getLocalPart() + ":"
291                                        + type.getNamespaceURI() + "};in");
292                         }
293                         else
294                         {
295                             params.add("value" + i + ";qname{"
296                                        + Types.getLocalNameFromFullName(args[i].getClass().getName()) + ":"
297                                        + Namespaces.makeNamespace(args[i].getClass().getName()) + "};in");
298                             params.add("qname{" + entry.getKey().toString()
299                                        + (methodNamespace == null ? "" : ":" + methodNamespace) + "};qname{"
300                                        + Types.getLocalNameFromFullName(args[i].getClass().getName()) + ":"
301                                        + Namespaces.makeNamespace(args[i].getClass().getName()) + "};in");
302                         }
303
304                     }
305                 }
306                 else if (call.getTypeMapping().getTypeQName(args[i].getClass()) != null)
307                 {
308                     QName JavaDoc qname = call.getTypeMapping().getTypeQName(args[i].getClass());
309                     params.add("value" + i + ";qname{" + qname.getPrefix() + ":" + qname.getLocalPart() + ":"
310                                + qname.getNamespaceURI() + "};in");
311                 }
312                 else
313                 {
314                     params.add("value" + i + ";qname{"
315                                + Types.getLocalNameFromFullName(args[i].getClass().getName()) + ":"
316                                + Namespaces.makeNamespace(args[i].getClass().getName()) + "};in");
317                 }
318             }
319
320             HashMap JavaDoc map = new HashMap JavaDoc();
321             map.put(method, params);
322             event.getMessage().setProperty("soapMethods", map);
323         }
324
325         setCallParams(call, event, call.getOperationName());
326
327         // Set custom soap action if set on the event or endpoint
328
String JavaDoc soapAction = (String JavaDoc)event.getMessage().getProperty(SoapConstants.SOAP_ACTION_PROPERTY);
329         if (soapAction != null)
330         {
331             soapAction = parseSoapAction(soapAction, call.getOperationName(), event);
332             call.setSOAPActionURI(soapAction);
333             call.setUseSOAPAction(Boolean.TRUE.booleanValue());
334         }
335         else
336         {
337             call.setSOAPActionURI(endpointUri.getAddress());
338         }
339
340         // Add any attachments to the call
341
for (Iterator JavaDoc iterator = event.getMessage().getAttachmentNames().iterator(); iterator.hasNext();)
342         {
343             String JavaDoc name = (String JavaDoc)iterator.next();
344             DataHandler JavaDoc dh = event.getMessage().getAttachment(name);
345             AttachmentPart part = new AttachmentPart(dh);
346             call.addAttachmentPart(part);
347         }
348         return call;
349     }
350
351     private Object JavaDoc[] getArgs(UMOEvent event) throws TransformerException
352     {
353         Object JavaDoc payload = event.getTransformedMessage();
354         Object JavaDoc[] args;
355         if (payload instanceof Object JavaDoc[])
356         {
357             args = (Object JavaDoc[])payload;
358         }
359         else
360         {
361             args = new Object JavaDoc[]{payload};
362         }
363         if (event.getMessage().getAttachmentNames() != null
364             && event.getMessage().getAttachmentNames().size() > 0)
365         {
366             ArrayList JavaDoc attachments = new ArrayList JavaDoc();
367             Iterator JavaDoc i = event.getMessage().getAttachmentNames().iterator();
368             while (i.hasNext())
369             {
370                 attachments.add(event.getMessage().getAttachment((String JavaDoc)i.next()));
371             }
372             ArrayList JavaDoc temp = new ArrayList JavaDoc(Arrays.asList(args));
373             temp.add(attachments.toArray(new DataHandler JavaDoc[0]));
374             args = temp.toArray();
375         }
376         return args;
377     }
378
379     protected void setMessageContextProperties(UMOMessage message, MessageContext ctx)
380     {
381         String JavaDoc temp = ctx.getStrProp(MuleProperties.MULE_CORRELATION_ID_PROPERTY);
382         if (StringUtils.isNotBlank(temp))
383         {
384             message.setCorrelationId(temp);
385         }
386         temp = ctx.getStrProp(MuleProperties.MULE_CORRELATION_GROUP_SIZE_PROPERTY);
387         if (StringUtils.isNotBlank(temp))
388         {
389             message.setCorrelationGroupSize(Integer.parseInt(temp));
390         }
391         temp = ctx.getStrProp(MuleProperties.MULE_CORRELATION_SEQUENCE_PROPERTY);
392         if (StringUtils.isNotBlank(temp))
393         {
394             message.setCorrelationSequence(Integer.parseInt(temp));
395         }
396         temp = ctx.getStrProp(MuleProperties.MULE_REPLY_TO_PROPERTY);
397         if (StringUtils.isNotBlank(temp))
398         {
399             message.setReplyTo(temp);
400         }
401     }
402
403     protected void setMessageContextAttachments(UMOMessage message, MessageContext ctx) throws Exception JavaDoc
404     {
405         int x = 0;
406         for (Iterator JavaDoc iterator = ctx.getMessage().getAttachments(); iterator.hasNext(); x++)
407         {
408             message.addAttachment(String.valueOf(x),
409                 ((AttachmentPart)iterator.next()).getActivationDataHandler());
410         }
411     }
412
413     /**
414      * Make a specific request to the underlying transport
415      *
416      * @param endpoint the endpoint to use when connecting to the resource
417      * @param timeout the maximum time the operation should block before returning.
418      * The call should return immediately if there is data available. If
419      * no data becomes available before the timeout elapses, null will be
420      * returned
421      * @return the result of the request wrapped in a UMOMessage object. Null will be
422      * returned if no data was avaialable
423      * @throws Exception if the call to the underlying protocal cuases an exception
424      */

425     protected UMOMessage doReceive(UMOImmutableEndpoint endpoint, long timeout) throws Exception JavaDoc
426     {
427         Call call = new Call(service);
428         String JavaDoc uri = endpoint.getEndpointURI().toString();
429         call.setSOAPActionURI(uri);
430         call.setTargetEndpointAddress(uri);
431
432         Properties JavaDoc params = endpoint.getEndpointURI().getUserParams();
433         String JavaDoc method = (String JavaDoc)params.remove(MuleProperties.MULE_METHOD_PROPERTY);
434         call.setOperationName(method);
435
436         String JavaDoc args[] = new String JavaDoc[params.size()];
437         int i = 0;
438         for (Iterator JavaDoc iterator = params.values().iterator(); iterator.hasNext(); i++)
439         {
440             args[i] = iterator.next().toString();
441         }
442
443         call.setOperationName(method);
444         call.setProperty(MuleProperties.MULE_ENDPOINT_PROPERTY, endpoint);
445         Object JavaDoc result = call.invoke(method, args);
446         return createMessage(result, call);
447     }
448
449     public UMOMessage receive(String JavaDoc endpoint, Object JavaDoc[] args) throws Exception JavaDoc
450     {
451         Call call = new Call(service);
452
453         call.setSOAPActionURI(endpoint);
454         call.setTargetEndpointAddress(endpoint);
455
456         if (!endpoint.startsWith("axis:"))
457         {
458             endpoint = "axis:" + endpoint;
459         }
460         UMOEndpointURI ep = new MuleEndpointURI(endpoint);
461         String JavaDoc method = (String JavaDoc)ep.getParams().remove(MuleProperties.MULE_METHOD_PROPERTY);
462         call.setOperationName(method);
463
464         call.setOperationName(method);
465         Object JavaDoc result = call.invoke(method, args);
466         return createMessage(result, call);
467     }
468
469     public UMOMessage receive(String JavaDoc endpoint, SOAPEnvelope JavaDoc envelope) throws Exception JavaDoc
470     {
471         Call call = new Call(service);
472
473         call.setSOAPActionURI(endpoint);
474         call.setTargetEndpointAddress(endpoint);
475         Object JavaDoc result = call.invoke(new Message(envelope));
476         return createMessage(result, call);
477     }
478
479     protected UMOMessage createMessage(Object JavaDoc result, Call call)
480     {
481         if (result == null)
482         {
483             result = new NullPayload();
484         }
485         Map JavaDoc props = new HashMap JavaDoc();
486         Iterator JavaDoc iter = call.getMessageContext().getPropertyNames();
487         Object JavaDoc key;
488         while (iter.hasNext())
489         {
490             key = iter.next();
491             props.put(key, call.getMessageContext().getProperty(key.toString()));
492         }
493         props.put("soap.message", call.getMessageContext().getMessage());
494         call.clearHeaders();
495         call.clearOperation();
496         return new MuleMessage(result, props);
497     }
498
499     public Object JavaDoc getDelegateSession() throws UMOException
500     {
501         return null;
502     }
503
504     public String JavaDoc parseSoapAction(String JavaDoc soapAction, QName JavaDoc method, UMOEvent event)
505     {
506
507         UMOEndpointURI endpointURI = event.getEndpoint().getEndpointURI();
508         Map JavaDoc properties = new HashMap JavaDoc();
509         UMOMessage msg = event.getMessage();
510         for (Iterator JavaDoc iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
511         {
512             String JavaDoc propertyKey = (String JavaDoc)iterator.next();
513             properties.put(propertyKey, msg.getProperty(propertyKey));
514         }
515         properties.put(MuleProperties.MULE_METHOD_PROPERTY, method.getLocalPart());
516         properties.put("methodNamespace", method.getNamespaceURI());
517         properties.put("address", endpointURI.getAddress());
518         properties.put("scheme", endpointURI.getScheme());
519         properties.put("host", endpointURI.getHost());
520         properties.put("port", String.valueOf(endpointURI.getPort()));
521         properties.put("path", endpointURI.getPath());
522         properties.put("hostInfo", endpointURI.getScheme()
523                                    + "://"
524                                    + endpointURI.getHost()
525                                    + (endpointURI.getPort() > -1
526                                                    ? ":" + String.valueOf(endpointURI.getPort()) : ""));
527         if (event.getComponent() != null)
528         {
529             properties.put("serviceName", event.getComponent().getDescriptor().getName());
530         }
531
532         TemplateParser tp = TemplateParser.createAntStyleParser();
533         soapAction = tp.parse(properties, soapAction);
534
535         if (logger.isDebugEnabled())
536         {
537             logger.debug("SoapAction for this call is: " + soapAction);
538         }
539         return soapAction;
540     }
541
542     private void setCallParams(Call call, UMOEvent event, QName JavaDoc method) throws ClassNotFoundException JavaDoc
543     {
544         synchronized (this)
545         {
546             if (callParameters == null)
547             {
548                 loadCallParams(event, method.getNamespaceURI());
549             }
550         }
551
552         SoapMethod soapMethod = (SoapMethod)event.getMessage()
553             .removeProperty(MuleProperties.MULE_SOAP_METHOD);
554         if (soapMethod == null)
555         {
556             soapMethod = (SoapMethod)callParameters.get(method.getLocalPart());
557         }
558
559         if (soapMethod != null)
560         {
561             for (Iterator JavaDoc iterator = soapMethod.getNamedParameters().iterator(); iterator.hasNext();)
562             {
563                 NamedParameter parameter = (NamedParameter)iterator.next();
564                 call.addParameter(parameter.getName(), parameter.getType(), parameter.getMode());
565             }
566
567             if (soapMethod.getReturnType() != null)
568             {
569                 call.setReturnType(soapMethod.getReturnType());
570             }
571             else if (soapMethod.getReturnClass() != null)
572             {
573                 call.setReturnClass(soapMethod.getReturnClass());
574             }
575
576             call.setOperationName(soapMethod.getName());
577         }
578     }
579
580     private void loadCallParams(UMOEvent event, String JavaDoc namespace) throws ClassNotFoundException JavaDoc
581     {
582         Map JavaDoc methodCalls = (Map JavaDoc)event.getMessage().getProperty("soapMethods");
583         if (methodCalls == null)
584         {
585             return;
586         }
587
588         Map.Entry JavaDoc entry;
589         SoapMethod soapMethod;
590         callParameters = new HashMap JavaDoc();
591
592         for (Iterator JavaDoc iterator = methodCalls.entrySet().iterator(); iterator.hasNext();)
593         {
594             entry = (Map.Entry JavaDoc)iterator.next();
595             if (StringUtils.isEmpty(namespace))
596             {
597                 if (entry.getValue() instanceof List JavaDoc)
598                 {
599                     soapMethod = new SoapMethod(entry.getKey().toString(), (List JavaDoc)entry.getValue());
600                 }
601                 else
602                 {
603                     soapMethod = new SoapMethod(entry.getKey().toString(), entry.getValue().toString());
604                 }
605             }
606             else
607             {
608                 if (entry.getValue() instanceof List JavaDoc)
609                 {
610                     soapMethod = new SoapMethod(new QName JavaDoc(namespace, entry.getKey().toString()),
611                         (List JavaDoc)entry.getValue());
612                 }
613                 else
614                 {
615                     soapMethod = new SoapMethod(new QName JavaDoc(namespace, entry.getKey().toString()),
616                         entry.getValue().toString());
617                 }
618             }
619             callParameters.put(soapMethod.getName().getLocalPart(), soapMethod);
620         }
621     }
622 }
623
Popular Tags