1
2
3
4
5
6
7 package org.mule.config.transformer;
8
9 import org.mule.api.MuleMessage;
10 import org.mule.api.annotations.param.Payload;
11 import org.mule.api.lifecycle.InitialisationException;
12 import org.mule.api.transformer.DataType;
13 import org.mule.api.transformer.DiscoverableTransformer;
14 import org.mule.api.transformer.TransformerException;
15 import org.mule.config.expression.ExpressionAnnotationsHelper;
16 import org.mule.config.i18n.AnnotationsMessages;
17 import org.mule.expression.transformers.ExpressionTransformer;
18 import org.mule.transformer.AbstractMessageTransformer;
19 import org.mule.transformer.types.DataTypeFactory;
20 import org.mule.transformer.types.SimpleDataType;
21 import org.mule.util.annotation.AnnotationUtils;
22
23 import java.lang.reflect.Method;
24 import java.lang.reflect.Modifier;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Map;
28 import java.util.WeakHashMap;
29
30
31
32
33
34
35 public class AnnotatedTransformerProxy extends AbstractMessageTransformer implements DiscoverableTransformer
36 {
37 private int weighting;
38
39 private Object proxy;
40
41 private Method transformMethod;
42 private boolean messageAware = false;
43 private ExpressionTransformer paramTransformer = null;
44 private Collection<TransformerArgumentResolver> resolvers;
45 private Map<Class<?>, Object> cachedObjects = new WeakHashMap<Class<?>, Object>();
46 private boolean sourceAnnotated = false;
47
48 public AnnotatedTransformerProxy(int weighting, Object proxy, Method transformMethod, Class[] additionalSourceTypes, String sourceMimeType, String resultMimeType) throws TransformerException, InitialisationException
49 {
50 this.weighting = weighting;
51 this.proxy = proxy;
52
53
54 setAllowNullReturn(true);
55
56 validateMethod(transformMethod, additionalSourceTypes);
57
58 this.transformMethod = transformMethod;
59 setReturnDataType(DataTypeFactory.createFromReturnType(transformMethod));
60
61 messageAware = MuleMessage.class.isAssignableFrom(transformMethod.getParameterTypes()[0]);
62 this.transformMethod = transformMethod;
63 if (additionalSourceTypes.length > 0)
64 {
65 if (messageAware)
66 {
67 logger.error("Transformer: " + getName() + " is MuleMessage aware, this means additional source types configured on the transformer will be ignorred. Source types are: " + Arrays.toString(additionalSourceTypes));
68 }
69 else
70 {
71 for (int i = 0; i < additionalSourceTypes.length; i++)
72 {
73 registerSourceType(new SimpleDataType(additionalSourceTypes[i], sourceMimeType));
74
75 }
76 }
77 }
78
79 Class<?> source = transformMethod.getParameterTypes()[0];
80 registerSourceType(DataTypeFactory.create(source));
81 sourceAnnotated = (transformMethod.getParameterAnnotations()[0].length > 0 &&
82 transformMethod.getParameterAnnotations()[0][0] instanceof Payload);
83
84 setName(proxy.getClass().getSimpleName() + "." + transformMethod.getName());
85 }
86
87 protected void validateMethod(Method method, Class[] sourceTypes) throws IllegalArgumentException
88 {
89 int mods = method.getModifiers();
90 if(Modifier.isAbstract(mods) || Modifier.isInterface(mods) || !Modifier.isPublic(mods)
91 || method.getReturnType().equals(Void.TYPE) || method.getParameterTypes().length==0 ||
92 method.getReturnType().equals(Object.class) || Arrays.asList(method.getParameterTypes()).contains(Object.class) ||
93 Arrays.asList(sourceTypes).contains(Object.class))
94 {
95
96
97 throw new IllegalArgumentException(AnnotationsMessages.transformerMethodNotValid(method).getMessage());
98 }
99 }
100
101 @Override
102 public void initialise() throws InitialisationException
103 {
104 super.initialise();
105 if (AnnotationUtils.methodHasParamAnnotations(transformMethod))
106 {
107 try
108 {
109 paramTransformer = ExpressionAnnotationsHelper.getTransformerForMethodWithAnnotations(transformMethod, muleContext);
110 }
111 catch (TransformerException e)
112 {
113 throw new InitialisationException(e, this);
114 }
115 }
116 resolvers = muleContext.getRegistry().lookupObjects(TransformerArgumentResolver.class);
117 }
118
119 @Override
120 public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException
121 {
122 Object firstArg = null;
123 Object[] params = new Object[transformMethod.getParameterTypes().length];
124 int paramCounter = 0;
125
126
127
128 if (paramTransformer != null)
129 {
130 Object paramArgs = paramTransformer.transformMessage(message, outputEncoding);
131
132 if (paramArgs != null && paramArgs.getClass().isArray())
133 {
134 Object[] temp = (Object[]) paramArgs;
135
136 if (!sourceAnnotated)
137 {
138 paramCounter++;
139 }
140 for (int i = 0; i < temp.length; i++)
141 {
142 params[paramCounter++] = temp[i];
143 }
144 }
145 else
146 {
147
148 if (!sourceAnnotated)
149 {
150 paramCounter++;
151 }
152 params[paramCounter++] = paramArgs;
153 }
154 }
155
156 if (messageAware)
157 {
158 firstArg = message;
159 }
160 else if (!sourceAnnotated)
161 {
162
163 try
164 {
165 firstArg = message.getPayload(DataTypeFactory.create(transformMethod.getParameterTypes()[0]));
166 }
167 catch (TransformerException e)
168 {
169 throw new TransformerException(e.getI18nMessage(), this, e);
170 }
171 }
172
173
174 if (!sourceAnnotated)
175 {
176 params[0] = firstArg;
177 if (paramCounter == 0)
178 {
179 paramCounter++;
180 }
181 }
182
183 if (paramCounter < transformMethod.getParameterTypes().length)
184 {
185 for (int i = paramCounter; i < transformMethod.getParameterTypes().length; i++)
186 {
187 Object o;
188 Class<?> type = transformMethod.getParameterTypes()[i];
189 o = cachedObjects.get(type);
190 if (o != null)
191 {
192 params[paramCounter++] = o;
193 continue;
194 }
195 DataType<?> source = DataTypeFactory.createFromParameterType(transformMethod, 0);
196
197 for (TransformerArgumentResolver resolver : resolvers)
198 {
199 try
200 {
201 o = resolver.resolve(type, source, this.returnType, muleContext);
202 if (o != null)
203 {
204 params[paramCounter++] = o;
205 cachedObjects.put(type, o);
206 break;
207 }
208 }
209 catch (Exception e)
210 {
211 throw new TransformerException(this, e);
212 }
213
214 }
215 if (o == null)
216 {
217 throw new IllegalArgumentException("Failed to find resolver for object type: " + type + " for transform method: " + transformMethod);
218 }
219 }
220 }
221 try
222 {
223 return transformMethod.invoke(proxy, params);
224 }
225 catch (Exception e)
226 {
227 e.printStackTrace();
228 throw new TransformerException(this, e);
229 }
230 }
231
232 public int getPriorityWeighting()
233 {
234 return weighting;
235 }
236
237 public void setPriorityWeighting(int weighting)
238 {
239 throw new UnsupportedOperationException("setPriorityWeighting");
240 }
241
242 @Override
243 public boolean equals(Object o)
244 {
245 if (this == o)
246 {
247 return true;
248 }
249 if (o == null || getClass() != o.getClass())
250 {
251 return false;
252 }
253
254 AnnotatedTransformerProxy that = (AnnotatedTransformerProxy) o;
255
256 if (messageAware != that.messageAware)
257 {
258 return false;
259 }
260 if (weighting != that.weighting)
261 {
262 return false;
263 }
264 if (proxy != null ? !proxy.equals(that.proxy) : that.proxy != null)
265 {
266 return false;
267 }
268 if (transformMethod != null ? !transformMethod.equals(that.transformMethod) : that.transformMethod != null)
269 {
270 return false;
271 }
272
273 return true;
274 }
275
276 @Override
277 public int hashCode()
278 {
279 int result = weighting;
280 result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
281 result = 31 * result + (transformMethod != null ? transformMethod.hashCode() : 0);
282 result = 31 * result + (messageAware ? 1 : 0);
283 return result;
284 }
285
286
287 }