1
2
3
4
5
6
7
8
9
10 package org.mule.impl.model.resolvers;
11
12 import org.mule.api.MuleEventContext;
13 import org.mule.api.annotations.meta.Evaluator;
14 import org.mule.api.config.MuleProperties;
15 import org.mule.api.lifecycle.InitialisationException;
16 import org.mule.api.model.InvocationResult;
17 import org.mule.api.transformer.Transformer;
18 import org.mule.api.transformer.TransformerException;
19 import org.mule.api.transport.PropertyScope;
20 import org.mule.config.expression.ExpressionAnnotationsHelper;
21 import org.mule.config.i18n.CoreMessages;
22 import org.mule.expression.transformers.ExpressionTransformer;
23 import org.mule.model.resolvers.AbstractEntryPointResolver;
24 import org.mule.transport.NullPayload;
25 import org.mule.util.ClassUtils;
26 import org.mule.util.annotation.AnnotationUtils;
27
28 import java.lang.reflect.Method;
29 import java.util.Map;
30
31 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
32 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
33
34 import net.sf.cglib.proxy.Enhancer;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public class AnnotatedEntryPointResolver extends AbstractEntryPointResolver
72 {
73
74 private AtomicBoolean cacheBuilt = new AtomicBoolean(false);
75
76
77 @SuppressWarnings("unchecked")
78 private Map<Method, Transformer> transformerCache = new ConcurrentHashMap();
79
80 public InvocationResult invoke(Object component, MuleEventContext context) throws Exception
81 {
82 try
83 {
84 initCache(component, context);
85 }
86 catch (Exception e)
87 {
88 InvocationResult result = new InvocationResult(this, InvocationResult.State.NOT_SUPPORTED);
89 result.setErrorMessage(e.toString());
90 return result;
91 }
92
93 ConcurrentHashMap methodCache = getMethodCache(component);
94 if(methodCache.size()==0)
95 {
96 InvocationResult result = new InvocationResult(this, InvocationResult.State.NOT_SUPPORTED);
97 result.setErrorMessage("Component: " + component + " doesn't have any annotated methods, skipping.");
98 return result;
99 }
100
101 Object[] payload;
102 Method method = null;
103
104 Object tempMethod = context.getMessage().removeProperty(MuleProperties.MULE_METHOD_PROPERTY, PropertyScope.INVOCATION);
105 String methodName = null;
106 if (tempMethod != null && tempMethod instanceof Method)
107 {
108 method = (Method) tempMethod;
109 }
110 else
111 {
112 methodName = (String)tempMethod;
113 }
114
115
116
117 if (methodName != null)
118 {
119 method = getMethodByName(component, methodName, context);
120 if (method == null)
121 {
122 InvocationResult result = new InvocationResult(this, InvocationResult.State.NOT_SUPPORTED);
123 result.setErrorMessage("Method not found: " + methodName + " on object: " + component.getClass() + ". If the component is a proxy there needs to be an interface on the proxy that defines this method");
124 return result;
125
126 }
127 payload = getPayloadForMethod(method, component, context);
128 }
129 else if (method != null)
130 {
131 payload = getPayloadForMethod(method, component, context);
132 }
133 else if (methodCache.size() == 1)
134 {
135 method = (Method) methodCache.values().iterator().next();
136 payload = getPayloadForMethod(method, component, context);
137 }
138 else
139 {
140 InvocationResult result = new InvocationResult(this, InvocationResult.State.FAILED);
141 result.setErrorMessage("Component: " + component + " has more than one method annotated, which means the target method name needs to be set on the event");
142 return result;
143 }
144 return invokeMethod(component, method,
145 (method.getParameterTypes().length == 0 ? ClassUtils.NO_ARGS : payload));
146 }
147
148 protected Object[] getPayloadForMethod(Method method, Object component, MuleEventContext context) throws TransformerException, InitialisationException
149 {
150 Object[] payload = null;
151 Method m = method;
152
153 if (Enhancer.isEnhanced(component.getClass()))
154 {
155 try
156 {
157 m = component.getClass().getSuperclass().getMethod(method.getName(), method.getParameterTypes());
158 }
159 catch (NoSuchMethodException e)
160 {
161 throw new TransformerException(CoreMessages.createStaticMessage(e.getMessage()), e);
162 }
163 }
164
165 if (AnnotationUtils.getParamAnnotationsWithMeta(m, Evaluator.class).size() > 0)
166 {
167 payload = getPayloadFromMessageWithAnnotations(m, context);
168 }
169 return payload;
170 }
171
172 protected Object[] getPayloadFromMessageWithAnnotations(Method method, MuleEventContext context) throws TransformerException, InitialisationException
173 {
174 ExpressionTransformer trans = (ExpressionTransformer) transformerCache.get(method);
175 if (trans == null)
176 {
177 trans = ExpressionAnnotationsHelper.getTransformerForMethodWithAnnotations(method, context.getMuleContext());
178 transformerCache.put(method, trans);
179 }
180
181 Object o = trans.transform(context.getMessage());
182 if (o instanceof NullPayload)
183 {
184 return new Object[]{null};
185 }
186 else if (o.getClass().isArray())
187 {
188 return (Object[]) o;
189 }
190 else
191 {
192 return new Object[]{o};
193 }
194 }
195
196 @Override
197 public String toString()
198 {
199 final StringBuffer sb = new StringBuffer();
200 sb.append("AnnotatedEntryPointResolver");
201 sb.append(", acceptVoidMethods=").append(isAcceptVoidMethods());
202 sb.append('}');
203 return sb.toString();
204 }
205
206
207 protected void initCache(Object component, MuleEventContext context)
208 {
209 if (!cacheBuilt.get())
210 {
211 synchronized (this)
212 {
213 try
214 {
215 if (!cacheBuilt.get())
216 {
217 for (int i = 0; i < component.getClass().getMethods().length; i++)
218 {
219 Method method = component.getClass().getMethods()[i];
220 if (AnnotationUtils.getParamAnnotationsWithMeta(method, Evaluator.class).size() > 0)
221 {
222 this.addMethodByName(component, method, context);
223 }
224 }
225 }
226 }
227 finally
228 {
229 cacheBuilt.set(true);
230 }
231 }
232 }
233 }
234 }