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