Coverage Report - org.mule.transport.soap.axis.AxisServiceProxy
 
Classes in this File Line Coverage Branch Coverage Complexity
AxisServiceProxy
88%
46/52
86%
19/22
3.333
AxisServiceProxy$AxisServiceHandler
89%
16/18
67%
4/6
3.333
 
 1  
 /*
 2  
  * $Id: AxisServiceProxy.java 11373 2008-03-15 05:03:10Z 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;
 12  
 
 13  
 import org.mule.DefaultMuleMessage;
 14  
 import org.mule.RequestContext;
 15  
 import org.mule.api.ExceptionPayload;
 16  
 import org.mule.api.MuleException;
 17  
 import org.mule.api.MuleMessage;
 18  
 import org.mule.api.component.JavaComponent;
 19  
 import org.mule.api.config.MuleProperties;
 20  
 import org.mule.api.lifecycle.Callable;
 21  
 import org.mule.api.lifecycle.Disposable;
 22  
 import org.mule.api.lifecycle.Initialisable;
 23  
 import org.mule.api.service.Service;
 24  
 import org.mule.api.transport.MessageAdapter;
 25  
 import org.mule.config.ExceptionHelper;
 26  
 import org.mule.transport.AbstractMessageReceiver;
 27  
 import org.mule.transport.soap.SoapConstants;
 28  
 import org.mule.transport.soap.axis.extras.AxisCleanAndAddProperties;
 29  
 import org.mule.util.ClassUtils;
 30  
 
 31  
 import java.lang.reflect.InvocationHandler;
 32  
 import java.lang.reflect.Method;
 33  
 import java.lang.reflect.Proxy;
 34  
 import java.util.ArrayList;
 35  
 import java.util.Arrays;
 36  
 import java.util.List;
 37  
 import java.util.Map;
 38  
 
 39  
 /**
 40  
  * <code>ServiceProxy</code> is a proxy that wraps a soap endpointUri to look like
 41  
  * a Web service. Also provides helper methods for building and describing web
 42  
  * service interfaces in Mule.
 43  
  */
 44  
 
 45  0
 public class AxisServiceProxy
 46  
 {
 47  
 
 48  2
     private static ThreadLocal properties = new ThreadLocal();
 49  
 
 50  
     public static Object createProxy(AbstractMessageReceiver receiver, boolean synchronous, Class[] classes)
 51  
     {
 52  160
         final ClassLoader cl = Thread.currentThread().getContextClassLoader();
 53  160
         return Proxy.newProxyInstance(cl, classes, createServiceHandler(receiver, synchronous));
 54  
     }
 55  
 
 56  
     public static InvocationHandler createServiceHandler(AbstractMessageReceiver receiver, boolean synchronous)
 57  
     {
 58  160
         return new AxisServiceHandler(receiver, synchronous);
 59  
     }
 60  
 
 61  0
     private static class AxisServiceHandler implements InvocationHandler
 62  
     {
 63  
         private AbstractMessageReceiver receiver;
 64  160
         private boolean synchronous = true;
 65  
 
 66  
         public AxisServiceHandler(AbstractMessageReceiver receiver, boolean synchronous)
 67  160
         {
 68  160
             this.receiver = receiver;
 69  160
             this.synchronous = synchronous;
 70  160
         }
 71  
 
 72  
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
 73  
         {
 74  160
             MessageAdapter messageAdapter = receiver.getConnector().getMessageAdapter(args);
 75  160
             messageAdapter.setProperty(MuleProperties.MULE_METHOD_PROPERTY, method);
 76  
             
 77  
             // add all custom headers, filter out all mule headers (such as
 78  
             // MULE_SESSION) except
 79  
             // for MULE_USER header. Filter out other headers like "soapMethods" and
 80  
             // MuleProperties.MULE_METHOD_PROPERTY and "soapAction"
 81  
             // and also filter out any http related header
 82  160
             messageAdapter.addProperties(AxisCleanAndAddProperties.cleanAndAdd(RequestContext.getEventContext()));                        
 83  
                                    
 84  160
             MuleMessage message = receiver.routeMessage(new DefaultMuleMessage(messageAdapter), synchronous);
 85  
             
 86  160
             if (message != null)
 87  
             {
 88  160
                 ExceptionPayload wsException = message.getExceptionPayload();
 89  
 
 90  160
                 if (wsException != null)
 91  
                 {
 92  8
                     MuleException umoException = ExceptionHelper.getRootMuleException(wsException.getException());
 93  
                     // if the exception has a cause, then throw only the cause
 94  8
                     if (umoException.getCause() != null)
 95  
                     {
 96  8
                         throw umoException.getCause();
 97  
                     }
 98  
                     else
 99  
                     {
 100  0
                         throw umoException;
 101  
                     }
 102  
                 }
 103  
 
 104  152
                 return message.getPayload();
 105  
             }
 106  
             else
 107  
             {
 108  0
                 return null;
 109  
             }
 110  
         }
 111  
     }
 112  
 
 113  
     /*
 114  
        This is a horrible hack, which is axis-specific (no general classes are affected).  It was
 115  
        added to allow service interface to be configured on endpoints.  The reason it needs to be
 116  
        via a global thread local is that:
 117  
        - the routine getInterfacesForComponent is called from "callback" objects, of which at least
 118  
          one is set in the axis connector.  So the endpoint properties are unavailable when set.
 119  
        - the information passed to the callback is sufficient to identify the component, but not
 120  
          the endpoint, and we would like this configuration to be endpoint specific for two
 121  
          reasons: (i) it is more flexible and (ii) we want to avoid transport specific config
 122  
          on the component (setting it on the connector is way too constraining)
 123  
        - the only other solution (which also uses thread local globals) would be to use the
 124  
          request context, but this is called, amongst other places, from the create() method
 125  
          of the axis message receiver, so no request context is currently in scope.
 126  
        I apologise for this poor code, but after discussing it with rest of the 2.x team we
 127  
        decided that if it worked, it was probably sufficient, since axis 1 support is largely
 128  
        legacy-based.  AC.
 129  
      */
 130  
     public static void setProperties(Map properties)
 131  
     {
 132  540
         AxisServiceProxy.properties.set(properties);
 133  540
     }
 134  
 
 135  
     public static Class[] getInterfacesForComponent(Service service)
 136  
         throws MuleException, ClassNotFoundException
 137  
     {
 138  
         Class[] interfaces;
 139  674
         List ifaces = null;
 140  
 
 141  674
         Map localProperties = (Map) properties.get();
 142  674
         if (null != localProperties)
 143  
         {
 144  666
             ifaces = (List) localProperties.get(SoapConstants.SERVICE_INTERFACES);
 145  
         }
 146  674
         if (ifaces == null || ifaces.size() == 0)
 147  
         {
 148  
             final Class implementationClass;
 149  
 
 150  624
             if (service.getComponent() instanceof JavaComponent)
 151  
             {
 152  
                 try
 153  
                 {
 154  624
                     implementationClass = ((JavaComponent) service.getComponent()).getObjectType();
 155  
                 }
 156  0
                 catch (Exception e)
 157  
                 {
 158  0
                     throw new ClassNotFoundException("Unable to retrieve class from service factory", e);
 159  624
                 }
 160  
             }
 161  
             else
 162  
             {
 163  0
                 throw new ClassNotFoundException("Unable to retrieve class from service factory");
 164  
             }
 165  
             
 166  
 
 167  
             // get all implemented interfaces from superclasses as well
 168  624
             final List intfList = ClassUtils.getAllInterfaces(implementationClass);
 169  624
             interfaces = (Class[])intfList.toArray(new Class[intfList.size()]);
 170  624
         }
 171  
         else
 172  
         {
 173  50
             interfaces = new Class[ifaces.size()];
 174  150
             for (int i = 0; i < ifaces.size(); i++)
 175  
             {
 176  100
                 String iface = (String)ifaces.get(i);
 177  100
                 interfaces[i] = ClassUtils.loadClass(iface, AxisServiceProxy.class);
 178  
             }
 179  
         }
 180  
 
 181  674
         interfaces = removeInterface(interfaces, Callable.class);
 182  674
         interfaces = removeInterface(interfaces, Disposable.class);
 183  674
         interfaces = removeInterface(interfaces, Initialisable.class);
 184  674
         return interfaces;
 185  
     }
 186  
 
 187  
     public static Class[] removeInterface(Class[] interfaces, Class iface)
 188  
     {
 189  2022
         if (interfaces == null)
 190  
         {
 191  0
             return null;
 192  
         }
 193  2022
         List results = new ArrayList();
 194  10222
         for (int i = 0; i < interfaces.length; i++)
 195  
         {
 196  8200
             Class anInterface = interfaces[i];
 197  8200
             if (!anInterface.equals(iface))
 198  
             {
 199  7002
                 results.add(anInterface);
 200  
             }
 201  
         }
 202  2022
         Class[] arResults = new Class[results.size()];
 203  2022
         if (arResults.length == 0)
 204  
         {
 205  6
             return arResults;
 206  
         }
 207  
         else
 208  
         {
 209  2016
             results.toArray(arResults);
 210  2016
             return arResults;
 211  
         }
 212  
     }
 213  
 
 214  
     public static Method[] getMethods(Class[] interfaces)
 215  
     {
 216  370
         List methodNames = new ArrayList();
 217  1530
         for (int i = 0; i < interfaces.length; i++)
 218  
         {
 219  1160
             methodNames.addAll(Arrays.asList(interfaces[i].getMethods()));
 220  
         }
 221  370
         Method[] results = new Method[methodNames.size()];
 222  370
         return (Method[])methodNames.toArray(results);
 223  
 
 224  
     }
 225  
 
 226  
     public static String[] getMethodNames(Class[] interfaces)
 227  
     {
 228  370
         Method[] methods = getMethods(interfaces);
 229  
 
 230  370
         String[] results = new String[methods.length];
 231  2084
         for (int i = 0; i < results.length; i++)
 232  
         {
 233  1714
             results[i] = methods[i].getName();
 234  
         }
 235  370
         return results;
 236  
     }
 237  
 
 238  
 }