Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DefaultVelocityService |
|
| 3.0;3 |
1 | package org.apache.fulcrum.template.velocity; | |
2 | ||
3 | ||
4 | /* | |
5 | * Licensed to the Apache Software Foundation (ASF) under one | |
6 | * or more contributor license agreements. See the NOTICE file | |
7 | * distributed with this work for additional information | |
8 | * regarding copyright ownership. The ASF licenses this file | |
9 | * to you under the Apache License, Version 2.0 (the | |
10 | * "License"); you may not use this file except in compliance | |
11 | * with the License. You may obtain a copy of the License at | |
12 | * | |
13 | * http://www.apache.org/licenses/LICENSE-2.0 | |
14 | * | |
15 | * Unless required by applicable law or agreed to in writing, | |
16 | * software distributed under the License is distributed on an | |
17 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
18 | * KIND, either express or implied. See the License for the | |
19 | * specific language governing permissions and limitations | |
20 | * under the License. | |
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 | * This is a Service that can process Velocity templates from within a | |
55 | * Turbine Screen. Here's an example of how you might use it from a | |
56 | * screen:<br> | |
57 | * | |
58 | * <code><pre> | |
59 | * Context context = new VelocityContext(); | |
60 | * context.put("message", "Hello from Turbine!"); | |
61 | * String results = VelocityServiceFacade.handleRequest(context,"HelloWorld.vm"); | |
62 | * </pre></code> | |
63 | * | |
64 | * Character sets map codes to glyphs, while encodings map between | |
65 | * chars/bytes and codes. | |
66 | * <i>bytes -> [encoding] -> charset -> [rendering] -> glyphs</i> | |
67 | * | |
68 | * @author <a href="mailto:epugh@opensourceconnections.com">Eric Pugh</a> | |
69 | * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a> | |
70 | * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a> | |
71 | * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a> | |
72 | * @author <a href="mailto:sean@informage.ent">Sean Legassick</a> | |
73 | * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> | |
74 | * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a> | |
75 | * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a> | |
76 | * @author <a href="mailto:james@jamestaylor.org">James Taylor</a> | |
77 | * @version $Id: DefaultVelocityService.java 535465 2007-05-05 06:58:06Z tv $ | |
78 | */ | |
79 | 0 | public class DefaultVelocityService |
80 | extends BaseTemplateEngineService | |
81 | implements VelocityService, Initializable | |
82 | { | |
83 | /** | |
84 | * The generic resource loader path property in velocity. | |
85 | */ | |
86 | private static final String RESOURCE_LOADER_PATH = | |
87 | ".resource.loader.path"; | |
88 | ||
89 | /** | |
90 | * Default character set to use if not specified by caller. | |
91 | */ | |
92 | private static final String DEFAULT_CHAR_SET = "ISO-8859-1"; | |
93 | ||
94 | /** | |
95 | * The prefix used for URIs which are of type <code>jar</code>. | |
96 | */ | |
97 | private static final String JAR_PREFIX = "jar:"; | |
98 | ||
99 | /** | |
100 | * The prefix used for URIs which are of type <code>absolute</code>. | |
101 | */ | |
102 | private static final String ABSOLUTE_PREFIX = "file://"; | |
103 | ||
104 | /** | |
105 | * The EventCartridge that is used against all contexts | |
106 | */ | |
107 | private EventCartridge eventCartridge; | |
108 | ||
109 | /** | |
110 | * Whether or not to use the eventCartridge. Defaults to true. | |
111 | * Can be used to turn off EC processing. | |
112 | */ | |
113 | 0 | private boolean eventCartridgeEnabled = true; |
114 | ||
115 | ||
116 | // put conf into object to pass to the velocity engine | |
117 | org.apache.commons.configuration.Configuration velocityConf; | |
118 | ||
119 | /** | |
120 | * The VelocityEngine used by the service to merge templates | |
121 | */ | |
122 | private VelocityEngine velocityEngine; | |
123 | ||
124 | /** | |
125 | * @see org.apache.fulcrum.velocity.VelocityService | |
126 | */ | |
127 | public String handleRequest(TemplateContext context, String template) | |
128 | throws TemplateException | |
129 | { | |
130 | 0 | return handleRequest(new ContextAdapter(context), template); |
131 | } | |
132 | ||
133 | /** | |
134 | * @see org.apache.fulcrum.velocity.VelocityService | |
135 | */ | |
136 | public String handleRequest(Context context, String filename) | |
137 | throws TemplateException | |
138 | { | |
139 | 0 | return handleRequest(context, filename, (String)null, null); |
140 | } | |
141 | ||
142 | /** | |
143 | * @see org.apache.fulcrum.velocity.VelocityService | |
144 | */ | |
145 | public String handleRequest(Context context, String filename, | |
146 | String charset, String encoding) | |
147 | throws TemplateException | |
148 | { | |
149 | 0 | String results = null; |
150 | 0 | ByteArrayOutputStream bytes = null; |
151 | ||
152 | try | |
153 | { | |
154 | 0 | bytes = new ByteArrayOutputStream(); |
155 | 0 | charset = decodeRequest(context, filename, bytes, charset, |
156 | encoding); | |
157 | 0 | results = bytes.toString(charset); |
158 | } | |
159 | 0 | catch (Exception e) |
160 | { | |
161 | 0 | renderingError(filename, e); |
162 | } | |
163 | finally | |
164 | { | |
165 | 0 | try |
166 | { | |
167 | 0 | if (bytes != null) |
168 | { | |
169 | 0 | bytes.close(); |
170 | } | |
171 | } | |
172 | 0 | catch (IOException ignored) |
173 | { | |
174 | 0 | } |
175 | 0 | } |
176 | 0 | return results; |
177 | } | |
178 | ||
179 | /** | |
180 | * @see org.apache.fulcrum.template.TemplateEngineService | |
181 | */ | |
182 | public void handleRequest(TemplateContext context, String template, | |
183 | OutputStream outputStream) | |
184 | throws TemplateException | |
185 | { | |
186 | 0 | handleRequest(new ContextAdapter(context), template, outputStream); |
187 | 0 | } |
188 | ||
189 | /** | |
190 | * @see org.apache.fulcrum.velocity.VelocityService | |
191 | */ | |
192 | public void handleRequest(Context context, String filename, | |
193 | OutputStream output) | |
194 | throws TemplateException | |
195 | { | |
196 | 0 | handleRequest(context, filename, output, null, null); |
197 | 0 | } |
198 | ||
199 | /** | |
200 | * @see org.apache.fulcrum.velocity.VelocityService | |
201 | */ | |
202 | public void handleRequest(Context context, String filename, | |
203 | OutputStream output, String charset, | |
204 | String encoding) | |
205 | throws TemplateException | |
206 | { | |
207 | 0 | decodeRequest(context, filename, output, charset, encoding); |
208 | 0 | } |
209 | ||
210 | /** | |
211 | * @see BaseTemplateEngineService#handleRequest(TemplateContext, String, Writer) | |
212 | */ | |
213 | public void handleRequest(TemplateContext context, | |
214 | String template, Writer writer) | |
215 | throws TemplateException | |
216 | { | |
217 | 0 | handleRequest(new ContextAdapter(context), template, writer); |
218 | 0 | } |
219 | ||
220 | /** | |
221 | * @see VelocityService#handleRequest(Context, String, Writer) | |
222 | */ | |
223 | public void handleRequest(Context context, String filename, | |
224 | Writer writer) | |
225 | throws TemplateException | |
226 | { | |
227 | 0 | handleRequest(context, filename, writer, null); |
228 | 0 | } |
229 | ||
230 | /** | |
231 | * @see VelocityService#handleRequest(Context, String, Writer, String) | |
232 | */ | |
233 | public void handleRequest(Context context, String filename, | |
234 | Writer writer, String encoding) | |
235 | throws TemplateException | |
236 | { | |
237 | try | |
238 | { | |
239 | // If the context is not already an instance of | |
240 | // InternalEventContext, wrap it in a VeclocityContext so that | |
241 | // event cartridges will work. Unfortunately there is no interface | |
242 | // that extends both Context and InternalEventContext, so this | |
243 | // is not as clear as it could be. | |
244 | ||
245 | Context eventContext; | |
246 | ||
247 | 0 | if ( context instanceof InternalEventContext ) |
248 | { | |
249 | 0 | eventContext = context; |
250 | } | |
251 | else | |
252 | { | |
253 | 0 | eventContext = new VelocityContext( context ); |
254 | } | |
255 | ||
256 | // Attach the EC to the context | |
257 | 0 | EventCartridge ec = getEventCartridge(); |
258 | 0 | if (ec != null && eventCartridgeEnabled) |
259 | { | |
260 | 0 | ec.attachToContext(eventContext); |
261 | } | |
262 | ||
263 | 0 | if (encoding != null) |
264 | { | |
265 | // Request scoped encoding first supported by Velocity 1.1. | |
266 | 0 | velocityEngine.mergeTemplate(filename, encoding, |
267 | eventContext, writer); | |
268 | } | |
269 | else | |
270 | { | |
271 | 0 | velocityEngine.mergeTemplate(filename, eventContext, writer); |
272 | } | |
273 | } | |
274 | 0 | catch (Exception e) |
275 | { | |
276 | 0 | renderingError(filename, e); |
277 | 0 | } |
278 | 0 | } |
279 | ||
280 | /** | |
281 | * By default, this is true if there is configured event cartridges. | |
282 | * You can disable EC processing if you first disable it and then call | |
283 | * handleRequest. | |
284 | */ | |
285 | public void setEventCartridgeEnabled(boolean value) | |
286 | { | |
287 | 0 | this.eventCartridgeEnabled = value; |
288 | 0 | } |
289 | ||
290 | /** | |
291 | * @return EventCartridge the event cartridge | |
292 | */ | |
293 | public EventCartridge getEventCartridge() | |
294 | { | |
295 | 0 | return eventCartridge; |
296 | } | |
297 | ||
298 | /** | |
299 | * Processes the request and fill in the template with the values | |
300 | * you set in the the supplied Context. Applies the specified | |
301 | * character and template encodings. | |
302 | * | |
303 | * @param context A context to use when evaluating the specified | |
304 | * template. | |
305 | * @param filename The file name of the template. | |
306 | * @param output The stream to which we will write the processed | |
307 | * template as a String. | |
308 | * @return The character set applied to the resulting text. | |
309 | * | |
310 | * @throws ServiceException Any exception trown while processing | |
311 | * will be wrapped into a ServiceException and rethrown. | |
312 | */ | |
313 | private String decodeRequest(Context context, String filename, | |
314 | OutputStream output, String charset, | |
315 | String encoding) | |
316 | throws TemplateException | |
317 | { | |
318 | // TODO: Push this method of getting character set & encoding | |
319 | // from RunData back into Turbine. | |
320 | // charset = ((RunData) data).getCharSet(); | |
321 | // encoding = ((RunData) data).getTemplateEncoding(); | |
322 | ||
323 | 0 | if (charset == null) |
324 | { | |
325 | 0 | charset = DEFAULT_CHAR_SET; |
326 | } | |
327 | ||
328 | 0 | OutputStreamWriter writer = null; |
329 | try | |
330 | { | |
331 | try | |
332 | { | |
333 | 0 | writer = new OutputStreamWriter(output, charset); |
334 | } | |
335 | 0 | catch (Exception e) |
336 | { | |
337 | 0 | renderingError(filename, e); |
338 | 0 | } |
339 | 0 | handleRequest(context, filename, writer, encoding); |
340 | } | |
341 | finally | |
342 | { | |
343 | 0 | try |
344 | { | |
345 | 0 | if (writer != null) |
346 | { | |
347 | 0 | writer.flush(); |
348 | } | |
349 | } | |
350 | 0 | catch (Exception ignored) |
351 | { | |
352 | 0 | } |
353 | 0 | } |
354 | 0 | return charset; |
355 | } | |
356 | ||
357 | /** | |
358 | * Macro to handle rendering errors. | |
359 | * | |
360 | * @param filename The file name of the unrenderable template. | |
361 | * @param e The error. | |
362 | * | |
363 | * @exception ServiceException Thrown every time. Adds additional | |
364 | * information to <code>e</code>. | |
365 | */ | |
366 | private final void renderingError(String filename, Throwable e) | |
367 | throws TemplateException | |
368 | { | |
369 | 0 | String err = "Error rendering Velocity template: " + filename; |
370 | 0 | getLogger().error(err + ": " + e.getMessage()); |
371 | // if the Exception is a MethodInvocationException, the underlying | |
372 | // Exception is likely to be more informative, so rewrap that one. | |
373 | 0 | if (e instanceof MethodInvocationException) |
374 | { | |
375 | 0 | e = ((MethodInvocationException)e).getWrappedThrowable(); |
376 | } | |
377 | ||
378 | 0 | throw new TemplateException(err, e); |
379 | } | |
380 | ||
381 | /** | |
382 | * Find out if a given template exists. Velocity | |
383 | * will do its own searching to determine whether | |
384 | * a template exists or not. | |
385 | * | |
386 | * @param String template to search for | |
387 | * @return boolean | |
388 | */ | |
389 | public boolean templateExists(String template) | |
390 | { | |
391 | 0 | return velocityEngine.templateExists(template); |
392 | } | |
393 | ||
394 | // ---------------- Avalon Lifecycle Methods --------------------- | |
395 | ||
396 | /** | |
397 | * Avalon component lifecycle method | |
398 | */ | |
399 | public void configure(Configuration conf) | |
400 | throws ConfigurationException | |
401 | { | |
402 | // put conf into object to pass to the velocity engine | |
403 | 0 | velocityConf = |
404 | new org.apache.commons.configuration.BaseConfiguration(); | |
405 | 0 | List ecconfig = null; |
406 | 0 | String logPath = null; |
407 | 0 | List templatePathKeys = new ArrayList(); |
408 | 0 | List templatePaths = new ArrayList(); |
409 | ||
410 | if (1==2) | |
411 | { | |
412 | /* ### FIXME: Why is this both setup in a block which | |
413 | ### won't be compiled, and commented out? | |
414 | org.apache.commons.configuration.Configuration oldConf = | |
415 | getConfiguration(); | |
416 | ||
417 | ecconfig = oldConf | |
418 | .getVector("eventCartridge.classes", new Vector(0)); | |
419 | if (ecconfig.isEmpty()) | |
420 | { | |
421 | getLogger().info("No Velocity EventCartridges configured."); | |
422 | } | |
423 | ||
424 | // Now we have to perform a couple of path translations | |
425 | // for our log file and template paths. | |
426 | logPath = | |
427 | oldConf.getString(VelocityEngine.RUNTIME_LOG, null); | |
428 | if (logPath == null || logPath.length() == 0) | |
429 | { | |
430 | String msg = VelocityService.SERVICE_NAME+" runtime log file "+ | |
431 | "is misconfigured: '" + logPath + "' is not a valid log file"; | |
432 | throw new Error(msg); | |
433 | } | |
434 | ||
435 | // Get all the template paths where the velocity | |
436 | // runtime should search for templates and | |
437 | // collect them into a separate vector | |
438 | // to avoid concurrent modification exceptions. | |
439 | for (Iterator i = oldConf.getKeys(); i.hasNext();) | |
440 | { | |
441 | String key = (String) i.next(); | |
442 | if (key.endsWith(RESOURCE_LOADER_PATH)) | |
443 | { | |
444 | templatePathKeys.add(key); | |
445 | templatePaths.add(oldConf.getVector(key)); | |
446 | } | |
447 | } | |
448 | */ | |
449 | } | |
450 | else | |
451 | { | |
452 | // trick compiler | |
453 | if (true) | |
454 | { | |
455 | 0 | 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 | * final Configuration pathConfs = | |
485 | * conf.getChild("event-cartriges", false); | |
486 | * if (pathConfs != null) | |
487 | * { | |
488 | * Configuration[] nameVal = ecConfs.getChildren(); | |
489 | * for (int i=0; i < nameVal.length; i++) | |
490 | * { | |
491 | * String key = nameVal[i].getName(); | |
492 | * String val = nameVal[i].getValue(); | |
493 | * } | |
494 | * } | |
495 | */ | |
496 | } | |
497 | ||
498 | initEventCartridges(ecconfig); | |
499 | ||
500 | // check if path to logfile needs translation to webapp root | |
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 | // Register with the template service. | |
510 | registerConfiguration(conf, "vm"); | |
511 | } | |
512 | ||
513 | /** | |
514 | * This method is responsible for initializing the various Velocity | |
515 | * EventCartridges. You just add a configuration like this: | |
516 | * <code> | |
517 | * services.VelocityService.eventCartridge.classes = org.tigris.scarab.util.ReferenceInsertionFilter | |
518 | * </code> | |
519 | * and list out (comma separated) the list of EC's that you want to | |
520 | * initialize. | |
521 | */ | |
522 | private void initEventCartridges(List ecconfig) | |
523 | throws ConfigurationException | |
524 | { | |
525 | 0 | eventCartridge = new EventCartridge(); |
526 | 0 | Object obj = null; |
527 | 0 | String className = null; |
528 | 0 | for (Iterator i = ecconfig.iterator() ; i.hasNext() ;) |
529 | { | |
530 | 0 | className = (String)i.next(); |
531 | try | |
532 | { | |
533 | 0 | boolean result = false; |
534 | ||
535 | 0 | obj = Class.forName(className).newInstance(); |
536 | ||
537 | 0 | if (obj instanceof ReferenceInsertionEventHandler) |
538 | { | |
539 | 0 | result = getEventCartridge() |
540 | .addEventHandler((ReferenceInsertionEventHandler)obj); | |
541 | } | |
542 | 0 | else if (obj instanceof NullSetEventHandler) |
543 | { | |
544 | 0 | result = getEventCartridge() |
545 | .addEventHandler((NullSetEventHandler)obj); | |
546 | } | |
547 | 0 | else if (obj instanceof MethodExceptionEventHandler) |
548 | { | |
549 | 0 | result = getEventCartridge() |
550 | .addEventHandler((MethodExceptionEventHandler)obj); | |
551 | } | |
552 | 0 | getLogger().info("Added EventCartridge: " + |
553 | obj.getClass().getName() + " : " + result); | |
554 | } | |
555 | 0 | catch (Exception h) |
556 | { | |
557 | 0 | throw new ConfigurationException( |
558 | "Could not configure EventCartridge: " + | |
559 | className, h); | |
560 | 0 | } |
561 | } | |
562 | 0 | } |
563 | ||
564 | /** | |
565 | * Setup the velocity runtime by using a subset of the | |
566 | * Turbine configuration which relates to velocity. | |
567 | * | |
568 | * @exception ConfigurationException For any errors during initialization. | |
569 | */ | |
570 | private void configureTemplatePaths( | |
571 | List templatePathKeys, List templatePaths) | |
572 | { | |
573 | // Loop through all template paths, clear the corresponding | |
574 | // velocity properties and translate them all to the webapp space. | |
575 | 0 | for (int i=0; i<templatePathKeys.size(); i++) |
576 | { | |
577 | 0 | String key = (String) templatePathKeys.get(i); |
578 | 0 | Vector paths = (Vector) templatePaths.get(i); |
579 | 0 | if (paths != null) |
580 | { | |
581 | String entry; | |
582 | 0 | for (Iterator j = paths.iterator(); j.hasNext();) |
583 | { | |
584 | 0 | String path = (String) j.next(); |
585 | 0 | if (path.startsWith(JAR_PREFIX + "file")) |
586 | { | |
587 | // A local jar resource URL path is a bit more | |
588 | // complicated, but we can translate it as well. | |
589 | 0 | int ind = path.indexOf("!/"); |
590 | 0 | if (ind >= 0) |
591 | { | |
592 | 0 | entry = path.substring(ind); |
593 | 0 | path = path.substring(9,ind); |
594 | } | |
595 | else | |
596 | { | |
597 | 0 | entry = "!/"; |
598 | 0 | path = path.substring(9); |
599 | } | |
600 | 0 | path = JAR_PREFIX + "file:" + getRealPath(path) + |
601 | entry; | |
602 | 0 | } |
603 | 0 | else if (path.startsWith(ABSOLUTE_PREFIX)) |
604 | { | |
605 | 0 | path = path.substring (ABSOLUTE_PREFIX.length(), |
606 | path.length()); | |
607 | } | |
608 | 0 | else if (!path.startsWith(JAR_PREFIX)) |
609 | { | |
610 | // But we don't translate remote jar URLs. | |
611 | 0 | path = getRealPath(path); |
612 | } | |
613 | // Put the translated paths back to the configuration. | |
614 | 0 | velocityConf.addProperty(key,path); |
615 | 0 | } |
616 | } | |
617 | } | |
618 | 0 | } |
619 | ||
620 | // ---------------- Avalon Lifecycle Methods --------------------- | |
621 | ||
622 | /** | |
623 | * Avalon component lifecycle method | |
624 | */ | |
625 | public void initialize() | |
626 | throws Exception | |
627 | { | |
628 | try | |
629 | { | |
630 | 0 | velocityEngine = new VelocityEngine(); |
631 | ||
632 | // clear the property to prepare for new value, | |
633 | //is this needed? | |
634 | 0 | Iterator i = velocityConf.getKeys(); |
635 | 0 | while (i.hasNext()) |
636 | { | |
637 | 0 | velocityEngine.clearProperty((String)i.next()); |
638 | } | |
639 | ||
640 | 0 | velocityEngine.setExtendedProperties(ConfigurationConverter |
641 | .getExtendedProperties(velocityConf)); | |
642 | 0 | velocityEngine.init(); |
643 | 0 | velocityConf = null; |
644 | ||
645 | } | |
646 | 0 | catch (Exception e) |
647 | { | |
648 | 0 | e.printStackTrace(); |
649 | 0 | throw new Exception( |
650 | "Failed to initialize DefaultVelocityService", e); | |
651 | 0 | } |
652 | 0 | } |
653 | ||
654 | } |