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