Coverage Report - org.mule.processor.InvokerMessageProcessor
 
Classes in this File Line Coverage Branch Coverage Complexity
InvokerMessageProcessor
0%
0/108
0%
0/54
0
 
 1  
 /*
 2  
  * $Id: InvokerMessageProcessor.java 20637 2010-12-11 02:32:12Z 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  
 
 11  
 package org.mule.processor;
 12  
 
 13  
 import org.mule.DefaultMuleEvent;
 14  
 import org.mule.DefaultMuleMessage;
 15  
 import org.mule.api.MessagingException;
 16  
 import org.mule.api.MuleContext;
 17  
 import org.mule.api.MuleEvent;
 18  
 import org.mule.api.MuleException;
 19  
 import org.mule.api.MuleMessage;
 20  
 import org.mule.api.context.MuleContextAware;
 21  
 import org.mule.api.expression.ExpressionManager;
 22  
 import org.mule.api.lifecycle.Initialisable;
 23  
 import org.mule.api.lifecycle.InitialisationException;
 24  
 import org.mule.api.processor.MessageProcessor;
 25  
 import org.mule.api.registry.RegistrationException;
 26  
 import org.mule.api.transformer.DataType;
 27  
 import org.mule.api.transformer.Transformer;
 28  
 import org.mule.api.transformer.TransformerException;
 29  
 import org.mule.config.i18n.CoreMessages;
 30  
 import org.mule.transformer.TransformerTemplate;
 31  
 import org.mule.transformer.types.DataTypeFactory;
 32  
 import org.mule.transport.NullPayload;
 33  
 import org.mule.util.ClassUtils;
 34  
 import org.mule.util.TemplateParser;
 35  
 import org.mule.util.TemplateParser.PatternInfo;
 36  
 
 37  
 import java.lang.reflect.Method;
 38  
 import java.util.ArrayList;
 39  
 import java.util.Arrays;
 40  
 import java.util.Collection;
 41  
 import java.util.Collections;
 42  
 import java.util.HashMap;
 43  
 import java.util.List;
 44  
 import java.util.Map;
 45  
 import java.util.Map.Entry;
 46  
 
 47  
 import org.apache.commons.logging.Log;
 48  
 import org.apache.commons.logging.LogFactory;
 49  
 
 50  
 /**
 51  
  * <code>InvokerMessageProcessor</code> invokes a specified method of an object. An
 52  
  * array of argument expressions can be provided to map the message to the method
 53  
  * arguments. The method used is determined by the method name along with the number
 54  
  * of argument expressions provided. The results of the expression evaluations will
 55  
  * automatically be transformed where possible to the method argument type. Multiple
 56  
  * methods with the same name and same number of arguments are not supported
 57  
  * currently.
 58  
  */
 59  0
 public class InvokerMessageProcessor implements MessageProcessor, Initialisable, MuleContextAware
 60  
 {
 61  0
     protected final transient Log logger = LogFactory.getLog(getClass());
 62  
 
 63  
     protected Object object;
 64  
     protected Class<?> objectType;
 65  
     protected String methodName;
 66  
     protected List<?> arguments;
 67  
     protected Class<?>[] argumentTypes;
 68  
     protected String name;
 69  0
     protected PatternInfo patternInfo = TemplateParser.createMuleStyleParser().getStyle();
 70  
 
 71  
     protected Method method;
 72  
     protected ExpressionManager expressionManager;
 73  
     protected MuleContext muleContext;
 74  
 
 75  
     public void initialise() throws InitialisationException
 76  
     {
 77  0
         if (object == null)
 78  
         {
 79  0
             lookupObjectInstance();
 80  
         }
 81  
 
 82  0
         resolveMethodToInvoke();
 83  
 
 84  0
         expressionManager = muleContext.getExpressionManager();
 85  0
     }
 86  
 
 87  
     protected void resolveMethodToInvoke() throws InitialisationException
 88  
     {
 89  0
         if (argumentTypes != null)
 90  
         {
 91  0
             method = ClassUtils.getMethod(object.getClass(), methodName, argumentTypes);
 92  0
             if (method == null)
 93  
             {
 94  0
                 throw new InitialisationException(CoreMessages.methodWithParamsNotFoundOnObject(methodName,
 95  
                     argumentTypes, object.getClass()), this);
 96  
             }
 97  
         }
 98  
         else
 99  
         {
 100  0
             List<Method> matchingMethods = new ArrayList<Method>();
 101  0
             for (Method methodCandidate : object.getClass().getMethods())
 102  
             {
 103  0
                 if (methodCandidate.getName().equals(methodName)
 104  
                     && methodCandidate.getParameterTypes().length == arguments.size())
 105  0
                     matchingMethods.add(methodCandidate);
 106  
             }
 107  0
             if (matchingMethods.size() == 1)
 108  
             {
 109  0
                 method = matchingMethods.get(0);
 110  0
                 argumentTypes = method.getParameterTypes();
 111  
             }
 112  
             else
 113  
             {
 114  0
                 throw new InitialisationException(CoreMessages.methodWithNumParamsNotFoundOnObject(
 115  
                     methodName, arguments.size(), object), this);
 116  
             }
 117  
         }
 118  
 
 119  0
         if (logger.isDebugEnabled())
 120  
         {
 121  0
             logger.debug(String.format("Initialised %s to use method: '%s'", this, method));
 122  
         }
 123  0
     }
 124  
 
 125  
     protected void lookupObjectInstance() throws InitialisationException
 126  
     {
 127  0
         if (logger.isDebugEnabled())
 128  
         {
 129  0
             logger.debug(String.format(
 130  
                 "No object instance speciedied.  Looking up single instance of type %s in mule registry",
 131  
                 objectType));
 132  
         }
 133  
 
 134  
         try
 135  
         {
 136  0
             object = muleContext.getRegistry().lookupObject(objectType);
 137  
         }
 138  0
         catch (RegistrationException e)
 139  
         {
 140  0
             throw new InitialisationException(
 141  
                 CoreMessages.initialisationFailure(String.format(
 142  
                     "Muliple instances of '%s' were found in the registry so you need to configure a specific instance",
 143  
                     objectType)), this);
 144  0
         }
 145  0
         if (object == null)
 146  
         {
 147  0
             throw new InitialisationException(CoreMessages.initialisationFailure(String.format(
 148  
                 "No instance of '%s' was found in the registry", objectType)), this);
 149  
 
 150  
         }
 151  0
     }
 152  
 
 153  
     public MuleEvent process(MuleEvent event) throws MuleException
 154  
     {
 155  0
         MuleEvent resultEvent = event;
 156  0
         Object[] args = evaluateArguments(event, arguments);
 157  
 
 158  0
         if (logger.isDebugEnabled())
 159  
         {
 160  0
             logger.debug(String.format("Invoking  '%s' of '%s' with arguments: '%s'", method.getName(),
 161  
                 object, args));
 162  
         }
 163  
 
 164  
         try
 165  
         {
 166  0
             Object result = method.invoke(object, args);
 167  0
             if (!method.getReturnType().equals(void.class))
 168  
             {
 169  0
                 resultEvent = createResultEvent(event, result);
 170  
             }
 171  
         }
 172  0
         catch (Exception e)
 173  
         {
 174  0
             throw new MessagingException(CoreMessages.failedToInvoke(object.toString()), event, e);
 175  0
         }
 176  0
         return resultEvent;
 177  
     }
 178  
 
 179  
     protected Object[] evaluateArguments(MuleEvent event, List<?> argumentTemplates)
 180  
         throws MessagingException
 181  
     {
 182  0
         Object[] args = new Object[argumentTemplates.size()];
 183  0
         MuleMessage message = event.getMessage();
 184  
         try
 185  
         {
 186  0
             for (int i = 0; i < args.length; i++)
 187  
             {
 188  0
                 Object argumentTemplate = argumentTemplates.get(i);
 189  0
                 if (argumentTemplate != null)
 190  
                 {
 191  0
                     args[i] = transformArgument(evaluateExpressionCandidate(argumentTemplate, message),
 192  
                         argumentTypes[i]);
 193  
                 }
 194  
             }
 195  0
             return args;
 196  
         }
 197  0
         catch (TransformerException e)
 198  
         {
 199  0
             throw new MessagingException(event, e);
 200  
         }
 201  
     }
 202  
 
 203  
     @SuppressWarnings("unchecked")
 204  
     protected Object evaluateExpressionCandidate(Object expressionCandidate, MuleMessage message)
 205  
         throws TransformerException
 206  
     {
 207  0
         if (expressionCandidate instanceof Collection<?>)
 208  
         {
 209  0
             Collection<Object> collectionTemplate = (Collection<Object>) expressionCandidate;
 210  0
             Collection<Object> newCollection = new ArrayList<Object>();
 211  0
             for (Object object : collectionTemplate)
 212  
             {
 213  0
                 newCollection.add(evaluateExpressionCandidate(object, message));
 214  
             }
 215  0
             return newCollection;
 216  
         }
 217  0
         else if (expressionCandidate instanceof Map<?, ?>)
 218  
         {
 219  0
             Map<Object, Object> map = (Map<Object, Object>) expressionCandidate;
 220  0
             for (Entry<Object, Object> entry : map.entrySet())
 221  
             {
 222  0
                 map.put(entry.getKey(), evaluateExpressionCandidate(entry.getValue(), message));
 223  
             }
 224  0
             return map;
 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  
 }