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