1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.xml.transformer;
12
13 import org.mule.RequestContext;
14 import org.mule.api.MuleEventContext;
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.config.i18n.CoreMessages;
19 import org.mule.module.xml.util.XMLUtils;
20 import org.mule.util.ClassUtils;
21 import org.mule.util.IOUtils;
22 import org.mule.util.StringUtils;
23 import org.mule.util.expression.ExpressionEvaluatorManager;
24
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.StringReader;
28 import java.util.Iterator;
29 import java.util.Map;
30 import java.util.Map.Entry;
31
32 import javax.xml.transform.ErrorListener;
33 import javax.xml.transform.OutputKeys;
34 import javax.xml.transform.Result;
35 import javax.xml.transform.Source;
36 import javax.xml.transform.TransformerFactory;
37 import javax.xml.transform.TransformerFactoryConfigurationError;
38 import javax.xml.transform.URIResolver;
39 import javax.xml.transform.stream.StreamSource;
40
41 import org.apache.commons.pool.BasePoolableObjectFactory;
42 import org.apache.commons.pool.impl.GenericObjectPool;
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public class XsltTransformer extends AbstractXmlTransformer
95 {
96
97 private static final int MIN_IDLE_TRANSFORMERS = 1;
98
99 private static final int MAX_IDLE_TRANSFORMERS = 32;
100
101 private static final int MAX_ACTIVE_TRANSFORMERS = MAX_IDLE_TRANSFORMERS;
102
103 private static final String PARAM_EXTRACTOR_TOKEN = "${";
104
105 protected final GenericObjectPool transformerPool;
106
107
108 private volatile String xslTransformerFactoryClassName = "net.sf.saxon.TransformerFactoryImpl";
109 private volatile String xslFile;
110 private volatile String xslt;
111 private volatile Map contextProperties;
112
113 private URIResolver uriResolver;
114
115 public XsltTransformer()
116 {
117 super();
118 transformerPool = new GenericObjectPool(new PooledXsltTransformerFactory());
119 transformerPool.setMinIdle(MIN_IDLE_TRANSFORMERS);
120 transformerPool.setMaxIdle(MAX_IDLE_TRANSFORMERS);
121 transformerPool.setMaxActive(MAX_ACTIVE_TRANSFORMERS);
122 uriResolver = new LocalURIResolver();
123 }
124
125 public void initialise() throws InitialisationException
126 {
127 try
128 {
129 transformerPool.addObject();
130 }
131 catch (Throwable te)
132 {
133 throw new InitialisationException(te, this);
134 }
135 }
136
137
138
139
140
141
142
143 public Object doTransform(Object src, String encoding) throws TransformerException
144 {
145 try
146 {
147 Source sourceDoc = XMLUtils.toXmlSource(getXMLInputFactory(), isUseStaxSource(), src);
148 if (sourceDoc == null)
149 {
150 return null;
151 }
152
153 ResultHolder holder = getResultHolder(returnClass);
154
155
156 if (holder == null)
157 {
158 holder = getResultHolder(src.getClass());
159 }
160
161
162
163 if (holder == null || DelayedResult.class.equals(returnClass))
164 {
165 return getDelayedResult(encoding, sourceDoc);
166 }
167
168 doTransform(encoding, sourceDoc, holder.getResult());
169
170 return holder.getResultObject();
171 }
172 catch (Exception e)
173 {
174 throw new TransformerException(this, e);
175 }
176 }
177
178 protected Object getDelayedResult(final String encoding, final Source sourceDoc)
179 {
180 return new DelayedResult()
181 {
182 private String systemId;
183
184 public void write(Result result) throws Exception
185 {
186 doTransform(encoding, sourceDoc, result);
187 }
188
189 public String getSystemId()
190 {
191 return systemId;
192 }
193
194 public void setSystemId(String systemId)
195 {
196 this.systemId = systemId;
197 }
198 };
199 }
200
201 protected void doTransform(String encoding, Source sourceDoc, Result result)
202 throws Exception
203 {
204 DefaultErrorListener errorListener = new DefaultErrorListener(this);
205 javax.xml.transform.Transformer transformer = null;
206
207 try
208 {
209 transformer = (javax.xml.transform.Transformer) transformerPool.borrowObject();
210
211 transformer.setErrorListener(errorListener);
212 transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
213
214
215 if (contextProperties != null)
216 {
217 for (Iterator i = contextProperties.entrySet().iterator(); i.hasNext();)
218 {
219 Map.Entry parameter = (Entry) i.next();
220 String key = (String) parameter.getKey();
221 transformer.setParameter(key, evaluateTransformParameter(key, parameter.getValue()));
222 }
223 }
224
225 transformer.transform(sourceDoc, result);
226
227 if (errorListener.isError())
228 {
229 throw errorListener.getException();
230 }
231 }
232 finally
233 {
234 if (transformer != null)
235 {
236
237
238 transformer.clearParameters();
239
240 transformerPool.returnObject(transformer);
241 }
242 }
243 }
244
245
246
247
248
249
250
251
252 public String getXslTransformerFactory()
253 {
254 return xslTransformerFactoryClassName;
255 }
256
257
258
259
260
261
262 public void setXslTransformerFactory(String xslTransformerFactory)
263 {
264 this.xslTransformerFactoryClassName = xslTransformerFactory;
265 }
266
267
268
269
270 public String getXslFile()
271 {
272 return xslFile;
273 }
274
275
276
277
278 public void setXslFile(String xslFile)
279 {
280 this.xslFile = xslFile;
281 }
282
283 public String getXslt()
284 {
285 return xslt;
286 }
287
288 public void setXslt(String xslt)
289 {
290 this.xslt = xslt;
291 }
292
293 public URIResolver getUriResolver()
294 {
295 return uriResolver;
296 }
297
298 public void setUriResolver(URIResolver uriResolver)
299 {
300 this.uriResolver = uriResolver;
301 }
302
303
304
305
306
307
308 protected StreamSource getStreamSource() throws InitialisationException
309 {
310 if (xslt != null)
311 {
312 return new StreamSource(new StringReader(xslt));
313 }
314
315 if (xslFile == null)
316 {
317 throw new InitialisationException(CoreMessages.objectIsNull("xslFile"), this);
318 }
319
320 InputStream is;
321 try
322 {
323 is = IOUtils.getResourceAsStream(xslFile, getClass());
324
325
326
327
328 }
329 catch (IOException e)
330 {
331 throw new InitialisationException(e, this);
332 }
333 if (is != null)
334 {
335 return new StreamSource(is);
336 }
337 else
338 {
339 throw new InitialisationException(CoreMessages.failedToLoad(xslFile), this);
340 }
341 }
342
343 protected class PooledXsltTransformerFactory extends BasePoolableObjectFactory
344 {
345 public Object makeObject() throws Exception
346 {
347 StreamSource source = XsltTransformer.this.getStreamSource();
348 String factoryClassName = XsltTransformer.this.getXslTransformerFactory();
349 TransformerFactory factory;
350
351 if (StringUtils.isNotEmpty(factoryClassName))
352 {
353 factory = (TransformerFactory) ClassUtils.instanciateClass(factoryClassName,
354 ClassUtils.NO_ARGS, this.getClass());
355 }
356 else
357 {
358
359 try
360 {
361 factory = TransformerFactory.newInstance();
362 }
363 catch (TransformerFactoryConfigurationError e)
364 {
365 System.setProperty("javax.xml.transform.TransformerFactory", XMLUtils.TRANSFORMER_FACTORY_JDK5);
366 factory = TransformerFactory.newInstance();
367 }
368 }
369
370 factory.setURIResolver(getUriResolver());
371 return factory.newTransformer(source);
372 }
373 }
374
375 protected class DefaultErrorListener implements ErrorListener
376 {
377 private TransformerException e = null;
378 private final Transformer trans;
379
380 public DefaultErrorListener(Transformer trans)
381 {
382 this.trans = trans;
383 }
384
385 public TransformerException getException()
386 {
387 return e;
388 }
389
390 public boolean isError()
391 {
392 return e != null;
393 }
394
395 public void error(javax.xml.transform.TransformerException exception)
396 throws javax.xml.transform.TransformerException
397 {
398 e = new TransformerException(trans, exception);
399 }
400
401 public void fatalError(javax.xml.transform.TransformerException exception)
402 throws javax.xml.transform.TransformerException
403 {
404 e = new TransformerException(trans, exception);
405 }
406
407 public void warning(javax.xml.transform.TransformerException exception)
408 throws javax.xml.transform.TransformerException
409 {
410 logger.warn(exception.getMessage());
411 }
412 }
413
414
415
416
417
418 public int getMaxActiveTransformers()
419 {
420 return transformerPool.getMaxActive();
421 }
422
423
424
425
426
427
428
429 public void setMaxActiveTransformers(int maxActiveTransformers)
430 {
431 transformerPool.setMaxActive(maxActiveTransformers);
432 }
433
434
435
436
437
438 public int getMaxIdleTransformers()
439 {
440 return transformerPool.getMaxIdle();
441 }
442
443
444
445
446
447
448 public void setMaxIdleTransformers(int maxIdleTransformers)
449 {
450 transformerPool.setMaxIdle(maxIdleTransformers);
451 }
452
453
454
455
456
457
458
459
460 public Map getContextProperties()
461 {
462 return contextProperties;
463 }
464
465
466
467
468
469
470
471
472 public void setContextProperties(Map contextProperties)
473 {
474 this.contextProperties = contextProperties;
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490 protected Object evaluateTransformParameter(String name, Object value) throws TransformerException
491 {
492 if (value instanceof String)
493 {
494 String stringValue = (String) value;
495
496 if (!stringValue.startsWith(PARAM_EXTRACTOR_TOKEN))
497 {
498 return stringValue;
499 }
500 else
501 {
502 MuleEventContext context = RequestContext.getEventContext();
503
504 if (context == null)
505 {
506 throw new TransformerException(CoreMessages.noCurrentEventForTransformer(), this);
507 }
508 return ExpressionEvaluatorManager.evaluate(value.toString(), context.getMessage());
509 }
510 }
511
512 return value;
513 }
514
515 private class LocalURIResolver implements URIResolver
516 {
517 public Source resolve(String href, String base)
518 throws javax.xml.transform.TransformerException
519 {
520 try
521 {
522 return new StreamSource(IOUtils.getResourceAsStream(href, getClass()));
523 }
524 catch (IOException e)
525 {
526 throw new javax.xml.transform.TransformerException(e);
527 }
528 }
529 }
530 }