1 /* 2 * Copyright (c) 2012-2023, jcabi.com 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 1) Redistributions of source code must retain the above 8 * copyright notice, this list of conditions and the following 9 * disclaimer. 2) Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 3) Neither the name of the jcabi.com nor 13 * the names of its contributors may be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 28 * OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 package com.jcabi.velocity; 31 32 import java.io.PrintWriter; 33 import java.io.StringWriter; 34 import java.util.Map; 35 import org.apache.velocity.Template; 36 import org.apache.velocity.VelocityContext; 37 import org.apache.velocity.app.VelocityEngine; 38 import org.apache.velocity.runtime.RuntimeConstants; 39 import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; 40 41 /** 42 * Velocity page, builder/wrapper around Apache Velocity template. 43 * 44 * <p>The template should be in classpath: 45 * 46 * <pre> String text = new VelocityPage("com/foo/my-template.vm") 47 * .set("name", "John Doe") 48 * .toString();</pre> 49 * 50 * <p>At the moment all logging is forwarded to LOG4J. In Velocity 2.0 there 51 * will be an adapter for SLF4J and we'll use it: {@code Slf4jLogChute}. 52 * 53 * <p>The class is mutable and thread-safe. 54 * 55 * @see <a href="http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html">Velocity User Guide</a> 56 * @see <a href="http://velocity.apache.org/engine/releases/velocity-1.7/developer-guide.html">Velocity Developer Guide</a> 57 * @see <a href="http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/slf4j/Slf4jLogChute.html">Slf4jLogChute</a> 58 * @since 0.1.6 59 */ 60 public final class VelocityPage { 61 62 /** 63 * The engine to use. 64 */ 65 private static final VelocityEngine ENGINE = VelocityPage.init(); 66 67 /** 68 * Name of resource. 69 */ 70 private final transient String name; 71 72 /** 73 * The context. 74 */ 75 private final transient VelocityContext context; 76 77 /** 78 * Public ctor, with absolute resource name in classpath. 79 * @param res Name of resource with template (absolute resource name in 80 * classpath) 81 */ 82 public VelocityPage(final String res) { 83 this.name = res; 84 this.context = new VelocityContext(); 85 } 86 87 /** 88 * Set the name to the value specified. 89 * @param prop Name of the property to set 90 * @param value The value to use 91 * @return This object 92 */ 93 public VelocityPage set(final String prop, final Object value) { 94 synchronized (this.context) { 95 this.context.put(prop, value); 96 } 97 return this; 98 } 99 100 /** 101 * Set all names in one go. 102 * @param args Map of arguments 103 * @return This object 104 * @since 0.8 105 */ 106 public VelocityPage set(final Map<String, Object> args) { 107 synchronized (this.context) { 108 for (final Map.Entry<String, Object> entry : args.entrySet()) { 109 this.context.put(entry.getKey(), entry.getValue()); 110 } 111 } 112 return this; 113 } 114 115 @Override 116 public String toString() { 117 final Template template = 118 VelocityPage.ENGINE.getTemplate(this.name, "UTF-8"); 119 final StringWriter writer = new StringWriter(); 120 template.merge(this.context, new PrintWriter(writer)); 121 return writer.toString(); 122 } 123 124 /** 125 * Create and initialize Velocity engine. 126 * @return The engine to use 127 */ 128 private static VelocityEngine init() { 129 final VelocityEngine engine = new VelocityEngine(); 130 engine.setProperty("resource.loader", "cp"); 131 engine.setProperty( 132 "cp.resource.loader.class", 133 ClasspathResourceLoader.class.getName() 134 ); 135 engine.setProperty( 136 RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, 137 "org.apache.velocity.runtime.log.Log4JLogChute" 138 ); 139 engine.setProperty( 140 "runtime.log.logsystem.log4j.logger", 141 "org.apache.velocity" 142 ); 143 engine.init(); 144 return engine; 145 } 146 147 }