Coverage Report - org.mule.model.resolvers.AbstractArgumentEntryPointResolver
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractArgumentEntryPointResolver
79%
42/53
75%
12/16
2.2
 
 1  
 /*
 2  
  * $Id: AbstractArgumentEntryPointResolver.java 10489 2008-01-23 17:53:38Z 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  
 package org.mule.model.resolvers;
 11  
 
 12  
 import org.mule.api.MuleEventContext;
 13  
 import org.mule.api.model.InvocationResult;
 14  
 import org.mule.util.ClassUtils;
 15  
 import org.mule.util.StringMessageUtils;
 16  
 
 17  
 import java.lang.reflect.Method;
 18  
 import java.util.Arrays;
 19  
 import java.util.HashSet;
 20  
 import java.util.Iterator;
 21  
 import java.util.List;
 22  
 import java.util.Set;
 23  
 
 24  
 /**
 25  
  * A base class that allows implementing resolvers to define what parameters it is expecting.  Currently
 26  
  * there are two implementations of this {@link org.mule.model.resolvers.NoArgumentsEntryPointResolver}, that
 27  
  * allows meothds with no arguments to be invoked and {@link org.mule.model.resolvers.ArrayEntryPointResolver} that
 28  
  * allows for methods that accept an array type to be invoked.
 29  
  * <p/>
 30  
  * Users can set explicit method names on this resolver to control which methods are allowed to be called. Also a set of
 31  
  * 'ingorred' methods are available (and the use can add others) to tell the resolver to not resolve to these methods.
 32  
  * The default ones are:
 33  
  * <ul>
 34  
  * <li>{@link #toString()}
 35  
  * <li>{@link #getClass()}
 36  
  * <li>{@link #notify}
 37  
  * <li>{@link #notifyAll}
 38  
  * <li>{@link #hashCode}
 39  
  * <li>{@link #wait}
 40  
  * <li>{@link Cloneable#clone()}
 41  
  * <li>'is*'
 42  
  * <li>'get*'.
 43  
  * </ul>
 44  
  * <p/> Note that wildcard expressions can be used.
 45  
  */
 46  
 public abstract class AbstractArgumentEntryPointResolver extends ReflectionEntryPointResolver
 47  
 {
 48  20
     private Set methods = new HashSet(2);
 49  
 
 50  20
     private boolean enableDiscovery = true;
 51  
 
 52  
     public AbstractArgumentEntryPointResolver()
 53  20
     {
 54  
         //By default No arg methods without a return type should be supported
 55  20
         setAcceptVoidMethods(true);
 56  
         // we don't want to match these methods when looking for a service method
 57  
         //If you add to this list please change the javaDoc above too.
 58  20
         setIgnoredMethods(new HashSet(Arrays.asList(new String[]{"toString",
 59  
                 "getClass", "notify", "notifyAll", "wait", "hashCode", "clone", "is*", "get*"})));
 60  20
     }
 61  
 
 62  
     public Set getMethods()
 63  
     {
 64  0
         return methods;
 65  
     }
 66  
 
 67  
     public void setMethods(Set methods)
 68  
     {
 69  0
         this.methods = methods;
 70  0
     }
 71  
 
 72  
     public void addMethod(String name)
 73  
     {
 74  6
         this.methods.add(name);
 75  6
     }
 76  
 
 77  
     public boolean removeMethod(String name)
 78  
     {
 79  0
         return this.methods.remove(name);
 80  
     }
 81  
 
 82  
 
 83  
     public boolean isEnableDiscovery()
 84  
     {
 85  14
         return enableDiscovery;
 86  
     }
 87  
 
 88  
     public void setEnableDiscovery(boolean enableDiscovery)
 89  
     {
 90  0
         this.enableDiscovery = enableDiscovery;
 91  0
     }
 92  
 
 93  
     public InvocationResult invoke(Object component, MuleEventContext context) throws Exception
 94  
     {
 95  20
         Method method = null;
 96  20
         Object[] payload = getPayloadFromMessage(context);
 97  
 
 98  20
         if (payload == null)
 99  
         {
 100  0
             return new InvocationResult(InvocationResult.STATE_INVOKE_NOT_SUPPORTED);
 101  
         }
 102  
 
 103  20
         for (Iterator iterator = methods.iterator(); iterator.hasNext();)
 104  
         {
 105  6
             String methodName = (String) iterator.next();
 106  6
             method = getMethodByName(methodName, context);
 107  
 
 108  6
             if (method == null)
 109  
             {
 110  6
                 method = ClassUtils.getMethod(component.getClass(), methodName, getMethodArgumentTypes(payload));
 111  
             }
 112  6
             if (method != null)
 113  
             {
 114  6
                 addMethodByName(method, context);
 115  6
                 break;
 116  
             }
 117  0
         }
 118  
         //If the method wasn't explicitly set, lets try and discover it
 119  20
         if (method == null)
 120  
         {
 121  14
             if (isEnableDiscovery())
 122  
             {
 123  14
                 Class[] argTypes = getMethodArgumentTypes(payload);
 124  14
                 List methods = ClassUtils.getSatisfiableMethods(component.getClass(), argTypes,
 125  
                         isAcceptVoidMethods(), false, getIgnoredMethods(), filter);
 126  
 
 127  14
                 if (methods.size() > 1)
 128  
                 {
 129  4
                     InvocationResult result = new InvocationResult(InvocationResult.STATE_INVOKED_FAILED);
 130  
                     // too many methods match the payload argument
 131  4
                     result.setErrorTooManyMatchingMethods(component, argTypes, this);
 132  4
                     return result;
 133  
                 }
 134  10
                 else if (methods.size() == 1)
 135  
                 {
 136  
                     // found exact match for payload argument
 137  6
                     method = this.addMethodByArguments(component, (Method) methods.get(0), getPayloadFromMessage(context));
 138  
                 }
 139  
                 else
 140  
                 {
 141  4
                     InvocationResult result = new InvocationResult(InvocationResult.STATE_INVOKED_FAILED);
 142  
                     // no method for payload argument either - bail out
 143  4
                     result.setErrorNoMatchingMethods(component, ClassUtils.NO_ARGS_TYPE, this);
 144  4
                     return result;
 145  
                 }
 146  6
             }
 147  
             else
 148  
             {
 149  0
                 InvocationResult result = new InvocationResult(InvocationResult.STATE_INVOKED_FAILED);
 150  
                 // no method for the explicit methods either
 151  0
                 result.setErrorNoMatchingMethodsCalled(component, StringMessageUtils.toString(methods), this);
 152  0
                 return result;
 153  
             }
 154  
         }
 155  12
         return invokeMethod(component, method, getPayloadFromMessage(context));
 156  
     }
 157  
 
 158  
     protected abstract Class[] getMethodArgumentTypes(Object[] payload);
 159  
 
 160  
     public String toString()
 161  
     {
 162  8
         final StringBuffer sb = new StringBuffer();
 163  8
         sb.append(ClassUtils.getClassName(getClass()));
 164  8
         sb.append("{methods=").append(StringMessageUtils.toString(methods));
 165  8
         sb.append("{transformFirst=").append(isTransformFirst());
 166  8
         sb.append(", acceptVoidMethods=").append(isAcceptVoidMethods());
 167  8
         sb.append('}');
 168  8
         return sb.toString();
 169  
     }
 170  
 }