1
2
3
4
5
6
7
8
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
52
53
54
55
56
57
58
59 public class InvokerMessageProcessor implements MessageProcessor, Initialisable, MuleContextAware
60 {
61 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 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 if (object == null)
78 {
79 lookupObjectInstance();
80 }
81
82 resolveMethodToInvoke();
83
84 expressionManager = muleContext.getExpressionManager();
85 }
86
87 protected void resolveMethodToInvoke() throws InitialisationException
88 {
89 if (argumentTypes != null)
90 {
91 method = ClassUtils.getMethod(object.getClass(), methodName, argumentTypes);
92 if (method == null)
93 {
94 throw new InitialisationException(CoreMessages.methodWithParamsNotFoundOnObject(methodName,
95 argumentTypes, object.getClass()), this);
96 }
97 }
98 else
99 {
100 List<Method> matchingMethods = new ArrayList<Method>();
101 for (Method methodCandidate : object.getClass().getMethods())
102 {
103 if (methodCandidate.getName().equals(methodName)
104 && methodCandidate.getParameterTypes().length == arguments.size())
105 matchingMethods.add(methodCandidate);
106 }
107 if (matchingMethods.size() == 1)
108 {
109 method = matchingMethods.get(0);
110 argumentTypes = method.getParameterTypes();
111 }
112 else
113 {
114 throw new InitialisationException(CoreMessages.methodWithNumParamsNotFoundOnObject(
115 methodName, arguments.size(), object), this);
116 }
117 }
118
119 if (logger.isDebugEnabled())
120 {
121 logger.debug(String.format("Initialised %s to use method: '%s'", this, method));
122 }
123 }
124
125 protected void lookupObjectInstance() throws InitialisationException
126 {
127 if (logger.isDebugEnabled())
128 {
129 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 object = muleContext.getRegistry().lookupObject(objectType);
137 }
138 catch (RegistrationException e)
139 {
140 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 }
145 if (object == null)
146 {
147 throw new InitialisationException(CoreMessages.initialisationFailure(String.format(
148 "No instance of '%s' was found in the registry", objectType)), this);
149
150 }
151 }
152
153 public MuleEvent process(MuleEvent event) throws MuleException
154 {
155 MuleEvent resultEvent = event;
156 Object[] args = evaluateArguments(event, arguments);
157
158 if (logger.isDebugEnabled())
159 {
160 logger.debug(String.format("Invoking '%s' of '%s' with arguments: '%s'", method.getName(),
161 object, args));
162 }
163
164 try
165 {
166 Object result = method.invoke(object, args);
167 if (!method.getReturnType().equals(void.class))
168 {
169 resultEvent = createResultEvent(event, result);
170 }
171 }
172 catch (Exception e)
173 {
174 throw new MessagingException(CoreMessages.failedToInvoke(object.toString()), event, e);
175 }
176 return resultEvent;
177 }
178
179 protected Object[] evaluateArguments(MuleEvent event, List<?> argumentTemplates)
180 throws MessagingException
181 {
182 Object[] args = new Object[argumentTemplates.size()];
183 MuleMessage message = event.getMessage();
184 try
185 {
186 for (int i = 0; i < args.length; i++)
187 {
188 Object argumentTemplate = argumentTemplates.get(i);
189 if (argumentTemplate != null)
190 {
191 args[i] = transformArgument(evaluateExpressionCandidate(argumentTemplate, message),
192 argumentTypes[i]);
193 }
194 }
195 return args;
196 }
197 catch (TransformerException e)
198 {
199 throw new MessagingException(event, e);
200 }
201 }
202
203 @SuppressWarnings("unchecked")
204 protected Object evaluateExpressionCandidate(Object expressionCandidate, MuleMessage message)
205 throws TransformerException
206 {
207 if (expressionCandidate instanceof Collection<?>)
208 {
209 Collection<Object> collectionTemplate = (Collection<Object>) expressionCandidate;
210 Collection<Object> newCollection = new ArrayList<Object>();
211 for (Object object : collectionTemplate)
212 {
213 newCollection.add(evaluateExpressionCandidate(object, message));
214 }
215 return newCollection;
216 }
217 else if (expressionCandidate instanceof Map<?, ?>)
218 {
219 Map<Object, Object> map = (Map<Object, Object>) expressionCandidate;
220 for (Entry<Object, Object> entry : map.entrySet())
221 {
222 map.put(entry.getKey(), evaluateExpressionCandidate(entry.getValue(), message));
223 }
224 return map;
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 }