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 if(methodCache.size()==0)
94 {
95 InvocationResult result = new InvocationResult(this, InvocationResult.State.NOT_SUPPORTED);
96 result.setErrorMessage("Component: " + component + " doesn't have any annotated methods, skipping.");
97 return result;
98 }
99
100 Object[] payload;
101 Method method = null;
102
103 Object tempMethod = context.getMessage().removeProperty(MuleProperties.MULE_METHOD_PROPERTY, PropertyScope.INVOCATION);
104 String methodName = null;
105 if (tempMethod != null && tempMethod instanceof Method)
106 {
107 method = (Method) tempMethod;
108 }
109 else
110 {
111 methodName = (String)tempMethod;
112 }
113
114
115
116 if (methodName != null)
117 {
118 method = getMethodByName(methodName, context);
119 if (method == null)
120 {
121 InvocationResult result = new InvocationResult(this, InvocationResult.State.NOT_SUPPORTED);
122 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");
123 return result;
124
125 }
126 payload = getPayloadForMethod(method, component, context);
127 }
128 else if (method != null)
129 {
130 payload = getPayloadForMethod(method, component, context);
131 }
132 else if (methodCache.size() == 1)
133 {
134 method = (Method) methodCache.values().iterator().next();
135 payload = getPayloadForMethod(method, component, context);
136 }
137 else
138 {
139 InvocationResult result = new InvocationResult(this, InvocationResult.State.FAILED);
140 result.setErrorMessage("Component: " + component + " has more than one method annotated, which means the target method name needs to be set on the event");
141 return result;
142 }
143 return invokeMethod(component, method,
144 (method.getParameterTypes().length == 0 ? ClassUtils.NO_ARGS : payload));
145 }
146
147 protected Object[] getPayloadForMethod(Method method, Object component, MuleEventContext context) throws TransformerException, InitialisationException
148 {
149 Object[] payload = null;
150 Method m = method;
151
152 if (Enhancer.isEnhanced(component.getClass()))
153 {
154 try
155 {
156 m = component.getClass().getSuperclass().getMethod(method.getName(), method.getParameterTypes());
157 }
158 catch (NoSuchMethodException e)
159 {
160 throw new TransformerException(CoreMessages.createStaticMessage(e.getMessage()), e);
161 }
162 }
163
164 if (AnnotationUtils.getParamAnnotationsWithMeta(m, Evaluator.class).size() > 0)
165 {
166 payload = getPayloadFromMessageWithAnnotations(m, context);
167 }
168 return payload;
169 }
170
171 protected Object[] getPayloadFromMessageWithAnnotations(Method method, MuleEventContext context) throws TransformerException, InitialisationException
172 {
173 ExpressionTransformer trans = (ExpressionTransformer) transformerCache.get(method);
174 if (trans == null)
175 {
176 trans = ExpressionAnnotationsHelper.getTransformerForMethodWithAnnotations(method, context.getMuleContext());
177 transformerCache.put(method, trans);
178 }
179
180 Object o = trans.transform(context.getMessage());
181 if (o instanceof NullPayload)
182 {
183 return new Object[]{null};
184 }
185 else if (o.getClass().isArray())
186 {
187 return (Object[]) o;
188 }
189 else
190 {
191 return new Object[]{o};
192 }
193 }
194
195 @Override
196 public String toString()
197 {
198 final StringBuffer sb = new StringBuffer();
199 sb.append("AnnotatedEntryPointResolver");
200 sb.append(", acceptVoidMethods=").append(isAcceptVoidMethods());
201 sb.append('}');
202 return sb.toString();
203 }
204
205
206 protected void initCache(Object component, MuleEventContext context)
207 {
208 if (!cacheBuilt.get())
209 {
210 synchronized (this)
211 {
212 try
213 {
214 if (!cacheBuilt.get())
215 {
216 for (int i = 0; i < component.getClass().getMethods().length; i++)
217 {
218 Method method = component.getClass().getMethods()[i];
219 if (AnnotationUtils.getParamAnnotationsWithMeta(method, Evaluator.class).size() > 0)
220 {
221 this.addMethodByName(method, context);
222 }
223 }
224 }
225 }
226 finally
227 {
228 cacheBuilt.set(true);
229 }
230 }
231 }
232 }
233 }