1 package org.apache.fulcrum.template.velocity;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import java.io.ByteArrayOutputStream;
25 import java.io.File;
26 import java.io.IOException;
27 import java.io.OutputStream;
28 import java.io.OutputStreamWriter;
29 import java.io.Writer;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Vector;
35
36 import org.apache.avalon.framework.activity.Initializable;
37 import org.apache.avalon.framework.configuration.Configuration;
38 import org.apache.avalon.framework.configuration.ConfigurationException;
39 import org.apache.commons.configuration.ConfigurationConverter;
40 import org.apache.fulcrum.template.BaseTemplateEngineService;
41 import org.apache.fulcrum.template.TemplateContext;
42 import org.apache.fulcrum.template.TemplateException;
43 import org.apache.velocity.VelocityContext;
44 import org.apache.velocity.app.VelocityEngine;
45 import org.apache.velocity.app.event.EventCartridge;
46 import org.apache.velocity.app.event.MethodExceptionEventHandler;
47 import org.apache.velocity.app.event.NullSetEventHandler;
48 import org.apache.velocity.app.event.ReferenceInsertionEventHandler;
49 import org.apache.velocity.context.Context;
50 import org.apache.velocity.context.InternalEventContext;
51 import org.apache.velocity.exception.MethodInvocationException;
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 public class DefaultVelocityService
80 extends BaseTemplateEngineService
81 implements VelocityService, Initializable
82 {
83
84
85
86 private static final String RESOURCE_LOADER_PATH =
87 ".resource.loader.path";
88
89
90
91
92 private static final String DEFAULT_CHAR_SET = "ISO-8859-1";
93
94
95
96
97 private static final String JAR_PREFIX = "jar:";
98
99
100
101
102 private static final String ABSOLUTE_PREFIX = "file://";
103
104
105
106
107 private EventCartridge eventCartridge;
108
109
110
111
112
113 private boolean eventCartridgeEnabled = true;
114
115
116
117 org.apache.commons.configuration.Configuration velocityConf;
118
119
120
121
122 private VelocityEngine velocityEngine;
123
124
125
126
127 public String handleRequest(TemplateContext context, String template)
128 throws TemplateException
129 {
130 return handleRequest(new ContextAdapter(context), template);
131 }
132
133
134
135
136 public String handleRequest(Context context, String filename)
137 throws TemplateException
138 {
139 return handleRequest(context, filename, (String)null, null);
140 }
141
142
143
144
145 public String handleRequest(Context context, String filename,
146 String charset, String encoding)
147 throws TemplateException
148 {
149 String results = null;
150 ByteArrayOutputStream bytes = null;
151
152 try
153 {
154 bytes = new ByteArrayOutputStream();
155 charset = decodeRequest(context, filename, bytes, charset,
156 encoding);
157 results = bytes.toString(charset);
158 }
159 catch (Exception e)
160 {
161 renderingError(filename, e);
162 }
163 finally
164 {
165 try
166 {
167 if (bytes != null)
168 {
169 bytes.close();
170 }
171 }
172 catch (IOException ignored)
173 {
174 }
175 }
176 return results;
177 }
178
179
180
181
182 public void handleRequest(TemplateContext context, String template,
183 OutputStream outputStream)
184 throws TemplateException
185 {
186 handleRequest(new ContextAdapter(context), template, outputStream);
187 }
188
189
190
191
192 public void handleRequest(Context context, String filename,
193 OutputStream output)
194 throws TemplateException
195 {
196 handleRequest(context, filename, output, null, null);
197 }
198
199
200
201
202 public void handleRequest(Context context, String filename,
203 OutputStream output, String charset,
204 String encoding)
205 throws TemplateException
206 {
207 decodeRequest(context, filename, output, charset, encoding);
208 }
209
210
211
212
213 public void handleRequest(TemplateContext context,
214 String template, Writer writer)
215 throws TemplateException
216 {
217 handleRequest(new ContextAdapter(context), template, writer);
218 }
219
220
221
222
223 public void handleRequest(Context context, String filename,
224 Writer writer)
225 throws TemplateException
226 {
227 handleRequest(context, filename, writer, null);
228 }
229
230
231
232
233 public void handleRequest(Context context, String filename,
234 Writer writer, String encoding)
235 throws TemplateException
236 {
237 try
238 {
239
240
241
242
243
244
245 Context eventContext;
246
247 if ( context instanceof InternalEventContext )
248 {
249 eventContext = context;
250 }
251 else
252 {
253 eventContext = new VelocityContext( context );
254 }
255
256
257 EventCartridge ec = getEventCartridge();
258 if (ec != null && eventCartridgeEnabled)
259 {
260 ec.attachToContext(eventContext);
261 }
262
263 if (encoding != null)
264 {
265
266 velocityEngine.mergeTemplate(filename, encoding,
267 eventContext, writer);
268 }
269 else
270 {
271 velocityEngine.mergeTemplate(filename, eventContext, writer);
272 }
273 }
274 catch (Exception e)
275 {
276 renderingError(filename, e);
277 }
278 }
279
280
281
282
283
284
285 public void setEventCartridgeEnabled(boolean value)
286 {
287 this.eventCartridgeEnabled = value;
288 }
289
290
291
292
293 public EventCartridge getEventCartridge()
294 {
295 return eventCartridge;
296 }
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 private String decodeRequest(Context context, String filename,
314 OutputStream output, String charset,
315 String encoding)
316 throws TemplateException
317 {
318
319
320
321
322
323 if (charset == null)
324 {
325 charset = DEFAULT_CHAR_SET;
326 }
327
328 OutputStreamWriter writer = null;
329 try
330 {
331 try
332 {
333 writer = new OutputStreamWriter(output, charset);
334 }
335 catch (Exception e)
336 {
337 renderingError(filename, e);
338 }
339 handleRequest(context, filename, writer, encoding);
340 }
341 finally
342 {
343 try
344 {
345 if (writer != null)
346 {
347 writer.flush();
348 }
349 }
350 catch (Exception ignored)
351 {
352 }
353 }
354 return charset;
355 }
356
357
358
359
360
361
362
363
364
365
366 private final void renderingError(String filename, Throwable e)
367 throws TemplateException
368 {
369 String err = "Error rendering Velocity template: " + filename;
370 getLogger().error(err + ": " + e.getMessage());
371
372
373 if (e instanceof MethodInvocationException)
374 {
375 e = ((MethodInvocationException)e).getWrappedThrowable();
376 }
377
378 throw new TemplateException(err, e);
379 }
380
381
382
383
384
385
386
387
388
389 public boolean templateExists(String template)
390 {
391 return velocityEngine.templateExists(template);
392 }
393
394
395
396
397
398
399 public void configure(Configuration conf)
400 throws ConfigurationException
401 {
402
403 velocityConf =
404 new org.apache.commons.configuration.BaseConfiguration();
405 List ecconfig = null;
406 String logPath = null;
407 List templatePathKeys = new ArrayList();
408 List templatePaths = new ArrayList();
409
410 if (1==2)
411 {
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 }
450 else
451 {
452
453 if (true)
454 {
455 throw new ConfigurationException(
456 "Use of avalon-style configuration not completed yet");
457 }
458
459 final Configuration eventCartridgeConfs =
460 conf.getChild("event-cartriges", false);
461 if (eventCartridgeConfs == null)
462 {
463 ecconfig = Collections.EMPTY_LIST;
464 }
465 else
466 {
467 Configuration[] classNameConfs =
468 eventCartridgeConfs.getChildren("classname");
469 if (classNameConfs == null)
470 {
471 ecconfig = Collections.EMPTY_LIST;
472 }
473 else
474 {
475 ecconfig = new ArrayList(classNameConfs.length);
476 for (int i=0; i < classNameConfs.length; i++)
477 {
478 ecconfig.add(classNameConfs[i].getValue());
479 }
480 }
481 }
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496 }
497
498 initEventCartridges(ecconfig);
499
500
501 if ( !(new File(logPath).isAbsolute()) )
502 {
503 logPath = getRealPath(logPath);
504 }
505 velocityConf.setProperty(VelocityEngine.RUNTIME_LOG, logPath);
506
507 configureTemplatePaths(templatePathKeys, templatePaths);
508
509
510 registerConfiguration(conf, "vm");
511 }
512
513
514
515
516
517
518
519
520
521
522 private void initEventCartridges(List ecconfig)
523 throws ConfigurationException
524 {
525 eventCartridge = new EventCartridge();
526 Object obj = null;
527 String className = null;
528 for (Iterator i = ecconfig.iterator() ; i.hasNext() ;)
529 {
530 className = (String)i.next();
531 try
532 {
533 boolean result = false;
534
535 obj = Class.forName(className).newInstance();
536
537 if (obj instanceof ReferenceInsertionEventHandler)
538 {
539 result = getEventCartridge()
540 .addEventHandler((ReferenceInsertionEventHandler)obj);
541 }
542 else if (obj instanceof NullSetEventHandler)
543 {
544 result = getEventCartridge()
545 .addEventHandler((NullSetEventHandler)obj);
546 }
547 else if (obj instanceof MethodExceptionEventHandler)
548 {
549 result = getEventCartridge()
550 .addEventHandler((MethodExceptionEventHandler)obj);
551 }
552 getLogger().info("Added EventCartridge: " +
553 obj.getClass().getName() + " : " + result);
554 }
555 catch (Exception h)
556 {
557 throw new ConfigurationException(
558 "Could not configure EventCartridge: " +
559 className, h);
560 }
561 }
562 }
563
564
565
566
567
568
569
570 private void configureTemplatePaths(
571 List templatePathKeys, List templatePaths)
572 {
573
574
575 for (int i=0; i<templatePathKeys.size(); i++)
576 {
577 String key = (String) templatePathKeys.get(i);
578 Vector paths = (Vector) templatePaths.get(i);
579 if (paths != null)
580 {
581 String entry;
582 for (Iterator j = paths.iterator(); j.hasNext();)
583 {
584 String path = (String) j.next();
585 if (path.startsWith(JAR_PREFIX + "file"))
586 {
587
588
589 int ind = path.indexOf("!/");
590 if (ind >= 0)
591 {
592 entry = path.substring(ind);
593 path = path.substring(9,ind);
594 }
595 else
596 {
597 entry = "!/";
598 path = path.substring(9);
599 }
600 path = JAR_PREFIX + "file:" + getRealPath(path) +
601 entry;
602 }
603 else if (path.startsWith(ABSOLUTE_PREFIX))
604 {
605 path = path.substring (ABSOLUTE_PREFIX.length(),
606 path.length());
607 }
608 else if (!path.startsWith(JAR_PREFIX))
609 {
610
611 path = getRealPath(path);
612 }
613
614 velocityConf.addProperty(key,path);
615 }
616 }
617 }
618 }
619
620
621
622
623
624
625 public void initialize()
626 throws Exception
627 {
628 try
629 {
630 velocityEngine = new VelocityEngine();
631
632
633
634 Iterator i = velocityConf.getKeys();
635 while (i.hasNext())
636 {
637 velocityEngine.clearProperty((String)i.next());
638 }
639
640 velocityEngine.setExtendedProperties(ConfigurationConverter
641 .getExtendedProperties(velocityConf));
642 velocityEngine.init();
643 velocityConf = null;
644
645 }
646 catch (Exception e)
647 {
648 e.printStackTrace();
649 throw new Exception(
650 "Failed to initialize DefaultVelocityService", e);
651 }
652 }
653
654 }