##### Coverage Report - org.apache.turbine.services.velocity.TurbineVelocityService

Classes in this File | Line Coverage | Branch Coverage | Complexity
TurbineVelocityService |
78% | 118/150
62% | 35/56
| 3.235294117647059;3,235

1 |  |
     package org.apache.turbine.services.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.IOException;
26 |  |
     import java.io.OutputStream;
27 |  |
     import java.io.OutputStreamWriter;
28 |  |
     import java.io.Writer;
29 |  |
     import java.util.Iterator;
30 |  |
     import java.util.List;
31 |  |
32 |  |
     import org.apache.commons.collections.ExtendedProperties;
33 |  |
     import org.apache.commons.configuration.Configuration;
34 |  |
     import org.apache.commons.lang.StringUtils;
35 |  |
     import org.apache.commons.logging.Log;
36 |  |
     import org.apache.commons.logging.LogFactory;
37 |  |
     import org.apache.turbine.Turbine;
38 |  |
     import org.apache.turbine.pipeline.PipelineData;
39 |  |
     import org.apache.turbine.services.InitializationException;
40 |  |
     import org.apache.turbine.services.pull.PullService;
41 |  |
     import org.apache.turbine.services.pull.TurbinePull;
42 |  |
     import org.apache.turbine.services.template.BaseTemplateEngineService;
43 |  |
     import org.apache.turbine.util.RunData;
44 |  |
     import org.apache.turbine.util.TurbineException;
45 |  |
     import org.apache.velocity.VelocityContext;
46 |  |
     import org.apache.velocity.app.Velocity;
47 |  |
     import org.apache.velocity.app.event.EventCartridge;
48 |  |
     import org.apache.velocity.app.event.MethodExceptionEventHandler;
49 |  |
     import org.apache.velocity.context.Context;
50 |  |
     import org.apache.velocity.runtime.log.Log4JLogChute;
51 |  |
52 |  |
     /**
53 |  |
      * This is a Service that can process Velocity templates from within a
54 |  |
      * Turbine Screen. It is used in conjunction with the templating service
55 |  |
      * as a Templating Engine for templates ending in "vm". It registers
56 |  |
      * itself as translation engine with the template service and gets
57 |  |
      * accessed from there. After configuring it in your properties, it
58 |  |
      * should never be necessary to call methods from this service directly.
59 |  |
      *
60 |  |
      * Here's an example of how you might use it from a
61 |  |
      * screen:<br>
62 |  |
      *
63 |  |
      * <code>
64 |  |
      * Context context = TurbineVelocity.getContext(data);<br>
65 |  |
      * context.put("message", "Hello from Turbine!");<br>
66 |  |
      * String results = TurbineVelocity.handleRequest(context,"helloWorld.vm");<br>
67 |  |
      * data.getPage().getBody().addElement(results);<br>
68 |  |
      * </code>
69 |  |
      *
70 |  |
      * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
71 |  |
      * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
72 |  |
      * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
73 |  |
      * @author <a href="mailto:sean@informage.ent">Sean Legassick</a>
74 |  |
      * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
75 |  |
      * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
76 |  |
      * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
77 |  |
      * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
78 |  |
      * @version $Id: TurbineVelocityService.java 1073172 2011-02-21 22:16:51Z tv $
79 |  |
      */
80 | 42 |
     public class TurbineVelocityService
81 |  |
             extends BaseTemplateEngineService
82 |  |
             implements VelocityService,
83 |  |
                        MethodExceptionEventHandler
84 |  |
     {
85 |  |
         /** The generic resource loader path property in velocity.*/
86 |  |
         private static final String RESOURCE_LOADER_PATH = ".resource.loader.path";
87 |  |
88 |  |
         /** Default character set to use if not specified in the RunData object. */
89 |  |
         private static final String DEFAULT_CHAR_SET = "ISO-8859-1";
90 |  |
91 |  |
         /** The prefix used for URIs which are of type <code>jar</code>. */
92 |  |
         private static final String JAR_PREFIX = "jar:";
93 |  |
94 |  |
         /** The prefix used for URIs which are of type <code>absolute</code>. */
95 |  |
         private static final String ABSOLUTE_PREFIX = "file://";
96 |  |
97 |  |
         /** Logging */
98 | 42 |
         private static Log log = LogFactory.getLog(TurbineVelocityService.class);
99 |  |
100 |  |
         /** Is the pullModelActive? */
101 | 42 |
         private boolean pullModelActive = false;
102 |  |
103 |  |
         /** Shall we catch Velocity Errors and report them in the log file? */
104 | 42 |
         private boolean catchErrors = true;
105 |  |
106 |  |
         /** Internal Reference to the pull Service */
107 | 42 |
         private PullService pullService = null;
108 |  |
109 |  |
110 |  |
         /**
111 |  |
          * Load all configured components and initialize them. This is
112 |  |
          * a zero parameter variant which queries the Turbine Servlet
113 |  |
          * for its config.
114 |  |
          *
115 |  |
          * @throws InitializationException Something went wrong in the init
116 |  |
          *         stage
117 |  |
          */
118 |  |
         @Override
119 |  |
         public void init()
120 |  |
                 throws InitializationException
121 |  |
         {
122 |  |
             try
123 |  |
             {
124 | 62 |
                 initVelocity();
125 |  |
126 |  |
                 // We can only load the Pull Model ToolBox
127 |  |
                 // if the Pull service has been listed in the TR.props
128 |  |
                 // and the service has successfully been initialized.
129 | 62 |
                 if (TurbinePull.isRegistered())
130 |  |
                 {
131 | 62 |
                     pullModelActive = true;
132 |  |
133 | 62 |
                     pullService = TurbinePull.getService();
134 |  |
135 | 62 |
                     log.debug("Activated Pull Tools");
136 |  |
                 }
137 |  |
138 |  |
                 // Register with the template service.
139 | 62 |
                 registerConfiguration(VelocityService.VELOCITY_EXTENSION);
140 |  |
141 | 62 |
                 setInit(true);
142 |  |
             }
143 | 0 |
             catch (Exception e)
144 |  |
             {
145 | 0 |
                 throw new InitializationException(
146 |  |
                     "Failed to initialize TurbineVelocityService", e);
147 | 62 |
             }
148 | 62 |
         }
149 |  |
150 |  |
         /**
151 |  |
          * Create a Context object that also contains the globalContext.
152 |  |
          *
153 |  |
          * @return A Context object.
154 |  |
          */
155 |  |
         public Context getContext()
156 |  |
         {
157 | 16 |
             Context globalContext =
158 |  |
                     pullModelActive ? pullService.getGlobalContext() : null;
159 |  |
160 | 16 |
             Context ctx = new VelocityContext(globalContext);
161 | 16 |
             return ctx;
162 |  |
         }
163 |  |
164 |  |
         /**
165 |  |
          * This method returns a new, empty Context object.
166 |  |
          *
167 |  |
          * @return A Context Object.
168 |  |
          */
169 |  |
         public Context getNewContext()
170 |  |
         {
171 | 62 |
             Context ctx = new VelocityContext();
172 |  |
173 |  |
             // Attach an Event Cartridge to it, so we get exceptions
174 |  |
             // while invoking methods from the Velocity Screens
175 | 62 |
             EventCartridge ec = new EventCartridge();
176 | 62 |
             ec.addEventHandler(this);
177 | 62 |
             ec.attachToContext(ctx);
178 | 62 |
             return ctx;
179 |  |
         }
180 |  |
181 |  |
         /**
182 |  |
          * MethodException Event Cartridge handler
183 |  |
          * for Velocity.
184 |  |
          *
185 |  |
          * It logs an execption thrown by the velocity processing
186 |  |
          * on error level into the log file
187 |  |
          *
188 |  |
          * @param clazz The class that threw the exception
189 |  |
          * @param method The Method name that threw the exception
190 |  |
          * @param e The exception that would've been thrown
191 |  |
          * @return A valid value to be used as Return value
192 |  |
          * @throws Exception We threw the exception further up
193 |  |
          */
194 |  |
         public Object methodException(Class clazz, String method, Exception e)
195 |  |
                 throws Exception
196 |  |
         {
197 | 0 |
             log.error("Class " + clazz.getName() + "." + method + " threw Exception", e);
198 |  |
199 | 0 |
             if (!catchErrors)
200 |  |
             {
201 | 0 |
                 throw e;
202 |  |
             }
203 |  |
204 | 0 |
             return "[Turbine caught an Error here. Look into the turbine.log for further information]";
205 |  |
         }
206 |  |
207 |  |
         /**
208 |  |
          * Create a Context from the RunData object.  Adds a pointer to
209 |  |
          * the RunData object to the VelocityContext so that RunData
210 |  |
          * is available in the templates.
211 |  |
          * @deprecated. Use PipelineData version.
212 |  |
          * @param data The Turbine RunData object.
213 |  |
          * @return A clone of the WebContext needed by Velocity.
214 |  |
          */
215 |  |
         public Context getContext(RunData data)
216 |  |
         {
217 |  |
             // Attempt to get it from the data first.  If it doesn't
218 |  |
             // exist, create it and then stuff it into the data.
219 | 18 |
             Context context = (Context)
220 |  |
                 data.getTemplateInfo().getTemplateContext(VelocityService.CONTEXT);
221 |  |
222 | 18 |
             if (context == null)
223 |  |
             {
224 | 10 |
                 context = getContext();
225 | 10 |
                 context.put(VelocityService.RUNDATA_KEY, data);
226 |  |
227 | 10 |
                 if (pullModelActive)
228 |  |
                 {
229 |  |
                     // Populate the toolbox with request scope, session scope
230 |  |
                     // and persistent scope tools (global tools are already in
231 |  |
                     // the toolBoxContent which has been wrapped to construct
232 |  |
                     // this request-specific context).
233 | 10 |
                     pullService.populateContext(context, data);
234 |  |
                 }
235 |  |
236 | 10 |
                 data.getTemplateInfo().setTemplateContext(
237 |  |
                     VelocityService.CONTEXT, context);
238 |  |
             }
239 | 18 |
             return context;
240 |  |
         }
241 |  |
242 |  |
         /**
243 |  |
          * Create a Context from the PipelineData object.  Adds a pointer to
244 |  |
          * the RunData object to the VelocityContext so that RunData
245 |  |
          * is available in the templates.
246 |  |
          *
247 |  |
          * @param data The Turbine RunData object.
248 |  |
          * @return A clone of the WebContext needed by Velocity.
249 |  |
          */
250 |  |
         public Context getContext(PipelineData pipelineData)
251 |  |
         {
252 |  |
             //Map runDataMap = (Map)pipelineData.get(RunData.class);
253 | 40 |
             RunData data = (RunData)pipelineData;
254 |  |
             // Attempt to get it from the data first.  If it doesn't
255 |  |
             // exist, create it and then stuff it into the data.
256 | 32 |
             Context context = (Context)
257 |  |
                 data.getTemplateInfo().getTemplateContext(VelocityService.CONTEXT);
258 |  |
259 | 32 |
             if (context == null)
260 |  |
             {
261 | 6 |
                 context = getContext();
262 | 6 |
                 context.put(VelocityService.RUNDATA_KEY, data);
263 |  |
                 // we will add both data and pipelineData to the context.
264 | 6 |
                 context.put(VelocityService.PIPELINEDATA_KEY, pipelineData);
265 |  |
266 | 6 |
                 if (pullModelActive)
267 |  |
                 {
268 |  |
                     // Populate the toolbox with request scope, session scope
269 |  |
                     // and persistent scope tools (global tools are already in
270 |  |
                     // the toolBoxContent which has been wrapped to construct
271 |  |
                     // this request-specific context).
272 | 6 |
                     pullService.populateContext(context, pipelineData);
273 |  |
                 }
274 |  |
275 | 6 |
                 data.getTemplateInfo().setTemplateContext(
276 |  |
                     VelocityService.CONTEXT, context);
277 |  |
             }
278 | 32 |
             return context;
279 |  |
         }
280 |  |
281 |  |
         /**
282 |  |
          * Process the request and fill in the template with the values
283 |  |
          * you set in the Context.
284 |  |
          *
285 |  |
          * @param context  The populated context.
286 |  |
          * @param filename The file name of the template.
287 |  |
          * @return The process template as a String.
288 |  |
          *
289 |  |
          * @throws TurbineException Any exception trown while processing will be
290 |  |
          *         wrapped into a TurbineException and rethrown.
291 |  |
          */
292 |  |
         public String handleRequest(Context context, String filename)
293 |  |
             throws TurbineException
294 |  |
         {
295 | 2 |
             String results = null;
296 | 2 |
             ByteArrayOutputStream bytes = null;
297 | 2 |
             OutputStreamWriter writer = null;
298 | 2 |
             String charset = getCharSet(context);
299 |  |
300 |  |
             try
301 |  |
             {
302 | 2 |
                 bytes = new ByteArrayOutputStream();
303 |  |
304 | 2 |
                 writer = new OutputStreamWriter(bytes, charset);
305 |  |
306 | 2 |
                 executeRequest(context, filename, writer);
307 | 2 |
                 writer.flush();
308 | 2 |
                 results = bytes.toString(charset);
309 |  |
             }
310 | 0 |
             catch (Exception e)
311 |  |
             {
312 | 0 |
                 renderingError(filename, e);
313 |  |
             }
314 |  |
             finally
315 |  |
             {
316 | 0 |
                 try
317 |  |
                 {
318 | 2 |
                     if (bytes != null)
319 |  |
                     {
320 | 2 |
                         bytes.close();
321 |  |
                     }
322 |  |
                 }
323 | 0 |
                 catch (IOException ignored)
324 |  |
                 {
325 |  |
                     // do nothing.
326 | 2 |
                 }
327 | 0 |
             }
328 | 2 |
             return results;
329 |  |
         }
330 |  |
331 |  |
         /**
332 |  |
          * Process the request and fill in the template with the values
333 |  |
          * you set in the Context.
334 |  |
          *
335 |  |
          * @param context A Context.
336 |  |
          * @param filename A String with the filename of the template.
337 |  |
          * @param output A OutputStream where we will write the process template as
338 |  |
          * a String.
339 |  |
          *
340 |  |
          * @throws TurbineException Any exception trown while processing will be
341 |  |
          *         wrapped into a TurbineException and rethrown.
342 |  |
          */
343 |  |
         public void handleRequest(Context context, String filename,
344 |  |
                                   OutputStream output)
345 |  |
                 throws TurbineException
346 |  |
         {
347 | 2 |
             String charset  = getCharSet(context);
348 | 2 |
             OutputStreamWriter writer = null;
349 |  |
350 |  |
             try
351 |  |
             {
352 | 2 |
                 writer = new OutputStreamWriter(output, charset);
353 | 2 |
                 executeRequest(context, filename, writer);
354 |  |
             }
355 | 0 |
             catch (Exception e)
356 |  |
             {
357 | 0 |
                 renderingError(filename, e);
358 |  |
             }
359 |  |
             finally
360 |  |
             {
361 | 0 |
                 try
362 |  |
                 {
363 | 2 |
                     if (writer != null)
364 |  |
                     {
365 | 2 |
                         writer.flush();
366 |  |
                     }
367 |  |
                 }
368 | 0 |
                 catch (Exception ignored)
369 |  |
                 {
370 |  |
                     // do nothing.
371 | 2 |
                 }
372 | 0 |
             }
373 | 2 |
         }
374 |  |
375 |  |
376 |  |
         /**
377 |  |
          * Process the request and fill in the template with the values
378 |  |
          * you set in the Context.
379 |  |
          *
380 |  |
          * @param context A Context.
381 |  |
          * @param filename A String with the filename of the template.
382 |  |
          * @param writer A Writer where we will write the process template as
383 |  |
          * a String.
384 |  |
          *
385 |  |
          * @throws TurbineException Any exception trown while processing will be
386 |  |
          *         wrapped into a TurbineException and rethrown.
387 |  |
          */
388 |  |
         public void handleRequest(Context context, String filename, Writer writer)
389 |  |
                 throws TurbineException
390 |  |
         {
391 |  |
             try
392 |  |
             {
393 | 0 |
                 executeRequest(context, filename, writer);
394 |  |
             }
395 | 0 |
             catch (Exception e)
396 |  |
             {
397 | 0 |
                 renderingError(filename, e);
398 |  |
             }
399 |  |
             finally
400 |  |
             {
401 | 0 |
                 try
402 |  |
                 {
403 | 0 |
                     if (writer != null)
404 |  |
                     {
405 | 0 |
                         writer.flush();
406 |  |
                     }
407 |  |
                 }
408 | 0 |
                 catch (Exception ignored)
409 |  |
                 {
410 |  |
                     // do nothing.
411 | 0 |
                 }
412 | 0 |
             }
413 | 0 |
         }
414 |  |
415 |  |
416 |  |
         /**
417 |  |
          * Process the request and fill in the template with the values
418 |  |
          * you set in the Context. Apply the character and template
419 |  |
          * encodings from RunData to the result.
420 |  |
          *
421 |  |
          * @param context A Context.
422 |  |
          * @param filename A String with the filename of the template.
423 |  |
          * @param writer A OutputStream where we will write the process template as
424 |  |
          * a String.
425 |  |
          *
426 |  |
          * @throws Exception A problem occured.
427 |  |
          */
428 |  |
         private void executeRequest(Context context, String filename,
429 |  |
                                     Writer writer)
430 |  |
                 throws Exception
431 |  |
         {
432 | 4 |
             String encoding = getEncoding(context);
433 |  |
434 | 4 |
             if (encoding == null)
435 |  |
             {
436 | 4 |
               encoding = DEFAULT_CHAR_SET;
437 |  |
             }
438 | 4 |
                     Velocity.mergeTemplate(filename, encoding, context, writer);
439 | 4 |
         }
440 |  |
441 |  |
         /**
442 |  |
          * Retrieve the required charset from the Turbine RunData in the context
443 |  |
          *
444 |  |
          * @param context A Context.
445 |  |
          * @return The character set applied to the resulting String.
446 |  |
          */
447 |  |
         private String getCharSet(Context context)
448 |  |
         {
449 | 4 |
             String charset = null;
450 |  |
451 | 4 |
             Object data = context.get(VelocityService.RUNDATA_KEY);
452 | 4 |
             if ((data != null) && (data instanceof RunData))
453 |  |
             {
454 | 4 |
                 charset = ((RunData) data).getCharSet();
455 |  |
             }
456 |  |
457 | 4 |
             return (StringUtils.isEmpty(charset)) ? DEFAULT_CHAR_SET : charset;
458 |  |
         }
459 |  |
460 |  |
         /**
461 |  |
          * Retrieve the required encoding from the Turbine RunData in the context
462 |  |
          *
463 |  |
          * @param context A Context.
464 |  |
          * @return The encoding applied to the resulting String.
465 |  |
          */
466 |  |
         private String getEncoding(Context context)
467 |  |
         {
468 | 4 |
             String encoding = null;
469 |  |
470 | 4 |
             Object data = context.get(VelocityService.RUNDATA_KEY);
471 | 4 |
             if ((data != null) && (data instanceof RunData))
472 |  |
             {
473 | 4 |
                 encoding = ((RunData) data).getTemplateEncoding();
474 |  |
             }
475 |  |
476 | 4 |
             return encoding;
477 |  |
         }
478 |  |
479 |  |
         /**
480 |  |
          * Macro to handle rendering errors.
481 |  |
          *
482 |  |
          * @param filename The file name of the unrenderable template.
483 |  |
          * @param e        The error.
484 |  |
          *
485 |  |
          * @exception TurbineException Thrown every time.  Adds additional
486 |  |
          *                             information to <code>e</code>.
487 |  |
          */
488 |  |
         private static final void renderingError(String filename, Exception e)
489 |  |
                 throws TurbineException
490 |  |
         {
491 | 0 |
             String err = "Error rendering Velocity template: " + filename;
492 | 0 |
             log.error(err, e);
493 | 0 |
             throw new TurbineException(err, e);
494 |  |
         }
495 |  |
496 |  |
         /**
497 |  |
          * Setup the velocity runtime by using a subset of the
498 |  |
          * Turbine configuration which relates to velocity.
499 |  |
          *
500 |  |
          * @exception Exception An Error occured.
501 |  |
          */
502 |  |
         private synchronized void initVelocity()
503 |  |
             throws Exception
504 |  |
         {
505 |  |
             // Get the configuration for this service.
506 | 62 |
             Configuration conf = getConfiguration();
507 |  |
508 | 62 |
             catchErrors = conf.getBoolean(CATCH_ERRORS_KEY, CATCH_ERRORS_DEFAULT);
509 |  |
510 | 62 |
             conf.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
511 |  |
                     Log4JLogChute.class.getName());
512 | 62 |
             conf.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM
513 |  |
                     + ".log4j.category", "velocity");
514 |  |
515 | 62 |
             Velocity.setExtendedProperties(createVelocityProperties(conf));
516 | 62 |
             Velocity.init();
517 | 62 |
         }
518 |  |
519 |  |
520 |  |
         /**
521 |  |
          * This method generates the Extended Properties object necessary
522 |  |
          * for the initialization of Velocity. It also converts the various
523 |  |
          * resource loader pathes into webapp relative pathes. It also
524 |  |
          *
525 |  |
          * @param conf The Velocity Service configuration
526 |  |
          *
527 |  |
          * @return An ExtendedProperties Object for Velocity
528 |  |
          *
529 |  |
          * @throws Exception If a problem occured while converting the properties.
530 |  |
          */
531 |  |
532 |  |
         public ExtendedProperties createVelocityProperties(Configuration conf)
533 |  |
                 throws Exception
534 |  |
         {
535 |  |
             // This bugger is public, because we want to run some Unit tests
536 |  |
             // on it.
537 |  |
538 | 64 |
             ExtendedProperties veloConfig = new ExtendedProperties();
539 |  |
540 |  |
             // Fix up all the template resource loader pathes to be
541 |  |
             // webapp relative. Copy all other keys verbatim into the
542 |  |
             // veloConfiguration.
543 |  |
544 | 64 |
             for (Iterator i = conf.getKeys(); i.hasNext();)
545 |  |
             {
546 | 1168 |
                 String key = (String) i.next();
547 | 1168 |
                 if (!key.endsWith(RESOURCE_LOADER_PATH))
548 |  |
                 {
549 | 960 |
                     Object value = conf.getProperty(key);
550 | 960 |
                     if (value instanceof List) {
551 | 0 |
                         for (Iterator itr = ((List)value).iterator(); itr.hasNext();)
552 |  |
                         {
553 | 0 |
                             veloConfig.addProperty(key, itr.next());
554 |  |
                         }
555 |  |
                     }
556 |  |
                     else
557 |  |
                     {
558 | 960 |
                         veloConfig.addProperty(key, value);
559 |  |
                     }
560 | 960 |
                     continue; // for()
561 |  |
                 }
562 |  |
563 | 208 |
                 List paths = conf.getList(key, null);
564 | 208 |
                 if (paths == null)
565 |  |
                 {
566 |  |
                     // We don't copy this into VeloProperties, because
567 |  |
                     // null value is unhealthy for the ExtendedProperties object...
568 | 0 |
                     continue; // for()
569 |  |
                 }
570 |  |
571 | 208 |
                 Velocity.clearProperty(key);
572 |  |
573 |  |
                 // Translate the supplied pathes given here.
574 |  |
                 // the following three different kinds of
575 |  |
                 // pathes must be translated to be webapp-relative
576 |  |
                 //
577 |  |
                 // jar:file://path-component!/entry-component
578 |  |
                 // file://path-component
579 |  |
                 // path/component
580 | 208 |
                 for (Iterator j = paths.iterator(); j.hasNext();)
581 |  |
                 {
582 | 208 |
                     String path = (String) j.next();
583 |  |
584 | 208 |
                     log.debug("Translating " + path);
585 |  |
586 | 208 |
                     if (path.startsWith(JAR_PREFIX))
587 |  |
                     {
588 |  |
                         // skip jar: -> 4 chars
589 | 72 |
                         if (path.substring(4).startsWith(ABSOLUTE_PREFIX))
590 |  |
                         {
591 |  |
                             // We must convert up to the jar path separator
592 | 54 |
                             int jarSepIndex = path.indexOf("!/");
593 |  |
594 |  |
                             // jar:file:// -> skip 11 chars
595 | 54 |
                             path = (jarSepIndex < 0)
596 |  |
                                 ? Turbine.getRealPath(path.substring(11))
597 |  |
                             // Add the path after the jar path separator again to the new url.
598 |  |
                                 : (Turbine.getRealPath(path.substring(11, jarSepIndex)) + path.substring(jarSepIndex));
599 |  |
600 | 54 |
                             log.debug("Result (absolute jar path): " + path);
601 | 54 |
                         }
602 |  |
                     }
603 | 136 |
                     else if(path.startsWith(ABSOLUTE_PREFIX))
604 |  |
                     {
605 |  |
                         // skip file:// -> 7 chars
606 | 18 |
                         path = Turbine.getRealPath(path.substring(7));
607 |  |
608 | 18 |
                         log.debug("Result (absolute URL Path): " + path);
609 |  |
                     }
610 |  |
                     // Test if this might be some sort of URL that we haven't encountered yet.
611 | 118 |
                     else if(path.indexOf("://") < 0)
612 |  |
                     {
613 | 100 |
                         path = Turbine.getRealPath(path);
614 |  |
615 | 100 |
                         log.debug("Result (normal fs reference): " + path);
616 |  |
                     }
617 |  |
618 | 208 |
                     log.debug("Adding " + key + " -> " + path);
619 |  |
                     // Re-Add this property to the configuration object
620 | 208 |
                     veloConfig.addProperty(key, path);
621 | 208 |
                 }
622 | 208 |
             }
623 | 64 |
             return veloConfig;
624 |  |
         }
625 |  |
626 |  |
         /**
627 |  |
          * Find out if a given template exists. Velocity
628 |  |
          * will do its own searching to determine whether
629 |  |
          * a template exists or not.
630 |  |
          *
631 |  |
          * @param template String template to search for
632 |  |
          * @return True if the template can be loaded by Velocity
633 |  |
          */
634 |  |
         @Override
635 |  |
         public boolean templateExists(String template)
636 |  |
         {
637 | 84 |
             return Velocity.resourceExists(template);
638 |  |
         }
639 |  |
640 |  |
         /**
641 |  |
          * Performs post-request actions (releases context
642 |  |
          * tools back to the object pool).
643 |  |
          *
644 |  |
          * @param context a Velocity Context
645 |  |
          */
646 |  |
         public void requestFinished(Context context)
647 |  |
         {
648 | 2 |
             if (pullModelActive)
649 |  |
             {
650 | 2 |
                 pullService.releaseTools(context);
651 |  |
             }
652 | 2 |
         }
653 |  |
     }