1
2
3
4
5
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
48
49
50
51
52
53
54
55 public class InvokerMessageProcessor implements MessageProcessor, Initialisable, MuleContextAware
56 {
57 protected final transient Log logger = LogFactory.getLog(getClass());
58
59 protected Object object;
60 protected Class<?> objectType;
61 protected String methodName;
62 protected List<?> arguments = new ArrayList<Object>();;
63 protected Class<?>[] argumentTypes;
64 protected String name;
65 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 if (object == null)
74 {
75 lookupObjectInstance();
76 }
77
78 resolveMethodToInvoke();
79
80 expressionManager = muleContext.getExpressionManager();
81 }
82
83 protected void resolveMethodToInvoke() throws InitialisationException
84 {
85 if (argumentTypes != null)
86 {
87 method = ClassUtils.getMethod(object.getClass(), methodName, argumentTypes);
88 if (method == null)
89 {
90 throw new InitialisationException(CoreMessages.methodWithParamsNotFoundOnObject(methodName,
91 argumentTypes, object.getClass()), this);
92 }
93 }
94 else
95 {
96 List<Method> matchingMethods = new ArrayList<Method>();
97 int argSize = arguments != null ? arguments.size() : 0;
98 for (Method methodCandidate : object.getClass().getMethods())
99 {
100 if (methodCandidate.getName().equals(methodName)
101 && methodCandidate.getParameterTypes().length == argSize)
102 matchingMethods.add(methodCandidate);
103 }
104 if (matchingMethods.size() == 1)
105 {
106 method = matchingMethods.get(0);
107 argumentTypes = method.getParameterTypes();
108 }
109 else
110 {
111 throw new InitialisationException(CoreMessages.methodWithNumParamsNotFoundOnObject(
112 methodName, arguments.size(), object), this);
113 }
114 }
115
116 if (logger.isDebugEnabled())
117 {
118 logger.debug(String.format("Initialised %s to use method: '%s'", this, method));
119 }
120 }
121
122 protected void lookupObjectInstance() throws InitialisationException
123 {
124 if (logger.isDebugEnabled())
125 {
126 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 object = muleContext.getRegistry().lookupObject(objectType);
134 }
135 catch (RegistrationException e)
136 {
137 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 }
142 if (object == null)
143 {
144 throw new InitialisationException(CoreMessages.initialisationFailure(String.format(
145 "No instance of '%s' was found in the registry", objectType)), this);
146
147 }
148 }
149
150 public MuleEvent process(MuleEvent event) throws MuleException
151 {
152 MuleEvent resultEvent = event;
153 Object[] args = evaluateArguments(event, arguments);
154
155 if (logger.isDebugEnabled())
156 {
157 logger.debug(String.format("Invoking '%s' of '%s' with arguments: '%s'", method.getName(),
158 object, args));
159 }
160
161 try
162 {
163 Object result = method.invoke(object, args);
164 if (!method.getReturnType().equals(void.class))
165 {
166 resultEvent = createResultEvent(event, result);
167 }
168 }
169 catch (Exception e)
170 {
171 throw new MessagingException(CoreMessages.failedToInvoke(object.toString()), event, e);
172 }
173 return resultEvent;
174 }
175
176 protected Object[] evaluateArguments(MuleEvent event, List<?> argumentTemplates)
177 throws MessagingException
178 {
179 int argSize = argumentTemplates != null ? argumentTemplates.size() : 0;
180 Object[] args = new Object[argSize];
181 MuleMessage message = event.getMessage();
182 try
183 {
184 for (int i = 0; i < args.length; i++)
185 {
186 Object argumentTemplate = argumentTemplates.get(i);
187 if (argumentTemplate != null)
188 {
189 args[i] = transformArgument(evaluateExpressionCandidate(argumentTemplate, message),
190 argumentTypes[i]);
191 }
192 }
193 return args;
194 }
195 catch (TransformerException e)
196 {
197 throw new MessagingException(event, e);
198 }
199 }
200
201 @SuppressWarnings("unchecked")
202 protected Object evaluateExpressionCandidate(Object expressionCandidate, MuleMessage message)
203 throws TransformerException
204 {
205 if (expressionCandidate instanceof Collection<?>)
206 {
207 Collection<Object> collectionTemplate = (Collection<Object>) expressionCandidate;
208 Collection<Object> newCollection = new ArrayList<Object>();
209 for (Object object : collectionTemplate)
210 {
211 newCollection.add(evaluateExpressionCandidate(object, message));
212 }
213 return newCollection;
214 }
215 else if (expressionCandidate instanceof Map<?, ?>)
216 {
217 Map<Object, Object> mapTemplate = (Map<Object, Object>) expressionCandidate;
218 Map<Object, Object> newMap = new HashMap<Object, Object>();
219 for (Entry<Object, Object> entry : mapTemplate.entrySet())
220 {
221 newMap.put(evaluateExpressionCandidate(entry.getKey(), message), evaluateExpressionCandidate(
222 entry.getValue(), message));
223 }
224 return newMap;
225 }
226 else if (expressionCandidate instanceof String[])
227 {
228 String[] stringArrayTemplate = (String[]) expressionCandidate;
229 Object[] newArray = new String[stringArrayTemplate.length];
230 for (int j = 0; j < stringArrayTemplate.length; j++)
231 {
232 newArray[j] = evaluateExpressionCandidate(stringArrayTemplate[j], message);
233 }
234 return newArray;
235 }
236 if (expressionCandidate instanceof String)
237 {
238 Object arg;
239 String expression = (String) expressionCandidate;
240
241
242
243 if (expression.startsWith(patternInfo.getPrefix())
244 && expression.endsWith(patternInfo.getSuffix()))
245 {
246 arg = expressionManager.evaluate(expression, message);
247 }
248 else
249 {
250 arg = expressionManager.parse(expression, message);
251 }
252
253
254 if (arg instanceof MuleMessage)
255 {
256 arg = ((MuleMessage) arg).getPayload();
257 }
258 return arg;
259 }
260 else
261 {
262
263 return expressionCandidate;
264 }
265 }
266
267 private Object transformArgument(Object arg, Class<?> type) throws TransformerException
268 {
269 if (!(type.isAssignableFrom(arg.getClass())))
270 {
271 DataType<?> source = DataTypeFactory.create(arg.getClass());
272 DataType<?> target = DataTypeFactory.create(type);
273
274 Transformer t = muleContext.getRegistry().lookupTransformer(source, target);
275 arg = t.transform(arg);
276 }
277 return arg;
278 }
279
280 public void setObject(Object object)
281 {
282 this.object = object;
283 }
284
285 public void setMethodName(String methodName)
286 {
287 this.methodName = methodName;
288 }
289
290 public void setArgumentExpressionsString(String arguments)
291 {
292 this.arguments = Arrays.asList(arguments.split("\\s*,\\s*"));
293 }
294
295 public void setArguments(List<?> arguments)
296 {
297 this.arguments = arguments;
298 }
299
300 protected MuleEvent createResultEvent(MuleEvent event, Object result) throws MuleException
301 {
302 if (result instanceof MuleMessage)
303 {
304 return new DefaultMuleEvent((MuleMessage) result, event);
305 }
306 else if (result != null)
307 {
308 event.getMessage().applyTransformers(
309 event,
310 Collections.<Transformer> singletonList(new TransformerTemplate(
311 new TransformerTemplate.OverwitePayloadCallback(result))));
312 return event;
313 }
314 else
315 {
316 return new DefaultMuleEvent(new DefaultMuleMessage(NullPayload.getInstance(),
317 event.getMuleContext()), event);
318 }
319 }
320
321 public String getName()
322 {
323 return name;
324 }
325
326 public void setName(String name)
327 {
328 this.name = name;
329 }
330
331 public void setArgumentTypes(Class<?>[] argumentTypes)
332 {
333 this.argumentTypes = argumentTypes;
334 }
335
336 @Override
337 public String toString()
338 {
339 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 this.muleContext = context;
347 }
348
349 public void setObjectType(Class<?> objectType)
350 {
351 this.objectType = objectType;
352 }
353
354 }