Coverage Report - org.mule.providers.soap.xfire.XFireMessageDispatcher
 
Classes in this File Line Coverage Branch Coverage Complexity
XFireMessageDispatcher
0%
0/159
0%
0/34
3.533
 
 1  
 /*
 2  
  * $Id: XFireMessageDispatcher.java 7976 2007-08-21 14:26:13Z dirk.olmes $
 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 CPAL v1.0
 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.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  
  * The XFireMessageDispatcher is used for making Soap client requests to remote
 55  
  * services.
 56  
  */
 57  
 public class XFireMessageDispatcher extends AbstractMessageDispatcher
 58  
 {
 59  
     // Since the MessageDispatcher is guaranteed to serve a single thread,
 60  
     // the Dispatcher can own the xfire Client as an instance variable
 61  0
     protected Client client = null;
 62  
     protected final XFireConnector connector;
 63  0
     private final TemplateParser soapActionTemplateParser = TemplateParser.createAntStyleParser();
 64  
 
 65  
     public XFireMessageDispatcher(UMOImmutableEndpoint endpoint)
 66  
     {
 67  0
         super(endpoint);
 68  0
         this.connector = (XFireConnector) endpoint.getConnector();
 69  0
     }
 70  
 
 71  
     protected void doConnect() throws Exception
 72  
     {
 73  0
         if (client == null)
 74  
         {
 75  0
             final XFire xfire = connector.getXfire();
 76  0
             final String serviceName = getServiceName(endpoint);
 77  0
             final Service service = xfire.getServiceRegistry().getService(serviceName);
 78  
 
 79  0
             if (service == null)
 80  
             {
 81  0
                 throw new FatalConnectException(XFireMessages.serviceIsNull(serviceName), this);
 82  
             }
 83  
             
 84  0
             List inList = connector.getServerInHandlers();
 85  0
             if (inList != null)
 86  
             {
 87  0
                 for (int i = 0; i < inList.size(); i++)
 88  
                 {
 89  0
                     Handler handler = (Handler) ClassUtils.instanciateClass(
 90  
                                         inList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
 91  0
                     service.addInHandler(handler);
 92  
                 }
 93  
             }
 94  
             
 95  0
             List outList = connector.getServerOutHandlers();
 96  0
             if (outList != null)
 97  
             {
 98  0
                 for (int i = 0; i < outList.size(); i++)
 99  
                 {
 100  0
                     Handler handler = (Handler) ClassUtils.instanciateClass(
 101  
                                         outList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
 102  0
                     service.addOutHandler(handler);
 103  
                 }
 104  
             }
 105  
 
 106  
             try
 107  
             {
 108  0
                 this.client = createXFireClient(endpoint, service, xfire);
 109  
             }
 110  0
             catch (Exception ex)
 111  
             {
 112  0
                 disconnect();
 113  0
                 throw ex;
 114  0
             }
 115  
         }
 116  0
     }
 117  
 
 118  
     protected Client createXFireClient(UMOImmutableEndpoint endpoint, Service service, XFire xfire) throws Exception
 119  
     {
 120  0
         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  0
         if (connector.getClientTransport() == null)
 128  
         {
 129  0
             if (!StringUtils.isBlank(transportClass))
 130  
             {
 131  0
                 transportClazz = ClassUtils.loadClass(transportClass, this.getClass());
 132  
             }
 133  
             else
 134  
             {
 135  0
                 transportClazz = MuleUniversalTransport.class;
 136  
             }
 137  
         }
 138  
         else
 139  
         {
 140  0
             transportClazz = ClassUtils.loadClass(connector.getClientTransport(), this.getClass());
 141  
         }
 142  
         
 143  0
         Transport transport = (Transport) transportClazz.getConstructor(null).newInstance(null);
 144  0
         Client client = new Client(transport, service, endpoint.getEndpointURI().toString());
 145  0
         client.setXFire(xfire);
 146  0
         client.setEndpointUri(endpoint.getEndpointURI().toString());
 147  0
         return configureXFireClient(client);
 148  
     }
 149  
 
 150  
     protected Client configureXFireClient(Client client) throws Exception
 151  
     {
 152  0
         client.addInHandler(new MuleHeadersInHandler());
 153  0
         client.addOutHandler(new MuleHeadersOutHandler());
 154  
 
 155  0
         List inList = connector.getClientInHandlers();
 156  0
         if (inList != null)
 157  
         {
 158  0
             for (int i = 0; i < inList.size(); i++)
 159  
             {
 160  0
                 Handler handler = (Handler) ClassUtils.instanciateClass(
 161  
                                         inList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
 162  0
                 client.addInHandler(handler);
 163  
             }
 164  
         }
 165  
         
 166  0
         List outList = connector.getClientOutHandlers();
 167  0
         if (outList != null)
 168  
         {
 169  0
             for (int i = 0; i < outList.size(); i++)
 170  
             {
 171  0
                 Handler handler = (Handler) ClassUtils.instanciateClass(
 172  
                                         outList.get(i).toString(), ClassUtils.NO_ARGS, this.getClass());
 173  0
                 client.addOutHandler(handler);
 174  
             }
 175  
         }
 176  0
         return client;
 177  
     }
 178  
 
 179  
     protected void doDisconnect() throws Exception
 180  
     {
 181  0
         client = null;
 182  0
     }
 183  
 
 184  
     protected void doDispose()
 185  
     {
 186  
         // nothing to do
 187  0
     }
 188  
 
 189  
     protected String getMethod(UMOEvent event) throws DispatchException
 190  
     {
 191  0
         String method = (String)event.getMessage().getProperty(MuleProperties.MULE_METHOD_PROPERTY);     
 192  
                 
 193  0
         if (method == null)
 194  
         {
 195  0
             UMOEndpointURI endpointUri = event.getEndpoint().getEndpointURI();
 196  0
             method = (String)endpointUri.getParams().get(MuleProperties.MULE_METHOD_PROPERTY);
 197  
         }
 198  
         
 199  0
         if (method == null)
 200  
         {
 201  0
             method = (String)event.getEndpoint().getProperties().get(MuleProperties.MULE_METHOD_PROPERTY);
 202  
         }   
 203  
         
 204  0
         if (method == null)
 205  
         {
 206  0
             throw new DispatchException(SoapMessages.cannotInvokeCallWithoutOperation(), 
 207  
                 event.getMessage(), event.getEndpoint());
 208  
         }
 209  
                 
 210  0
         return method;
 211  
     }
 212  
 
 213  
     protected Object[] getArgs(UMOEvent event) throws TransformerException
 214  
     {
 215  0
         Object payload = event.getTransformedMessage();
 216  
         Object[] args;
 217  
 
 218  0
         if (payload instanceof Object[])
 219  
         {
 220  0
             args = (Object[])payload;
 221  
         }
 222  
         else
 223  
         {
 224  0
             args = new Object[]{payload};
 225  
         }
 226  
 
 227  0
         UMOMessage message = event.getMessage();
 228  0
         Set attachmentNames = message.getAttachmentNames();
 229  0
         if (attachmentNames != null && !attachmentNames.isEmpty())
 230  
         {
 231  0
             List attachments = new ArrayList();
 232  0
             for (Iterator i = attachmentNames.iterator(); i.hasNext();)
 233  
             {
 234  0
                 attachments.add(message.getAttachment((String)i.next()));
 235  
             }
 236  0
             List temp = new ArrayList(Arrays.asList(args));
 237  0
             temp.add(attachments.toArray(new DataHandler[0]));
 238  0
             args = temp.toArray();
 239  
         }
 240  
 
 241  0
         return args;
 242  
     }
 243  
 
 244  
     protected UMOMessage doSend(UMOEvent event) throws Exception
 245  
     {
 246  0
         if (event.getEndpoint().getProperty("complexTypes") != null)
 247  
         {
 248  0
             configureClientForComplexTypes(this.client, event);
 249  
         }
 250  0
         this.client.setTimeout(event.getTimeout());
 251  0
         this.client.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
 252  0
         String method = getMethod(event);
 253  
 
 254  
         // Set custom soap action if set on the event or endpoint
 255  0
         String soapAction = (String)event.getMessage().getProperty(SoapConstants.SOAP_ACTION_PROPERTY);
 256  0
         if (soapAction != null)
 257  
         {
 258  0
             soapAction = parseSoapAction(soapAction, new QName(method), event);
 259  0
             this.client.setProperty(org.codehaus.xfire.soap.SoapConstants.SOAP_ACTION, soapAction);
 260  
         }
 261  
 
 262  
         // Set Custom Headers on the client
 263  0
         Object[] arr = event.getMessage().getPropertyNames().toArray();
 264  
         String head;
 265  
 
 266  0
         for (int i = 0; i < arr.length; i++)
 267  
         {
 268  0
             head = (String) arr[i];
 269  0
             if ((head != null) && (!head.startsWith("MULE")))
 270  
             {
 271  0
                 this.client.setProperty((String) arr[i], event.getMessage().getProperty((String) arr[i]));
 272  
             }
 273  
         }
 274  
 
 275  0
         Object[] response = client.invoke(method, getArgs(event));
 276  
 
 277  0
         UMOMessage result = null;
 278  0
         if (response != null && response.length <= 1)
 279  
         {
 280  0
             if (response.length == 1)
 281  
             {
 282  0
                 result = new MuleMessage(response[0], event.getMessage());
 283  
             }
 284  
         }
 285  
         else
 286  
         {
 287  0
             result = new MuleMessage(response, event.getMessage());
 288  
         }
 289  
 
 290  0
         return result;
 291  
     }
 292  
 
 293  
     protected void doDispatch(UMOEvent event) throws Exception
 294  
     {
 295  0
         this.client.setTimeout(event.getTimeout());
 296  0
         this.client.setProperty(MuleProperties.MULE_EVENT_PROPERTY, event);
 297  0
         this.client.invoke(getMethod(event), getArgs(event));
 298  0
     }
 299  
 
 300  
     /**
 301  
      * Make a specific request to the underlying transport
 302  
      * 
 303  
      * @param timeout the maximum time the operation should block before returning.
 304  
      *            The call should return immediately if there is data available. If
 305  
      *            no data becomes available before the timeout elapses, null will be
 306  
      *            returned
 307  
      * @return the result of the request wrapped in a UMOMessage object. Null will be
 308  
      *         returned if no data was avaialable
 309  
      * @throws Exception if the call to the underlying protocal cuases an exception
 310  
      */
 311  
     protected UMOMessage doReceive(long timeout) throws Exception
 312  
     {
 313  0
         String serviceName = getServiceName(endpoint);
 314  
 
 315  0
         XFire xfire = connector.getXfire();
 316  0
         Service service = xfire.getServiceRegistry().getService(serviceName);
 317  
 
 318  0
         Client client = new Client(new MuleUniversalTransport(), service, endpoint.getEndpointURI()
 319  
             .toString());
 320  0
         client.setXFire(xfire);
 321  0
         client.setTimeout((int)timeout);
 322  0
         client.setEndpointUri(endpoint.getEndpointURI().toString());
 323  
 
 324  0
         String method = (String)endpoint.getProperty(MuleProperties.MULE_METHOD_PROPERTY);
 325  0
         OperationInfo op = service.getServiceInfo().getOperation(method);
 326  
 
 327  0
         Properties params = endpoint.getEndpointURI().getUserParams();
 328  0
         String args[] = new String[params.size()];
 329  0
         int i = 0;
 330  0
         for (Iterator iterator = params.values().iterator(); iterator.hasNext(); i++)
 331  
         {
 332  0
             args[i] = iterator.next().toString();
 333  
         }
 334  
 
 335  0
         Object[] response = client.invoke(op, args);
 336  
 
 337  0
         if (response != null && response.length == 1)
 338  
         {
 339  0
             return new MuleMessage(response[0]);
 340  
         }
 341  
         else
 342  
         {
 343  0
             return new MuleMessage(response);
 344  
         }
 345  
     }
 346  
 
 347  
     /**
 348  
      * Get the service that is mapped to the specified request.
 349  
      * @param endpoint endpoint containing a service path
 350  
      * @return service name
 351  
      */
 352  
     protected String getServiceName(UMOImmutableEndpoint endpoint)
 353  
     {
 354  0
         String pathInfo = endpoint.getEndpointURI().getPath();
 355  
 
 356  0
         if (StringUtils.isEmpty(pathInfo))
 357  
         {
 358  0
             return endpoint.getEndpointURI().getHost();
 359  
         }
 360  
 
 361  
         String serviceName;
 362  
 
 363  0
         int i = pathInfo.lastIndexOf('/');
 364  
 
 365  0
         if (i > -1)
 366  
         {
 367  0
             serviceName = pathInfo.substring(i + 1);
 368  
         }
 369  
         else
 370  
         {
 371  0
             serviceName = pathInfo;
 372  
         }
 373  
 
 374  0
         return serviceName;
 375  
     }
 376  
 
 377  
     public String parseSoapAction(String soapAction, QName method, UMOEvent event)
 378  
     {
 379  
 
 380  0
         UMOEndpointURI endpointURI = event.getEndpoint().getEndpointURI();
 381  0
         Map properties = new HashMap();
 382  0
         UMOMessage msg = event.getMessage();
 383  0
         for (Iterator iterator = msg.getPropertyNames().iterator(); iterator.hasNext();)
 384  
         {
 385  0
             String propertyKey = (String)iterator.next();
 386  0
             properties.put(propertyKey, msg.getProperty(propertyKey));
 387  
         }
 388  0
         properties.put(MuleProperties.MULE_METHOD_PROPERTY, method.getLocalPart());
 389  0
         properties.put("methodNamespace", method.getNamespaceURI());
 390  0
         properties.put("address", endpointURI.getAddress());
 391  0
         properties.put("scheme", endpointURI.getScheme());
 392  0
         properties.put("host", endpointURI.getHost());
 393  0
         properties.put("port", String.valueOf(endpointURI.getPort()));
 394  0
         properties.put("path", endpointURI.getPath());
 395  0
         properties.put("hostInfo", endpointURI.getScheme()
 396  
                                    + "://"
 397  
                                    + endpointURI.getHost()
 398  
                                    + (endpointURI.getPort() > -1
 399  
                                                    ? ":" + String.valueOf(endpointURI.getPort()) : ""));
 400  0
         if (event.getComponent() != null)
 401  
         {
 402  0
             properties.put("serviceName", event.getComponent().getDescriptor().getName());
 403  
         }
 404  
 
 405  0
         soapAction = soapActionTemplateParser.parse(properties, soapAction);
 406  
 
 407  0
         if (logger.isDebugEnabled())
 408  
         {
 409  0
             logger.debug("SoapAction for this call is: " + soapAction);
 410  
         }
 411  
 
 412  0
         return soapAction;
 413  
     }
 414  
 
 415  
     protected void configureClientForComplexTypes(Client client, UMOEvent event) throws ClassNotFoundException
 416  
     {
 417  0
         Map complexTypes = (Map) event.getEndpoint().getProperty("complexTypes");
 418  0
         Object[] beans = complexTypes.keySet().toArray();
 419  
 
 420  0
         AegisBindingProvider bp = (AegisBindingProvider) client.getService().getBindingProvider();
 421  0
         TypeMapping typeMapping = bp.getTypeMapping(client.getService());
 422  
 
 423  
         // for each complex type
 424  0
         for (int i = 0; i < beans.length; i++)
 425  
         {
 426  0
             BeanType bt = new BeanType();
 427  0
             String[] queue = ((String) complexTypes.get(beans[i])).split(":", 2);
 428  0
             bt.setSchemaType(new QName(queue[1], queue[0]));
 429  0
             bt.setTypeClass(Class.forName(beans[i].toString()));
 430  0
             typeMapping.register(bt);
 431  
         }
 432  0
     }
 433  
 }