| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| TurbineVelocityService |
|
| 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 | } |