Coverage Report - org.mule.processor.InvokerMessageProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
InvokerMessageProcessor
0%
0/112
0%
0/58
0
 
 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.processor;
 8  
 
 9  
 import org.mule.DefaultMuleEvent;
 10  
 import org.mule.DefaultMuleMessage;
 11  
 import org.mule.api.MessagingException;
 12  
 import org.mule.api.MuleContext;
 13  
 import org.mule.api.MuleEvent;
 14  
 import org.mule.api.MuleException;
 15  
 import org.mule.api.MuleMessage;
 16  
 import org.mule.api.context.MuleContextAware;
 17  
 import org.mule.api.expression.ExpressionManager;
 18  
 import org.mule.api.lifecycle.Initialisable;
 19  
 import org.mule.api.lifecycle.InitialisationException;
 20  
 import org.mule.api.processor.MessageProcessor;
 21  
 import org.mule.api.registry.RegistrationException;
 22  
 import org.mule.api.transformer.DataType;
 23  
 import org.mule.api.transformer.Transformer;
 24  
 import org.mule.api.transformer.TransformerException;
 25  
 import org.mule.config.i18n.CoreMessages;
 26  
 import org.mule.transformer.TransformerTemplate;
 27  
 import org.mule.transformer.types.DataTypeFactory;
 28  
 import org.mule.transport.NullPayload;
 29  
 import org.mule.util.ClassUtils;
 30  
 import org.mule.util.TemplateParser;
 31  
 import org.mule.util.TemplateParser.PatternInfo;
 32  
 
 33  
 import java.lang.reflect.Method;
 34  
 import java.util.ArrayList;
 35  
 import java.util.Arrays;
 36  
 import java.util.Collection;
 37  
 import java.util.Collections;
 38  
 import java.util.HashMap;
 39  
 import java.util.List;
 40  
 import java.util.Map;
 41  
 import java.util.Map.Entry;
 42  
 
 43  
 import org.apache.commons.logging.Log;
 44  
 import org.apache.commons.logging.LogFactory;
 45  
 
 46  
 /**
 47  
  * <code>InvokerMessageProcessor</code> invokes a specified method of an object. An
 48  
  * array of argument expressions can be provided to map the message to the method
 49  
  * arguments. The method used is determined by the method name along with the number
 50  
  * of argument expressions provided. The results of the expression evaluations will
 51  
  * automatically be transformed where possible to the method argument type. Multiple
 52  
  * methods with the same name and same number of arguments are not supported
 53  
  * currently.
 54  
  */
 55  0
 public class InvokerMessageProcessor implements MessageProcessor, Initialisable, MuleContextAware
 56  
 {
 57  0
     protected final transient Log logger = LogFactory.getLog(getClass());
 58  
 
 59  
     protected Object object;
 60  
     protected Class<?> objectType;
 61  
     protected String methodName;
 62  0
     protected List<?> arguments = new ArrayList<Object>();;
 63  
     protected Class<?>[] argumentTypes;
 64  
     protected String name;
 65  0
     protected PatternInfo patternInfo = TemplateParser.createMuleStyleParser().getStyle();
 66  
 
 67  
     protected Method method;
 68  
     protected ExpressionManager expressionManager;
 69  
     protected MuleContext muleContext;
 70  
 
 71  
     public void initialise() throws InitialisationException
 72  
     {
 73  0
         if (object == null)
 74  
         {
 75  0
             lookupObjectInstance();
 76  
         }
 77  
 
 78  0
         resolveMethodToInvoke();
 79  
 
 80  0
         expressionManager = muleContext.getExpressionManager();
 81  0
     }
 82  
 
 83  
     protected void resolveMethodToInvoke() throws InitialisationException
 84  
     {
 85  0
         if (argumentTypes != null)
 86  
         {
 87  0
             method = ClassUtils.getMethod(object.getClass(), methodName, argumentTypes);
 88  0
             if (method == null)
 89  
             {
 90  0
                 throw new InitialisationException(CoreMessages.methodWithParamsNotFoundOnObject(methodName,
 91  
                     argumentTypes, object.getClass()), this);
 92  
             }
 93  
         }
 94  
         else
 95  
         {
 96  0
             List<Method> matchingMethods = new ArrayList<Method>();
 97  0
             int argSize = arguments != null ? arguments.size() : 0;
 98  0
             for (Method methodCandidate : object.getClass().getMethods())
 99  
             {
 100  0
                 if (methodCandidate.getName().equals(methodName)
 101  
                     && methodCandidate.getParameterTypes().length == argSize)
 102  0
                     matchingMethods.add(methodCandidate);
 103  
             }
 104  0
             if (matchingMethods.size() == 1)
 105  
             {
 106  0
                 method = matchingMethods.get(0);
 107  0
                 argumentTypes = method.getParameterTypes();
 108  
             }
 109  
             else
 110  
             {
 111  0
                 throw new InitialisationException(CoreMessages.methodWithNumParamsNotFoundOnObject(
 112  
                     methodName, arguments.size(), object), this);
 113  
             }
 114  
         }
 115  
 
 116  0
         if (logger.isDebugEnabled())
 117  
         {
 118  0
             logger.debug(String.format("Initialised %s to use method: '%s'", this, method));
 119  
         }
 120  0
     }
 121  
 
 122  
     protected void lookupObjectInstance() throws InitialisationException
 123  
     {
 124  0
         if (logger.isDebugEnabled())
 125  
         {
 126  0
             logger.debug(String.format(
 127  
                 "No object instance speciedied.  Looking up single instance of type %s in mule registry",
 128  
                 objectType));
 129  
         }
 130  
 
 131  
         try
 132  
         {
 133  0
             object = muleContext.getRegistry().lookupObject(objectType);
 134  
         }
 135  0
         catch (RegistrationException e)
 136  
         {
 137  0
             throw new InitialisationException(
 138  
                 CoreMessages.initialisationFailure(String.format(
 139  
                     "Muliple instances of '%s' were found in the registry so you need to configure a specific instance",
 140  
                     objectType)), this);
 141  0
         }
 142  0
         if (object == null)
 143  
         {
 144  0
             throw new InitialisationException(CoreMessages.initialisationFailure(String.format(
 145  
                 "No instance of '%s' was found in the registry", objectType)), this);
 146  
 
 147  
         }
 148  0
     }
 149  
 
 150  
     public MuleEvent process(MuleEvent event) throws MuleException
 151  
     {
 152  0
         MuleEvent resultEvent = event;
 153  0
         Object[] args = evaluateArguments(event, arguments);
 154  
 
 155  0
         if (logger.isDebugEnabled())
 156  
         {
 157  0
             logger.debug(String.format("Invoking  '%s' of '%s' with arguments: '%s'", method.getName(),
 158  
                 object, args));
 159  
         }
 160  
 
 161  
         try
 162  
         {
 163  0
             Object result = method.invoke(object, args);
 164  0
             if (!method.getReturnType().equals(void.class))
 165  
             {
 166  0
                 resultEvent = createResultEvent(event, result);
 167  
             }
 168  
         }
 169  0
         catch (Exception e)
 170  
         {
 171  0
             throw new MessagingException(CoreMessages.failedToInvoke(object.toString()), event, e);
 172  0
         }
 173  0
         return resultEvent;
 174  
     }
 175  
 
 176  
     protected Object[] evaluateArguments(MuleEvent event, List<?> argumentTemplates)
 177  
         throws MessagingException
 178  
     {
 179  0
         int argSize = argumentTemplates != null ? argumentTemplates.size() : 0;
 180  0
         Object[] args = new Object[argSize];
 181  0
         MuleMessage message = event.getMessage();
 182  
         try
 183  
         {
 184  0
             for (int i = 0; i < args.length; i++)
 185  
             {
 186  0
                 Object argumentTemplate = argumentTemplates.get(i);
 187  0
                 if (argumentTemplate != null)
 188  
                 {
 189  0
                     args[i] = transformArgument(evaluateExpressionCandidate(argumentTemplate, message),
 190  
                         argumentTypes[i]);
 191  
                 }
 192  
             }
 193  0
             return args;
 194  
         }
 195  0
         catch (TransformerException e)
 196  
         {
 197  0
             throw new MessagingException(event, e);
 198  
         }
 199  
     }
 200  
 
 201  
     @SuppressWarnings("unchecked")
 202  
     protected Object evaluateExpressionCandidate(Object expressionCandidate, MuleMessage message)
 203  
         throws TransformerException
 204  
     {
 205  0
         if (expressionCandidate instanceof Collection<?>)
 206  
         {
 207  0
             Collection<Object> collectionTemplate = (Collection<Object>) expressionCandidate;
 208  0
             Collection<Object> newCollection = new ArrayList<Object>();
 209  0
             for (Object object : collectionTemplate)
 210  
             {
 211  0
                 newCollection.add(evaluateExpressionCandidate(object, message));
 212  
             }
 213  0
             return newCollection;
 214  
         }
 215  0
         else if (expressionCandidate instanceof Map<?, ?>)
 216  
         {
 217  0
             Map<Object, Object> mapTemplate = (Map<Object, Object>) expressionCandidate;
 218  0
             Map<Object, Object> newMap = new HashMap<Object, Object>();
 219  0
             for (Entry<Object, Object> entry : mapTemplate.entrySet())
 220  
             {
 221  0
                 newMap.put(evaluateExpressionCandidate(entry.getKey(), message), evaluateExpressionCandidate(
 222  
                     entry.getValue(), message));
 223  
             }
 224  0
             return newMap;
 225  
         }
 226  0
         else if (expressionCandidate instanceof String[])
 227  
         {
 228  0
             String[] stringArrayTemplate = (String[]) expressionCandidate;
 229  0
             Object[] newArray = new String[stringArrayTemplate.length];
 230  0
             for (int j = 0; j < stringArrayTemplate.length; j++)
 231  
             {
 232  0
                 newArray[j] = evaluateExpressionCandidate(stringArrayTemplate[j], message);
 233  
             }
 234  0
             return newArray;
 235  
         }
 236  0
         if (expressionCandidate instanceof String)
 237  
         {
 238  
             Object arg;
 239  0
             String expression = (String) expressionCandidate;
 240  
             // If string contains is a single expression then evaluate otherwise
 241  
             // parse. We can't use parse() always because that will convert
 242  
             // everything to a string
 243  0
             if (expression.startsWith(patternInfo.getPrefix())
 244  
                 && expression.endsWith(patternInfo.getSuffix()))
 245  
             {
 246  0
                 arg = expressionManager.evaluate(expression, message);
 247  
             }
 248  
             else
 249  
             {
 250  0
                 arg = expressionManager.parse(expression, message);
 251  
             }
 252  
 
 253  
             // If expression evaluates to a MuleMessage then use it's payload
 254  0
             if (arg instanceof MuleMessage)
 255  
             {
 256  0
                 arg = ((MuleMessage) arg).getPayload();
 257  
             }
 258  0
             return arg;
 259  
         }
 260  
         else
 261  
         {
 262  
             // Not an expression so use object itself
 263  0
             return expressionCandidate;
 264  
         }
 265  
     }
 266  
 
 267  
     private Object transformArgument(Object arg, Class<?> type) throws TransformerException
 268  
     {
 269  0
         if (!(type.isAssignableFrom(arg.getClass())))
 270  
         {
 271  0
             DataType<?> source = DataTypeFactory.create(arg.getClass());
 272  0
             DataType<?> target = DataTypeFactory.create(type);
 273  
             // Throws TransformerException if no suitable transformer is found
 274  0
             Transformer t = muleContext.getRegistry().lookupTransformer(source, target);
 275  0
             arg = t.transform(arg);
 276  
         }
 277  0
         return arg;
 278  
     }
 279  
 
 280  
     public void setObject(Object object)
 281  
     {
 282  0
         this.object = object;
 283  0
     }
 284  
 
 285  
     public void setMethodName(String methodName)
 286  
     {
 287  0
         this.methodName = methodName;
 288  0
     }
 289  
 
 290  
     public void setArgumentExpressionsString(String arguments)
 291  
     {
 292  0
         this.arguments = Arrays.asList(arguments.split("\\s*,\\s*"));
 293  0
     }
 294  
 
 295  
     public void setArguments(List<?> arguments)
 296  
     {
 297  0
         this.arguments = arguments;
 298  0
     }
 299  
 
 300  
     protected MuleEvent createResultEvent(MuleEvent event, Object result) throws MuleException
 301  
     {
 302  0
         if (result instanceof MuleMessage)
 303  
         {
 304  0
             return new DefaultMuleEvent((MuleMessage) result, event);
 305  
         }
 306  0
         else if (result != null)
 307  
         {
 308  0
             event.getMessage().applyTransformers(
 309  
                 event,
 310  
                 Collections.<Transformer> singletonList(new TransformerTemplate(
 311  
                     new TransformerTemplate.OverwitePayloadCallback(result))));
 312  0
             return event;
 313  
         }
 314  
         else
 315  
         {
 316  0
             return new DefaultMuleEvent(new DefaultMuleMessage(NullPayload.getInstance(),
 317  
                 event.getMuleContext()), event);
 318  
         }
 319  
     }
 320  
 
 321  
     public String getName()
 322  
     {
 323  0
         return name;
 324  
     }
 325  
 
 326  
     public void setName(String name)
 327  
     {
 328  0
         this.name = name;
 329  0
     }
 330  
 
 331  
     public void setArgumentTypes(Class<?>[] argumentTypes)
 332  
     {
 333  0
         this.argumentTypes = argumentTypes;
 334  0
     }
 335  
 
 336  
     @Override
 337  
     public String toString()
 338  
     {
 339  0
         return String.format(
 340  
             "InvokerMessageProcessor [name=%s, object=%s, methodName=%s, argExpressions=%s, argTypes=%s]",
 341  
             name, object, methodName, arguments, argumentTypes);
 342  
     }
 343  
 
 344  
     public void setMuleContext(MuleContext context)
 345  
     {
 346  0
         this.muleContext = context;
 347  0
     }
 348  
 
 349  
     public void setObjectType(Class<?> objectType)
 350  
     {
 351  0
         this.objectType = objectType;
 352  0
     }
 353  
 
 354  
 }