1 /*
2 * $Source$
3 * $Revision$
4 *
5 * Copyright (C) 2000 Tim Joyce
6 *
7 * Part of Melati (http://melati.org), a framework for the rapid
8 * development of clean, maintainable web applications.
9 *
10 * Melati is free software; Permission is granted to copy, distribute
11 * and/or modify this software under the terms either:
12 *
13 * a) the GNU General Public License as published by the Free Software
14 * Foundation; either version 2 of the License, or (at your option)
15 * any later version,
16 *
17 * or
18 *
19 * b) any version of the Melati Software License, as published
20 * at http://melati.org
21 *
22 * You should have received a copy of the GNU General Public License and
23 * the Melati Software License along with this program;
24 * if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26 * GNU General Public License and visit http://melati.org to obtain the
27 * Melati Software License.
28 *
29 * Feel free to contact the Developers of Melati (http://melati.org),
30 * if you would like to work out a different arrangement than the options
31 * outlined here. It is our intention to allow Melati to be used by as
32 * wide an audience as possible.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * Contact details for copyright holder:
40 *
41 * Tim Joyce <timj At paneris.org>
42 */
43
44 package org.melati.template.velocity;
45
46 import java.util.Properties;
47
48 import org.melati.MelatiConfig;
49 import org.melati.poem.AccessPoemException;
50 import org.melati.template.AbstractTemplateEngine;
51 import org.melati.template.TemplateContext;
52 import org.melati.template.TemplateEngine;
53 import org.melati.template.TemplateEngineException;
54 import org.melati.template.NotFoundException;
55 import org.melati.util.MelatiBugMelatiException;
56 import org.melati.util.MelatiStringWriter;
57 import org.melati.util.MelatiWriter;
58
59 import org.apache.velocity.VelocityContext;
60 import org.apache.velocity.app.Velocity;
61 import org.apache.velocity.exception.MethodInvocationException;
62 import org.apache.velocity.exception.ParseErrorException;
63 import org.apache.velocity.exception.ResourceNotFoundException;
64
65 /**
66 * Wrapper for the Velocity Template Engine for use with Melati.
67 */
68 public class VelocityTemplateEngine extends AbstractTemplateEngine implements
69 TemplateEngine {
70
71 /** The name of the engine. */
72 public static final String NAME = "velocity";
73
74 /**
75 * This is the string that is looked for when getInitParameter is called.
76 */
77 // private static final String INIT_PROPS_KEY = "velocity.properties";
78 /**
79 * Constructor.
80 */
81 public VelocityTemplateEngine() {
82 super();
83 }
84
85 /**
86 * Construct a new Engine.
87 *
88 * @param melatiConfig
89 * a {@link MelatiConfig}
90 * @throws TemplateEngineException
91 * if any problem occurs with the engine
92 */
93 public void init(MelatiConfig melatiConfig)
94 throws TemplateEngineException {
95 try {
96 Properties props = loadConfiguration();
97 Velocity.init(props);
98 } catch (Exception e) {
99 throw new TemplateEngineException(e);
100 }
101 }
102
103
104 protected Properties loadConfiguration() {
105 Properties p = new Properties();
106 p.setProperty("resource.loader", "class");
107 p.setProperty("class.resource.loader.class",
108 WebMacroClasspathResourceLoader.class.getName());
109 return p;
110 }
111
112 /**
113 * Get the template context for Velocity.
114 *
115 * @return a {@link TemplateContext}
116 */
117 public TemplateContext getTemplateContext() {
118 VelocityContext context = new VelocityContext();
119 return new VelocityServletTemplateContext(context);
120 }
121
122 /**
123 * The name of the template engine (used to find the templets).
124 *
125 * @return the name of the current configured template engine
126 */
127 @Override
128 public String getName() {
129 return NAME;
130 }
131
132 /**
133 * @return the extension of the templates used by Velocity, including the dot.
134 */
135 @Override
136 public String templateExtension() {
137 return ".vm";
138 }
139
140 /**
141 * Get a template by name.
142 *
143 * @param templateName
144 * the name of the template to find
145 * @return a template
146 * @throws NotFoundException if template not found
147 */
148 @Override
149 public org.melati.template.Template template(String templateName)
150 throws NotFoundException {
151 try {
152 return new VelocityTemplate(templateName);
153 } catch (ResourceNotFoundException e) {
154 if (templateName.endsWith(templateExtension())) {
155 // have a go at loading the webmacro template, and converting it!
156 String webmacroTemplateName = templateName.substring(0, templateName
157 .lastIndexOf(templateExtension()))
158 + ".wm";
159 try {
160 return new VelocityTemplate(webmacroTemplateName);
161 } catch (ParseErrorException p) {
162 throw new MelatiBugMelatiException(
163 "Problem converting a WebMacro template to a Velocity template: " + webmacroTemplateName,
164 p);
165 } catch (ResourceNotFoundException e2) {
166 throw new NotFoundException("Could not find template " + templateName + " or " + webmacroTemplateName);
167 }
168 } else throw new NotFoundException("Could not find template " + templateName);
169 } catch (Exception e) {
170 throw new TemplateEngineException(e);
171 }
172 }
173
174 /**
175 * Get a Template by name and expand it against a context.
176 *
177 * @param out
178 * a {@link MelatiWriter} to output on
179 * @param templateName
180 * the name of the template to expand
181 * @param templateContext
182 * the {@link TemplateContext} to expand the template against
183 * @throws NotFoundException if template not found
184 */
185 public void expandTemplate(MelatiWriter out, String templateName,
186 TemplateContext templateContext) throws NotFoundException {
187 expandTemplate(out, template(templateName), templateContext);
188 }
189
190 /**
191 * Expand a {@link org.melati.template.Template} against the context.
192 *
193 * @param out
194 * a {@link MelatiWriter} to output on
195 * @param template
196 * the {@link org.melati.template.Template} to expand
197 * @param templateContext
198 * the {@link TemplateContext} to expand the template against
199 * @see org.melati.template.TemplateEngine#expandTemplate(org.melati.util.MelatiWriter, org.melati.template.Template, org.melati.template.TemplateContext)
200 */
201 @Override
202 public void expandTemplate(MelatiWriter out,
203 org.melati.template.Template template, TemplateContext templateContext) {
204 try {
205 template.write(out, templateContext);
206 } catch (TemplateEngineException problem) {
207 Exception underlying = problem.subException;
208 if (underlying instanceof AccessPoemException) {
209 throw (AccessPoemException)underlying;
210 }
211 if (underlying instanceof MethodInvocationException) {
212 Throwable caught = ((MethodInvocationException)underlying)
213 .getWrappedThrowable();
214 if (caught instanceof AccessPoemException) {
215 throw (AccessPoemException)caught;
216 }
217 }
218 throw problem;
219 }
220
221 }
222
223 /**
224 * @see org.melati.template.TemplateEngine#expandedTemplate(org.melati.template.Template, org.melati.template.TemplateContext)
225 */
226 @Override
227 public String expandedTemplate(org.melati.template.Template template,
228 TemplateContext templateContext) {
229 MelatiStringWriter s = new MelatiStringWriter();
230 expandTemplate(s, template, templateContext);
231 return s.toString();
232 }
233
234 /**
235 * @see org.melati.template.TemplateEngine#getStringWriter()
236 */
237 @Override
238 public MelatiStringWriter getStringWriter() {
239 return new MelatiStringWriter();
240 }
241
242 /**
243 * Get the underlying engine.
244 *
245 * @see org.melati.template.TemplateEngine#getEngine()
246 * @return null - for velocity there is none.
247 */
248 @Override
249 public Object getEngine() {
250 return null;
251 }
252
253 }