Coverage Report - org.mule.providers.soap.axis.extensions.UniversalSender
 
Classes in this File Line Coverage Branch Coverage Complexity
UniversalSender
66%
75/113
60%
29/48
11
 
 1  
 /*
 2  
  * $Id: UniversalSender.java 7963 2007-08-21 08:53:15Z 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.axis.extensions;
 12  
 
 13  
 import org.mule.MuleManager;
 14  
 import org.mule.config.MuleProperties;
 15  
 import org.mule.impl.MuleEvent;
 16  
 import org.mule.impl.MuleMessage;
 17  
 import org.mule.impl.RequestContext;
 18  
 import org.mule.impl.endpoint.MuleEndpoint;
 19  
 import org.mule.impl.endpoint.MuleEndpointURI;
 20  
 import org.mule.impl.model.ModelHelper;
 21  
 import org.mule.providers.http.HttpConstants;
 22  
 import org.mule.providers.soap.axis.AxisConnector;
 23  
 import org.mule.providers.soap.axis.extras.AxisCleanAndAddProperties;
 24  
 import org.mule.umo.UMODescriptor;
 25  
 import org.mule.umo.UMOEvent;
 26  
 import org.mule.umo.UMOException;
 27  
 import org.mule.umo.UMOMessage;
 28  
 import org.mule.umo.UMOSession;
 29  
 import org.mule.umo.endpoint.UMOEndpoint;
 30  
 import org.mule.umo.endpoint.UMOEndpointURI;
 31  
 import org.mule.umo.endpoint.UMOImmutableEndpoint;
 32  
 import org.mule.umo.routing.UMOOutboundRouter;
 33  
 import org.mule.umo.routing.UMOOutboundRouterCollection;
 34  
 
 35  
 import java.io.File;
 36  
 import java.io.FileInputStream;
 37  
 import java.io.FileOutputStream;
 38  
 import java.util.HashMap;
 39  
 import java.util.Iterator;
 40  
 import java.util.Map;
 41  
 
 42  
 import org.apache.axis.AxisFault;
 43  
 import org.apache.axis.Message;
 44  
 import org.apache.axis.MessageContext;
 45  
 import org.apache.axis.client.Call;
 46  
 import org.apache.axis.handlers.BasicHandler;
 47  
 import org.apache.commons.io.output.ByteArrayOutputStream;
 48  
 import org.apache.commons.logging.Log;
 49  
 import org.apache.commons.logging.LogFactory;
 50  
 
 51  
 /**
 52  
  * An Axis handler that will dispatch the SOAP event via a Mule endpoint
 53  
  */
 54  88
 public class UniversalSender extends BasicHandler
 55  
 {
 56  
     /**
 57  
      * Serial version
 58  
      */
 59  
     private static final long serialVersionUID = 7943380365092172940L;
 60  
 
 61  
     /**
 62  
      * logger used by this class
 63  
      */
 64  88
     protected transient Log logger = LogFactory.getLog(getClass());
 65  
 
 66  88
     protected Map endpointsCache = new HashMap();
 67  
 
 68  
     public void invoke(MessageContext msgContext) throws AxisFault
 69  
     {
 70  142
         boolean sync = true;
 71  142
         Call call = (Call)msgContext.getProperty("call_object");
 72  142
         if (call == null)
 73  
         {
 74  0
             throw new IllegalStateException(
 75  
                 "The call_object property must be set on the message context to the client Call object");
 76  
         }
 77  142
         if (Boolean.TRUE.equals(call.getProperty("axis.one.way")))
 78  
         {
 79  8
             sync = false;
 80  
         }
 81  
         // Get the event stored in call
 82  
         // If a receive call is made there will be no event
 83  
         // UMOEvent event =
 84  
         // (UMOEvent)call.getProperty(MuleProperties.MULE_EVENT_PROPERTY);
 85  
         // Get the dispatch endpoint
 86  142
         String uri = msgContext.getStrProp(MessageContext.TRANS_URL);
 87  142
         UMOImmutableEndpoint requestEndpoint = (UMOImmutableEndpoint)call
 88  
             .getProperty(MuleProperties.MULE_ENDPOINT_PROPERTY);
 89  142
         UMOImmutableEndpoint endpoint = null;
 90  
 
 91  
         // put username and password in URI if they are set on the current event
 92  142
         if (msgContext.getUsername() != null)
 93  
         {
 94  0
             String[] tempEndpoint = uri.split("//");
 95  0
             String credentialString = msgContext.getUsername() + ":"
 96  
                                       + msgContext.getPassword();
 97  0
             uri = tempEndpoint[0] + "//" + credentialString + "@" + tempEndpoint[1];
 98  
             try
 99  
             {
 100  0
                 endpoint = lookupEndpoint(uri);
 101  
             }
 102  0
             catch (UMOException e)
 103  
             {
 104  0
                 requestEndpoint.getConnector().handleException(e);
 105  0
                 return;
 106  0
             }
 107  0
         }
 108  
         else
 109  
         {
 110  
             try
 111  
             {
 112  142
                 endpoint = lookupEndpoint(uri);
 113  
             }
 114  0
             catch (UMOException e)
 115  
             {
 116  0
                 requestEndpoint.getConnector().handleException(e);
 117  0
                 return;
 118  142
             }
 119  
         }
 120  
 
 121  
         try
 122  
         {
 123  142
             if (requestEndpoint.getConnector() instanceof AxisConnector)
 124  
             {
 125  142
                 msgContext.setTypeMappingRegistry(((AxisConnector)requestEndpoint.getConnector())
 126  
                     .getAxisServer().getTypeMappingRegistry());
 127  
             }
 128  142
             Object payload = null;
 129  142
             int contentLength = 0;
 130  142
             if (msgContext.getRequestMessage().countAttachments() > 0)
 131  
             {
 132  10
                 File temp = File.createTempFile("soap", ".tmp");
 133  10
                 temp.deleteOnExit(); // TODO cleanup files earlier (IOUtils has a
 134  
                 // file tracker)
 135  10
                 FileOutputStream fos = new FileOutputStream(temp);
 136  10
                 msgContext.getRequestMessage().writeTo(fos);
 137  10
                 fos.close();
 138  10
                 contentLength = (int)temp.length();
 139  10
                 payload = new FileInputStream(temp);
 140  10
             }
 141  
             else
 142  
             {
 143  132
                 ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
 144  132
                 msgContext.getRequestMessage().writeTo(baos);
 145  132
                 baos.close();
 146  132
                 payload = baos.toByteArray();
 147  
             }
 148  
 
 149  142
             Map props = new HashMap();
 150  
             // props.putAll(event.getProperties());
 151  142
             for (Iterator iterator = msgContext.getPropertyNames(); iterator.hasNext();)
 152  
             {
 153  426
                 String name = (String)iterator.next();
 154  426
                 if (!name.equals("call_object") && !name.equals("wsdl.service"))
 155  
                 {
 156  142
                     props.put(name, msgContext.getProperty(name));
 157  
                 }
 158  426
             }
 159  
 
 160  
             // add all custom headers, filter out all mule headers (such as
 161  
             // MULE_SESSION) except
 162  
             // for MULE_USER header. Filter out other headers like "soapMethods" and
 163  
             // MuleProperties.MULE_METHOD_PROPERTY and "soapAction"
 164  
             // and also filter out any http related header
 165  142
             if ((RequestContext.getEvent() != null)
 166  
                 && (RequestContext.getEvent().getMessage() != null))
 167  
             {
 168  142
                 props = AxisCleanAndAddProperties.cleanAndAdd(RequestContext.getEventContext());
 169  
             }
 170  
             
 171  
             // with jms and vm the default SOAPAction will result in the name of the endpoint, which we may not necessarily want. This should be set manually on the endpoint
 172  142
             String scheme = requestEndpoint.getEndpointURI().getScheme(); 
 173  142
             if (!("vm".equalsIgnoreCase(scheme) || "jms".equalsIgnoreCase(scheme)))
 174  
             {
 175  76
                 if (call.useSOAPAction())
 176  
                 {
 177  76
                     uri = call.getSOAPActionURI();
 178  
                 }
 179  76
                 props.put("SOAPAction", uri);
 180  
             }
 181  142
             if (contentLength > 0)
 182  
             {
 183  10
                 props.put(HttpConstants.HEADER_CONTENT_LENGTH, Integer.toString(contentLength)); // necessary
 184  
                 // for
 185  
                 // supporting
 186  
                 // httpclient
 187  
             }
 188  
 
 189  142
             if (props.get(HttpConstants.HEADER_CONTENT_TYPE) == null)
 190  
             {
 191  142
                 props.put(HttpConstants.HEADER_CONTENT_TYPE, "text/xml");
 192  
             }
 193  142
             UMOMessage message = new MuleMessage(payload, props);
 194  142
             UMOSession session = RequestContext.getEventContext().getSession();
 195  
 
 196  142
             UMOEvent dispatchEvent = new MuleEvent(message, endpoint, session, sync);
 197  142
             logger.info("Making Axis soap request on: " + uri);
 198  142
             if (logger.isDebugEnabled())
 199  
             {
 200  0
                 logger.debug("Soap request is:\n" + payload.toString());
 201  
             }
 202  142
             if (sync)
 203  
             {
 204  
                 // We need to rewrite the endpoint on the event to set the
 205  
                 // reomoteSync property
 206  134
                 MuleEndpoint syncEndpoint = new MuleEndpoint(dispatchEvent.getEndpoint());
 207  134
                 syncEndpoint.setRemoteSync(true);
 208  134
                 dispatchEvent = new MuleEvent(dispatchEvent.getMessage(), syncEndpoint,
 209  
                     dispatchEvent.getSession(), dispatchEvent.isSynchronous());
 210  
                 
 211  
                 //set username and password
 212  
                 
 213  
                 
 214  134
                 UMOMessage result = session.sendEvent(dispatchEvent);
 215  132
                 if (result != null)
 216  
                 {
 217  132
                     byte[] response = result.getPayloadAsBytes();
 218  132
                     Message responseMessage = new Message(response);
 219  132
                     msgContext.setResponseMessage(responseMessage);
 220  
 
 221  132
                 }
 222  
                 else
 223  
                 {
 224  0
                     logger
 225  
                         .warn("No response message was returned from synchronous call to: " + uri);
 226  
                 }
 227  
                 // remove temp file created for streaming
 228  132
                 if (payload instanceof File)
 229  
                 {
 230  0
                     ((File)payload).delete();
 231  
                 }
 232  132
             }
 233  
             else
 234  
             {
 235  8
                 session.dispatchEvent(dispatchEvent);
 236  
             }
 237  
         }
 238  0
         catch (AxisFault axisFault)
 239  
         {
 240  0
             throw axisFault;
 241  
         }
 242  2
         catch (Exception e)
 243  
         {
 244  2
             throw new AxisFault(e.getMessage(), new Throwable(e));
 245  140
         }
 246  
 
 247  140
     }
 248  
 
 249  
     protected UMOEndpoint lookupEndpoint(String uri) throws UMOException
 250  
     {
 251  142
         UMODescriptor axis = MuleManager.getInstance().lookupModel(ModelHelper.SYSTEM_MODEL)
 252  
             .getDescriptor(AxisConnector.AXIS_SERVICE_COMPONENT_NAME);
 253  142
         UMOEndpointURI endpoint = new MuleEndpointURI(uri);
 254  
         UMOEndpoint ep;
 255  142
         if (axis != null)
 256  
         {
 257  0
             synchronized (endpointsCache)
 258  
             {
 259  0
                 ep = (UMOEndpoint)endpointsCache.get(endpoint.getAddress());
 260  0
                 if (ep == null)
 261  
                 {
 262  0
                     updateEndpointCache(axis.getOutboundRouter());
 263  0
                     ep = (UMOEndpoint)endpointsCache.get(endpoint.getAddress());
 264  0
                     if (ep == null)
 265  
                     {
 266  0
                         logger.debug("Dispatch Endpoint uri: " + uri
 267  
                                      + " not found on the cache. Creating the endpoint instead.");
 268  0
                         ep = new MuleEndpoint(uri, false);
 269  
                     }
 270  
                     else
 271  
                     {
 272  0
                         logger.info("Found endpoint: " + uri + " on the Axis service component");
 273  
                     }
 274  
                 }
 275  
                 else
 276  
                 {
 277  0
                     logger.info("Found endpoint: " + uri + " on the Axis service component");
 278  
                 }
 279  0
             }
 280  
         }
 281  
         else
 282  
         {
 283  142
             ep = new MuleEndpoint(uri, false);
 284  
         }
 285  142
         return ep;
 286  
     }
 287  
 
 288  
     private void updateEndpointCache(UMOOutboundRouterCollection router)
 289  
     {
 290  0
         endpointsCache.clear();
 291  0
         for (Iterator iterator = router.getRouters().iterator(); iterator.hasNext();)
 292  
         {
 293  0
             UMOOutboundRouter r = (UMOOutboundRouter)iterator.next();
 294  0
             for (Iterator iterator1 = r.getEndpoints().iterator(); iterator1.hasNext();)
 295  
             {
 296  0
                 UMOEndpoint endpoint = (UMOEndpoint)iterator1.next();
 297  0
                 endpointsCache.put(endpoint.getEndpointURI().getAddress(), endpoint);
 298  0
             }
 299  0
         }
 300  0
     }
 301  
 }