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