1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
package org.mule.transformer; |
12 | |
|
13 | |
import org.mule.api.MuleMessage; |
14 | |
import org.mule.api.endpoint.ImmutableEndpoint; |
15 | |
import org.mule.api.lifecycle.InitialisationException; |
16 | |
import org.mule.api.transformer.Transformer; |
17 | |
import org.mule.api.transformer.TransformerException; |
18 | |
import org.mule.api.transport.MessageAdapter; |
19 | |
import org.mule.config.i18n.CoreMessages; |
20 | |
import org.mule.transport.NullPayload; |
21 | |
import org.mule.util.ClassUtils; |
22 | |
import org.mule.util.FileUtils; |
23 | |
import org.mule.util.StringMessageUtils; |
24 | |
import org.mule.util.StringUtils; |
25 | |
|
26 | |
import java.io.InputStream; |
27 | |
import java.util.Collections; |
28 | |
import java.util.List; |
29 | |
|
30 | |
import javax.xml.transform.stream.StreamSource; |
31 | |
|
32 | |
import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList; |
33 | |
|
34 | |
import org.apache.commons.logging.Log; |
35 | |
import org.apache.commons.logging.LogFactory; |
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
public abstract class AbstractTransformer implements Transformer |
43 | |
{ |
44 | |
protected static final int DEFAULT_TRUNCATE_LENGTH = 200; |
45 | |
|
46 | 5472 | protected final Log logger = LogFactory.getLog(getClass()); |
47 | |
|
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | 5472 | protected Class returnClass = Object.class; |
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
|
58 | 5472 | protected String name = null; |
59 | |
|
60 | |
|
61 | 5472 | protected ImmutableEndpoint endpoint = null; |
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | |
|
67 | 5472 | protected final List sourceTypes = new CopyOnWriteArrayList(); |
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
|
73 | 5472 | private boolean ignoreBadInput = false; |
74 | |
|
75 | |
|
76 | |
public AbstractTransformer() |
77 | |
{ |
78 | 5472 | super(); |
79 | 5472 | } |
80 | |
|
81 | |
protected Object checkReturnClass(Object object) throws TransformerException |
82 | |
{ |
83 | 356 | if (returnClass != null) |
84 | |
{ |
85 | 356 | if (!returnClass.isInstance(object)) |
86 | |
{ |
87 | 72 | throw new TransformerException( |
88 | |
CoreMessages.transformUnexpectedType(object.getClass(), returnClass), |
89 | |
this); |
90 | |
} |
91 | |
} |
92 | |
|
93 | 284 | if (logger.isDebugEnabled()) |
94 | |
{ |
95 | 0 | logger.debug("The transformed object is of expected type. Type is: " + |
96 | |
ClassUtils.getSimpleName(object.getClass())); |
97 | |
} |
98 | |
|
99 | 284 | return object; |
100 | |
} |
101 | |
|
102 | |
protected void registerSourceType(Class aClass) |
103 | |
{ |
104 | 16942 | if (!sourceTypes.contains(aClass)) |
105 | |
{ |
106 | 16942 | sourceTypes.add(aClass); |
107 | |
|
108 | 16942 | if (aClass.equals(Object.class)) |
109 | |
{ |
110 | 1178 | logger.debug("java.lang.Object has been added as source type for this transformer, there will be no source type checking performed"); |
111 | |
} |
112 | |
} |
113 | 16942 | } |
114 | |
|
115 | |
protected void unregisterSourceType(Class aClass) |
116 | |
{ |
117 | 0 | sourceTypes.remove(aClass); |
118 | 0 | } |
119 | |
|
120 | |
|
121 | |
public String getName() |
122 | |
{ |
123 | 13792 | if (name == null) |
124 | |
{ |
125 | 4594 | name = this.generateTransformerName(); |
126 | |
} |
127 | 13792 | return name; |
128 | |
} |
129 | |
|
130 | |
|
131 | |
public void setName(String string) |
132 | |
{ |
133 | 4594 | if (string == null) |
134 | |
{ |
135 | 0 | string = ClassUtils.getSimpleName(this.getClass()); |
136 | |
} |
137 | |
|
138 | 4594 | logger.debug("Setting transformer name to: " + string); |
139 | 4594 | name = string; |
140 | 4594 | } |
141 | |
|
142 | |
|
143 | |
|
144 | |
|
145 | |
|
146 | |
|
147 | |
public Class getReturnClass() |
148 | |
{ |
149 | 178 | return returnClass; |
150 | |
} |
151 | |
|
152 | |
|
153 | |
|
154 | |
|
155 | |
|
156 | |
|
157 | |
public void setReturnClass(Class newClass) |
158 | |
{ |
159 | 7378 | returnClass = newClass; |
160 | 7378 | } |
161 | |
|
162 | |
public boolean isSourceTypeSupported(Class aClass) |
163 | |
{ |
164 | 554 | return isSourceTypeSupported(aClass, false); |
165 | |
} |
166 | |
|
167 | |
public boolean isSourceTypeSupported(Class aClass, boolean exactMatch) |
168 | |
{ |
169 | 918 | int numTypes = sourceTypes.size(); |
170 | |
|
171 | 918 | if (numTypes == 0) |
172 | |
{ |
173 | 344 | return !exactMatch; |
174 | |
} |
175 | |
|
176 | 1078 | for (int i = 0; i < numTypes; i++) |
177 | |
{ |
178 | 876 | Class anotherClass = (Class) sourceTypes.get(i); |
179 | 876 | if (exactMatch) |
180 | |
{ |
181 | 412 | if (anotherClass.equals(aClass)) |
182 | |
{ |
183 | 4 | return true; |
184 | |
} |
185 | |
} |
186 | 464 | else if (anotherClass.isAssignableFrom(aClass)) |
187 | |
{ |
188 | 368 | return true; |
189 | |
} |
190 | |
} |
191 | |
|
192 | 202 | return false; |
193 | |
} |
194 | |
|
195 | |
|
196 | |
|
197 | |
|
198 | |
|
199 | |
|
200 | |
|
201 | |
public final Object transform(Object src) throws TransformerException |
202 | |
{ |
203 | 370 | String encoding = null; |
204 | |
|
205 | 370 | Object payload = src; |
206 | |
MessageAdapter adapter; |
207 | 370 | if (src instanceof MessageAdapter) |
208 | |
{ |
209 | 182 | encoding = ((MessageAdapter) src).getEncoding(); |
210 | 182 | adapter = (MessageAdapter) src; |
211 | 182 | if ((!isSourceTypeSupported(MessageAdapter.class, true) |
212 | |
&& !isSourceTypeSupported(MuleMessage.class, true) |
213 | |
&& !(this instanceof AbstractMessageAwareTransformer)) |
214 | |
) |
215 | |
{ |
216 | 164 | src = ((MessageAdapter) src).getPayload(); |
217 | 164 | payload = adapter.getPayload(); |
218 | |
} |
219 | |
} |
220 | |
|
221 | 370 | if (encoding == null && endpoint != null) |
222 | |
{ |
223 | 0 | encoding = endpoint.getEncoding(); |
224 | |
} |
225 | 370 | else if (encoding == null) |
226 | |
{ |
227 | 188 | encoding = FileUtils.DEFAULT_ENCODING; |
228 | |
} |
229 | |
|
230 | 370 | Class srcCls = src.getClass(); |
231 | 370 | if (!isSourceTypeSupported(srcCls)) |
232 | |
{ |
233 | 10 | if (ignoreBadInput) |
234 | |
{ |
235 | 4 | logger.debug("Source type is incompatible with this transformer and property 'ignoreBadInput' is set to true, so the transformer chain will continue."); |
236 | 4 | return payload; |
237 | |
} |
238 | |
else |
239 | |
{ |
240 | 6 | throw new TransformerException( |
241 | |
CoreMessages.transformOnObjectUnsupportedTypeOfEndpoint(this.getName(), |
242 | |
payload.getClass(), endpoint), this); |
243 | |
} |
244 | |
} |
245 | |
|
246 | 360 | if (logger.isDebugEnabled()) |
247 | |
{ |
248 | 0 | logger.debug("Applying transformer " + getName() + " (" + getClass().getName() + ")"); |
249 | 0 | logger.debug("Object before transform: " |
250 | |
+ StringMessageUtils.truncate(StringMessageUtils.toString(payload), DEFAULT_TRUNCATE_LENGTH, false)); |
251 | |
} |
252 | |
|
253 | |
Object result; |
254 | 360 | result = doTransform(payload, encoding); |
255 | |
|
256 | 356 | if (result == null) |
257 | |
{ |
258 | 6 | result = NullPayload.getInstance(); |
259 | |
} |
260 | |
|
261 | 356 | if (logger.isDebugEnabled()) |
262 | |
{ |
263 | 0 | logger.debug("Object after transform: " |
264 | |
+ StringMessageUtils.truncate(StringMessageUtils.toString(result), DEFAULT_TRUNCATE_LENGTH, false)); |
265 | |
} |
266 | |
|
267 | 356 | result = checkReturnClass(result); |
268 | 284 | return result; |
269 | |
} |
270 | |
|
271 | |
protected boolean isConsumed(Class srcCls) |
272 | |
{ |
273 | 0 | return InputStream.class.isAssignableFrom(srcCls) || StreamSource.class.isAssignableFrom(srcCls); |
274 | |
} |
275 | |
|
276 | |
public ImmutableEndpoint getEndpoint() |
277 | |
{ |
278 | 4 | return endpoint; |
279 | |
} |
280 | |
|
281 | |
|
282 | |
|
283 | |
|
284 | |
|
285 | |
|
286 | |
public void setEndpoint(ImmutableEndpoint endpoint) |
287 | |
{ |
288 | 558 | this.endpoint = endpoint; |
289 | 558 | } |
290 | |
|
291 | |
protected abstract Object doTransform(Object src, String encoding) throws TransformerException; |
292 | |
|
293 | |
|
294 | |
|
295 | |
|
296 | |
|
297 | |
|
298 | |
|
299 | |
public void initialise() throws InitialisationException |
300 | |
{ |
301 | |
|
302 | 5172 | } |
303 | |
|
304 | |
protected String generateTransformerName() |
305 | |
{ |
306 | 4594 | String name = ClassUtils.getSimpleName(this.getClass()); |
307 | 4594 | int i = name.indexOf("To"); |
308 | 4594 | if (i > 0 && returnClass != null) |
309 | |
{ |
310 | 4590 | String target = ClassUtils.getSimpleName(returnClass); |
311 | 4590 | if (target.equals("byte[]")) |
312 | |
{ |
313 | 1150 | target = "byteArray"; |
314 | |
} |
315 | 4590 | name = name.substring(0, i + 2) + StringUtils.capitalize(target); |
316 | |
} |
317 | 4594 | return name; |
318 | |
} |
319 | |
|
320 | |
public List getSourceTypes() |
321 | |
{ |
322 | 26 | return Collections.unmodifiableList(sourceTypes); |
323 | |
} |
324 | |
|
325 | |
public boolean isIgnoreBadInput() |
326 | |
{ |
327 | 4 | return ignoreBadInput; |
328 | |
} |
329 | |
|
330 | |
public void setIgnoreBadInput(boolean ignoreBadInput) |
331 | |
{ |
332 | 10 | this.ignoreBadInput = ignoreBadInput; |
333 | 10 | } |
334 | |
|
335 | |
|
336 | |
public String toString() |
337 | |
{ |
338 | 10242 | StringBuffer sb = new StringBuffer(80); |
339 | 10242 | sb.append(ClassUtils.getSimpleName(this.getClass())); |
340 | 10242 | sb.append("{this=").append(Integer.toHexString(System.identityHashCode(this))); |
341 | 10242 | sb.append(", name='").append(name).append('\''); |
342 | 10242 | sb.append(", ignoreBadInput=").append(ignoreBadInput); |
343 | 10242 | sb.append(", returnClass=").append(returnClass); |
344 | 10242 | sb.append(", sourceTypes=").append(sourceTypes); |
345 | 10242 | sb.append('}'); |
346 | 10242 | return sb.toString(); |
347 | |
} |
348 | |
|
349 | |
public boolean isAcceptNull() |
350 | |
{ |
351 | 0 | return false; |
352 | |
} |
353 | |
|
354 | |
} |