Coverage Report - org.mule.module.cxf.MuleInvoker
 
Classes in this File Line Coverage Branch Coverage Complexity
MuleInvoker
0%
0/72
0%
0/42
0
 
 1  
 /*
 2  
  * $Id: MuleInvoker.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.module.cxf;
 12  
 
 13  
 import org.mule.api.MuleEvent;
 14  
 import org.mule.api.MuleException;
 15  
 import org.mule.api.MuleMessage;
 16  
 import org.mule.api.config.MuleProperties;
 17  
 import org.mule.api.transport.PropertyScope;
 18  
 import org.mule.component.ComponentException;
 19  
 import org.mule.transport.NullPayload;
 20  
 
 21  
 import java.lang.reflect.Method;
 22  
 import java.lang.reflect.Proxy;
 23  
 import java.util.List;
 24  
 
 25  
 import org.apache.cxf.frontend.MethodDispatcher;
 26  
 import org.apache.cxf.helpers.CastUtils;
 27  
 import org.apache.cxf.interceptor.Fault;
 28  
 import org.apache.cxf.message.Exchange;
 29  
 import org.apache.cxf.message.FaultMode;
 30  
 import org.apache.cxf.message.Message;
 31  
 import org.apache.cxf.message.MessageContentsList;
 32  
 import org.apache.cxf.service.Service;
 33  
 import org.apache.cxf.service.invoker.Invoker;
 34  
 import org.apache.cxf.service.model.BindingOperationInfo;
 35  
 
 36  
 /**
 37  
  * Invokes a Mule Service via a CXF binding.
 38  
  */
 39  
 public class MuleInvoker implements Invoker
 40  
 {
 41  
     private final CxfInboundMessageProcessor cxfMmessageProcessor;
 42  
     private Class<?> targetClass;
 43  
     
 44  
     public MuleInvoker(CxfInboundMessageProcessor cxfMmessageProcessor, Class<?> targetClass)
 45  0
     {
 46  0
         this.cxfMmessageProcessor = cxfMmessageProcessor;
 47  0
         this.targetClass = targetClass;
 48  0
     }
 49  
 
 50  
     public Object invoke(Exchange exchange, Object o)
 51  
     {
 52  
         // this is the original request. Keep it to copy all the message properties from it
 53  0
         MuleEvent event = (MuleEvent) exchange.getInMessage().get(CxfConstants.MULE_EVENT);
 54  0
         MuleEvent responseEvent = null;
 55  
         try
 56  
         {
 57  0
             MuleMessage reqMsg = event.getMessage();
 58  0
             reqMsg.setPayload(extractPayload(exchange.getInMessage()));
 59  
             
 60  0
             BindingOperationInfo bop = exchange.get(BindingOperationInfo.class);
 61  0
             Service svc = exchange.get(Service.class);
 62  0
             if (!cxfMmessageProcessor.isProxy())
 63  
             {
 64  0
                 MethodDispatcher md = (MethodDispatcher) svc.get(MethodDispatcher.class.getName());
 65  0
                 Method m = md.getMethod(bop);
 66  0
                 if (targetClass != null)
 67  
                 {
 68  0
                     m = matchMethod(m, targetClass);
 69  
                 }
 70  
             
 71  0
                 reqMsg.setProperty(MuleProperties.MULE_METHOD_PROPERTY, m, PropertyScope.INVOCATION);
 72  
             }
 73  
 
 74  0
             if (bop != null)
 75  
             {
 76  0
                 reqMsg.setProperty(CxfConstants.INBOUND_OPERATION, bop.getOperationInfo().getName(), PropertyScope.INVOCATION);
 77  0
                 reqMsg.setProperty(CxfConstants.INBOUND_SERVICE, svc.getName(), PropertyScope.INVOCATION);
 78  
             }
 79  
             
 80  0
             responseEvent = cxfMmessageProcessor.processNext(event);
 81  
         }
 82  0
         catch (MuleException e)
 83  
         {
 84  0
             exchange.put(CxfConstants.MULE_EVENT, event);
 85  0
             throw new Fault(e);
 86  
         }
 87  0
         catch (RuntimeException e)
 88  
         {
 89  0
             exchange.put(CxfConstants.MULE_EVENT, event);
 90  0
             throw new Fault(e);
 91  0
         }
 92  
 
 93  0
         if (!event.getEndpoint().getExchangePattern().hasResponse())
 94  
         {
 95  
             // weird response from AbstractInterceptingMessageProcessor
 96  0
             responseEvent = null;
 97  
         }
 98  
         
 99  0
         if (responseEvent != null)
 100  
         {
 101  0
             exchange.put(CxfConstants.MULE_EVENT, responseEvent);
 102  0
             MuleMessage resMessage = responseEvent.getMessage();
 103  
             
 104  0
             if (resMessage.getExceptionPayload() != null)
 105  
             {
 106  0
                 Throwable cause = resMessage.getExceptionPayload().getException();
 107  0
                 if (cause instanceof ComponentException)
 108  
                 {
 109  0
                     cause = cause.getCause();
 110  
                 }
 111  
 
 112  0
                 exchange.getInMessage().put(FaultMode.class, FaultMode.UNCHECKED_APPLICATION_FAULT);
 113  0
                 if (cause instanceof Fault)
 114  
                 {
 115  0
                     throw (Fault) cause;
 116  
                 }
 117  
 
 118  0
                 throw new Fault(cause);
 119  
             }
 120  0
             else if (resMessage.getPayload() instanceof NullPayload)
 121  
             {
 122  0
                 return new MessageContentsList((Object)null);
 123  
             }
 124  0
             else if (cxfMmessageProcessor.isProxy())
 125  
             {
 126  0
                 resMessage.getPayload();
 127  0
                 return new Object[] { resMessage };
 128  
             }
 129  
             else
 130  
             {
 131  0
                 return new Object[]{resMessage.getPayload()};
 132  
             }
 133  
         }
 134  
         else
 135  
         {
 136  0
             exchange.getInMessage().getInterceptorChain().abort();
 137  0
             if (exchange.getOutMessage() != null)
 138  
             {
 139  0
                 exchange.getOutMessage().getInterceptorChain().abort();
 140  
             }
 141  0
             exchange.put(CxfConstants.MULE_EVENT, null);
 142  0
             return null;
 143  
         }
 144  
     }
 145  
     
 146  
     protected Object extractPayload(Message cxfMessage)
 147  
     {   
 148  0
         List<Object> list = CastUtils.cast(cxfMessage.getContent(List.class));
 149  0
         if (list == null)
 150  
         {
 151  
             // Seems Providers get objects stored this way
 152  0
             Object object = cxfMessage.getContent(Object.class);
 153  0
             if (object != null)
 154  
             {
 155  0
                 return object;
 156  
             }
 157  
             else
 158  
             {
 159  0
                 return new Object[0];
 160  
             }
 161  
         }
 162  
         
 163  0
         if ((list.size() == 1) && (list.get(0) != null))
 164  
         {
 165  0
             return list.get(0);
 166  
         }
 167  
         else
 168  
         {
 169  0
             return list.toArray();
 170  
         }
 171  
     }
 172  
 
 173  
     /**
 174  
      * Returns a Method that has the same declaring class as the class of
 175  
      * targetObject to avoid the IllegalArgumentException when invoking the
 176  
      * method on the target object. The methodToMatch will be returned if the
 177  
      * targetObject doesn't have a similar method.
 178  
      * 
 179  
      * @param methodToMatch The method to be used when finding a matching method
 180  
      *            in targetObject
 181  
      * @param targetClass The class to search in for the method.
 182  
      * @return The methodToMatch if no such method exist in the class of
 183  
      *         targetObject; otherwise, a method from the class of targetObject
 184  
      *         matching the matchToMethod method.
 185  
      */
 186  
     private static Method matchMethod(Method methodToMatch, Class<?> targetClass) 
 187  
     {
 188  0
         Class<?>[] interfaces = targetClass.getInterfaces();
 189  0
         for (int i = 0; i < interfaces.length; i++) 
 190  
         {
 191  0
             Method m = getMostSpecificMethod(methodToMatch, interfaces[i]);
 192  0
             if (!methodToMatch.equals(m)) 
 193  
             {
 194  0
                 return m;
 195  
             }
 196  
         }
 197  0
         return methodToMatch;
 198  
     }
 199  
 
 200  
     /**
 201  
      * Return whether the given object is a J2SE dynamic proxy.
 202  
      * 
 203  
      * @param object the object to check
 204  
      * @see java.lang.reflect.Proxy#isProxyClass
 205  
      */
 206  
     public static boolean isJdkDynamicProxy(Object object) 
 207  
     {
 208  0
         return object != null && Proxy.isProxyClass(object.getClass());
 209  
     }
 210  
 
 211  
     /**
 212  
      * Given a method, which may come from an interface, and a targetClass used
 213  
      * in the current AOP invocation, find the most specific method if there is
 214  
      * one. E.g. the method may be IFoo.bar() and the target class may be
 215  
      * DefaultFoo. In this case, the method may be DefaultFoo.bar(). This
 216  
      * enables attributes on that method to be found.
 217  
      * 
 218  
      * @param method method to be invoked, which may come from an interface
 219  
      * @param targetClass target class for the curren invocation. May be
 220  
      *            <code>null</code> or may not even implement the method.
 221  
      * @return the more specific method, or the original method if the
 222  
      *         targetClass doesn't specialize it or implement it or is null
 223  
      */
 224  
     public static Method getMostSpecificMethod(Method method, Class<?> targetClass) {
 225  0
         if (method != null && targetClass != null) {
 226  
             try {
 227  0
                 method = targetClass.getMethod(method.getName(), method.getParameterTypes());
 228  0
             } catch (NoSuchMethodException ex) {
 229  
                 // Perhaps the target class doesn't implement this method:
 230  
                 // that's fine, just use the original method
 231  0
             }
 232  
         }
 233  0
         return method;
 234  
     }
 235  
 }