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