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