1
2
3
4
5
6
7
8
9
10
11 package org.mule.transformers;
12
13 import org.mule.MuleManager;
14 import org.mule.config.i18n.CoreMessages;
15 import org.mule.providers.NullPayload;
16 import org.mule.umo.UMOMessage;
17 import org.mule.umo.endpoint.UMOImmutableEndpoint;
18 import org.mule.umo.lifecycle.InitialisationException;
19 import org.mule.umo.transformer.TransformerException;
20 import org.mule.umo.transformer.UMOTransformer;
21 import org.mule.util.BeanUtils;
22 import org.mule.util.ClassUtils;
23 import org.mule.util.StringMessageUtils;
24
25 import java.util.List;
26
27 import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30
31
32
33
34
35
36 public abstract class AbstractTransformer implements UMOTransformer
37 {
38 protected static final int DEFAULT_TRUNCATE_LENGTH = 200;
39
40
41
42
43 protected final Log logger = LogFactory.getLog(getClass());
44
45
46
47
48
49 protected Class returnClass = Object.class;
50
51
52
53
54
55 protected String name = null;
56
57
58
59
60 protected UMOImmutableEndpoint endpoint = null;
61
62
63
64
65
66 protected final List sourceTypes = new CopyOnWriteArrayList();
67
68
69
70
71 protected UMOTransformer nextTransformer;
72
73
74
75
76
77 private boolean ignoreBadInput = false;
78
79
80
81
82 public AbstractTransformer()
83 {
84 name = this.generateTransformerName();
85 }
86
87 protected Object checkReturnClass(Object object) throws TransformerException
88 {
89 if (returnClass != null)
90 {
91 if (!returnClass.isInstance(object))
92 {
93 throw new TransformerException(
94 CoreMessages.transformUnexpectedType(object.getClass(), returnClass),
95 this);
96 }
97 }
98
99 if (logger.isDebugEnabled())
100 {
101 logger.debug("The transformed object is of expected type. Type is: " +
102 ClassUtils.getSimpleName(object.getClass()));
103 }
104
105 return object;
106 }
107
108 protected void registerSourceType(Class aClass)
109 {
110 if (!sourceTypes.contains(aClass))
111 {
112 sourceTypes.add(aClass);
113
114 if (aClass.equals(Object.class))
115 {
116 logger.debug("java.lang.Object has been added as source type for this transformer, there will be no source type checking performed");
117 }
118 }
119 }
120
121 protected void unregisterSourceType(Class aClass)
122 {
123 sourceTypes.remove(aClass);
124 }
125
126
127
128
129 public String getName()
130 {
131 return name;
132 }
133
134
135
136
137 public void setName(String string)
138 {
139 if (string == null)
140 {
141 string = ClassUtils.getSimpleName(this.getClass());
142 }
143
144 logger.debug("Setting transformer name to: " + string);
145 name = string;
146 }
147
148
149
150
151
152
153 public Class getReturnClass()
154 {
155 return returnClass;
156 }
157
158
159
160
161
162
163 public void setReturnClass(Class newClass)
164 {
165 returnClass = newClass;
166 }
167
168 public boolean isSourceTypeSupported(Class aClass)
169 {
170 return isSourceTypeSupported(aClass, false);
171 }
172
173 public boolean isSourceTypeSupported(Class aClass, boolean exactMatch)
174 {
175 int numTypes = sourceTypes.size();
176
177 if (numTypes == 0)
178 {
179 return !exactMatch;
180 }
181
182 for (int i = 0; i < numTypes; i++)
183 {
184 Class anotherClass = (Class) sourceTypes.get(i);
185 if (exactMatch)
186 {
187 if (anotherClass.equals(aClass))
188 {
189 return true;
190 }
191 }
192 else if (anotherClass.isAssignableFrom(aClass))
193 {
194 return true;
195 }
196 }
197
198 return false;
199 }
200
201
202
203
204
205
206
207 public final Object transform(Object src) throws TransformerException
208 {
209 String encoding = null;
210
211 if (src instanceof UMOMessage && !isSourceTypeSupported(UMOMessage.class))
212 {
213 encoding = ((UMOMessage) src).getEncoding();
214 src = ((UMOMessage) src).getPayload();
215 }
216
217 if (encoding == null && endpoint != null)
218 {
219 encoding = endpoint.getEncoding();
220 }
221
222
223 if (encoding == null)
224 {
225 encoding = MuleManager.getConfiguration().getEncoding();
226 }
227
228 if (!isSourceTypeSupported(src.getClass()))
229 {
230 if (ignoreBadInput)
231 {
232 logger.debug("Source type is incompatible with this transformer and property 'ignoreBadInput' is set to true, so the transformer chain will continue.");
233 return nextTransform(src);
234 }
235 else
236 {
237 throw new TransformerException(
238 CoreMessages.transformOnObjectUnsupportedTypeOfEndpoint(this.getName(),
239 src.getClass(), endpoint), this);
240 }
241 }
242
243 if (logger.isDebugEnabled())
244 {
245 logger.debug("Applying transformer " + getName() + " (" + getClass().getName() + ")");
246 logger.debug("Object before transform: "
247 + StringMessageUtils.truncate(StringMessageUtils.toString(src), DEFAULT_TRUNCATE_LENGTH, false));
248 }
249
250 Object result = doTransform(src, encoding);
251 if (result == null)
252 {
253 result = NullPayload.getInstance();
254 }
255
256 if (logger.isDebugEnabled())
257 {
258 logger.debug("Object after transform: "
259 + StringMessageUtils.truncate(StringMessageUtils.toString(result), DEFAULT_TRUNCATE_LENGTH, false));
260 }
261
262 result = checkReturnClass(result);
263
264 result = nextTransform(result);
265
266 return result;
267 }
268
269 public UMOImmutableEndpoint getEndpoint()
270 {
271 return endpoint;
272 }
273
274
275
276
277
278
279 public void setEndpoint(UMOImmutableEndpoint endpoint)
280 {
281 this.endpoint = endpoint;
282 UMOTransformer trans = nextTransformer;
283 while (trans != null && endpoint != null)
284 {
285 trans.setEndpoint(endpoint);
286 trans = trans.getNextTransformer();
287 }
288 }
289
290 protected abstract Object doTransform(Object src, String encoding) throws TransformerException;
291
292
293
294
295
296
297 public UMOTransformer getNextTransformer()
298 {
299 return nextTransformer;
300 }
301
302
303
304
305
306
307 public void setNextTransformer(UMOTransformer nextTransformer)
308 {
309 this.nextTransformer = nextTransformer;
310 }
311
312
313
314
315
316
317 public Object clone() throws CloneNotSupportedException
318 {
319 try
320 {
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 AbstractTransformer clone = (AbstractTransformer)BeanUtils.cloneBean(this);
337
338
339
340
341
342 clone.sourceTypes.clear();
343 clone.sourceTypes.addAll(sourceTypes);
344
345
346 if (nextTransformer != null)
347 {
348 clone.setNextTransformer((UMOTransformer) nextTransformer.clone());
349 }
350
351
352 clone.setEndpoint(endpoint);
353
354 return clone;
355 }
356 catch (Exception e)
357 {
358 throw (CloneNotSupportedException) new CloneNotSupportedException("Failed to clone transformer: "
359 + e.getMessage()).initCause(e);
360 }
361 }
362
363
364
365
366
367
368 public Class getFinalReturnClass()
369 {
370 UMOTransformer tempTrans = this;
371 UMOTransformer returnTrans = this;
372 while (tempTrans != null)
373 {
374 returnTrans = tempTrans;
375 tempTrans = tempTrans.getNextTransformer();
376 }
377 return returnTrans.getReturnClass();
378 }
379
380
381
382
383
384
385
386 public void initialise() throws InitialisationException
387 {
388
389 }
390
391 protected String generateTransformerName()
392 {
393 return ClassUtils.getSimpleName(this.getClass());
394 }
395
396 public boolean isIgnoreBadInput()
397 {
398 return ignoreBadInput;
399 }
400
401 public void setIgnoreBadInput(boolean ignoreBadInput)
402 {
403 this.ignoreBadInput = ignoreBadInput;
404 }
405
406
407 public String toString()
408 {
409 StringBuffer sb = new StringBuffer(80);
410 sb.append(ClassUtils.getSimpleName(this.getClass()));
411 sb.append("{this=").append(Integer.toHexString(System.identityHashCode(this)));
412 sb.append(", name='").append(name).append('\'');
413 sb.append(", ignoreBadInput=").append(ignoreBadInput);
414 sb.append(", returnClass=").append(returnClass);
415 sb.append(", sourceTypes=").append(sourceTypes);
416 sb.append('}');
417 return sb.toString();
418 }
419
420 public boolean isAcceptNull()
421 {
422 return false;
423 }
424
425
426
427
428 protected Object nextTransform(Object result)
429 throws TransformerException
430 {
431 if (nextTransformer != null)
432 {
433 logger.debug("Following transformer in the chain is " + nextTransformer.getName() + " ("
434 + nextTransformer.getClass().getName() + ")");
435 result = nextTransformer.transform(result);
436 }
437 return result;
438 }
439 }