1 package org.apache.turbine.services.freemarker;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57
58 import freemarker.template.CacheEvent;
59 import freemarker.template.CacheListener;
60 import freemarker.template.FileTemplateCache;
61 import freemarker.template.SimpleHash;
62 import freemarker.template.SimpleList;
63 import freemarker.template.Template;
64 import freemarker.template.TemplateServletUtils;
65 import java.io.File;
66 import java.io.IOException;
67 import java.io.PrintWriter;
68 import java.io.StringWriter;
69 import java.util.Enumeration;
70 import java.util.Iterator;
71 import java.util.StringTokenizer;
72 import javax.servlet.ServletRequest;
73 import org.apache.commons.configuration.Configuration;
74 import org.apache.turbine.om.security.Permission;
75 import org.apache.turbine.om.security.Role;
76 import org.apache.turbine.services.InitializationException;
77 import org.apache.turbine.services.TurbineBaseService;
78 import org.apache.turbine.services.servlet.TurbineServlet;
79 import org.apache.turbine.util.DynamicURI;
80 import org.apache.turbine.util.Log;
81 import org.apache.turbine.util.ParameterParser;
82 import org.apache.turbine.util.RunData;
83 import org.apache.turbine.util.TurbineException;
84
85
86 /***
87 * This is a Service that can process FreeMarker templates from within
88 * a Turbine Screen. Here's an example of how you might use it from a
89 * screen:
90 *
91 * <br>
92 *
93 * FreeMarkerService fm = (FreeMarkerService)TurbineServices.getInstance()
94 * .getService(FreeMarkerService.SERVICE_NAME);
95 * SimpleHash context = fm.getContext(data);
96 * context.put("message", "Hello from Turbine!");
97 * String results = fm.handleRequest(context,"helloWorld.wm");
98 * data.getPage().getBody().addElement(results);
99 *
100 * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
101 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
102 * @version $Id: TurbineFreeMarkerService.java,v 1.6 2002/07/16 16:38:13 henning Exp $
103 * @deprecated
104 */
105 public class TurbineFreeMarkerService
106 extends TurbineBaseService
107 implements FreeMarkerService, CacheListener
108 {
109 /*** A cache to store parsed templates. */
110 private FileTemplateCache templateCache;
111
112 /*** The base path prepended to filenames given in arguments. */
113 private String path;
114
115 /***
116 * Constructor.
117 */
118 public TurbineFreeMarkerService()
119 {
120 }
121
122 /***
123 * Called during Turbine.init()
124 *
125 * @param config A ServletConfig.
126 */
127 public void init() throws InitializationException
128 {
129 try
130 {
131 initFreeMarker();
132 setInit(true);
133 }
134 catch (Exception e)
135 {
136 throw new InitializationException(
137 "TurbineFreeMarkerService failed to initialize", e);
138 }
139 }
140
141 /***
142 * Create a context needed by the FreeMarker template. This
143 * method just returns an SimpleHash with the request parameters
144 * copied into a model called request.
145 *
146 * @return SimpleHash which can be used as the model for a
147 * template.
148 */
149 public SimpleHash getContext()
150 {
151 return new SimpleHash();
152 }
153
154 /***
155 * Create a context needed by the FreeMarker template. This
156 * method just returns an SimpleHash with the request parameters
157 * copied into a model called request.
158 *
159 * @param req A ServletRequest.
160 * @return SimpleHash which can be used as the model for a
161 * template.
162 */
163 public SimpleHash getContext(ServletRequest req)
164 {
165 return (SimpleHash)TemplateServletUtils.copyRequest(req);
166 }
167
168 /***
169 * Create a context from the RunData object. Values found in
170 * RunData are copied into the modelRoot under similar names as
171 * they can be found in RunData. e.g. data.serverName,
172 * data.parameters.form_field_name
173 * data.acl.permissions.can_write_file. Some default links are
174 * also made available under links.
175 *
176 * @param data The Turbine RunData object.
177 * @return a SimpleHash populated with RunData data.
178 */
179 public SimpleHash getContext(RunData data)
180 {
181 SimpleHash modelRoot = new SimpleHash();
182 SimpleHash modelLinks = new SimpleHash();
183 modelRoot.put("link", new DynamicURIModel(data));
184 modelRoot.put("links", modelLinks);
185 // modelLinks.put("default", new DynamicURI(data, "FreeMarkerScreen").toString());
186 // modelLinks.put("no_cache", new DynamicURI(data, "FreeMarkerNoCacheScreen").toString());
187 // modelLinks.put("simple", new DynamicURI(data).toString());
188 if (data.getUser() != null && data.getUser().hasLoggedIn())
189 {
190 modelRoot.put("loginout_link", new DynamicURI(data, "Login", "LogoutUser").toString());
191 modelRoot.put("loginout_text", "Logout");
192 }
193 else
194 {
195 modelRoot.put("loginout_link", new DynamicURI(data, "Login").toString());
196 modelRoot.put("loginout_text", "Login");
197 }
198
199 // Add default.
200 SimpleHash modelData = new SimpleHash();
201 SimpleHash modelParameters = new SimpleHash();
202 SimpleHash modelACL = new SimpleHash();
203 SimpleHash modelRoles = new SimpleHash();
204 SimpleHash modelPermissions = new SimpleHash();
205 modelRoot.put("data", modelData);
206 modelData.put("parameters", modelParameters);
207 modelData.put("acl", modelACL);
208 modelACL.put("roles", modelRoles);
209 modelACL.put("permissions", modelPermissions);
210
211 modelData.put("serverName", data.getServerName() );
212 modelData.put("serverPort", String.valueOf(data.getServerPort()) );
213 modelData.put("serverScheme", data.getServerScheme() );
214 modelData.put("scriptName", data.getScriptName() );
215 modelData.put("screen", data.getScreen() );
216 modelData.put("action", data.getAction() );
217 modelData.put("title", data.getTitle() );
218 modelData.put("message", data.getMessage() );
219
220 ParameterParser params = data.getParameters();
221 Enumeration e = params.keys();
222 while (e.hasMoreElements() )
223 {
224 String key = (String)e.nextElement();
225 String[] values = params.getStrings(key);
226 if (values.length==1)
227 {
228 modelParameters.put(key, values[0]);
229 }
230 else
231 {
232 SimpleList listModel = new SimpleList();
233 modelParameters.put(key, listModel);
234 for (int i=0; i<values.length; i++)
235 {
236 listModel.add(values[i]);
237 }
238 }
239 }
240
241 if (data.getACL() != null)
242 {
243 Iterator roles = data.getACL().getRoles().elements();
244 while (roles.hasNext() )
245 {
246 String key = ((Role)roles.next()).getName();
247 modelRoles.put(key, true);
248 }
249 Iterator permissions = data.getACL().getPermissions().elements();
250 while (permissions.hasNext() )
251 {
252 String key = ((Permission)permissions.next()).getName();
253 modelPermissions.put(key, true);
254 }
255 }
256
257 modelRoot.put("setTitle", new SetTitleModel(data));
258 modelRoot.put("addToHead", new AddToHeadModel(data));
259 modelRoot.put("addTemplatesToHead", new AddTemplatesToHeadModel(data));
260 modelRoot.put("setBodyAttributes", new SetBodyAttributesModel(data));
261
262 String templatePath = params.getString("template", null);
263 if (templatePath != null)
264 {
265 StringTokenizer st = new StringTokenizer(templatePath, "/");
266 int max = st.countTokens() - 1;
267 for (int i=0; i<max; i++)
268 {
269 modelRoot.put("template_path_" + (i+1), st.nextToken());
270 }
271 }
272
273 return modelRoot;
274 }
275
276 /***
277 * Process the request and fill in the template with the values
278 * you set in the WebContext.
279 *
280 * @param context A SimpleHash with the context.
281 * @param templateName A String with the filename of the template.
282 * @param cache True if the parsed template should be cached.
283 * @return The processed template as a String.
284 * @throws TurbineException Any exception trown while processing will be
285 * wrapped into a TurbineException and rethrown.
286 */
287 public String handleRequest(SimpleHash context,
288 String filename,
289 boolean cache)
290 throws TurbineException
291 {
292 String results = null;
293 StringWriter sw = null;
294 PrintWriter out = null;
295 try
296 {
297 sw = new StringWriter();
298 out = new PrintWriter(sw);
299 Template template = null;
300 if (cache)
301 {
302 template = getCachedTemplate(filename);
303 }
304 else
305 {
306 template = getNonCachedTemplate(filename);
307 }
308
309 template.process(context, out);
310 results = sw.toString();
311 }
312 catch(Exception e)
313 {
314 throw new TurbineException(
315 "Error encountered processing a template: " + filename, e);
316 }
317 finally
318 {
319 try
320 {
321 if (out != null) out.close();
322 if (sw != null) sw.close();
323 }
324 catch (Exception e) {}
325 }
326 return results;
327 }
328
329 /***
330 * Gets the base path for the FreeMarker templates.
331 *
332 * @return The base path for the FreeMarker templates.
333 */
334 public String getBasePath()
335 {
336 return path;
337 }
338
339 /***
340 * Return a FreeMarker template from the cache. If the template
341 * has not been cached yet, it will be added to the cache.
342 *
343 * @param templateName A String with the name of the template.
344 * @return A Template.
345 */
346 public Template getCachedTemplate(String templateName)
347 {
348 Template template = templateCache.getTemplate(templateName);
349 // if (template == null)
350 // {
351 // Exception e = new Exception("Template " + templateName +
352 // " is not available.");
353 // Log.error ( e );
354 // throw e;
355 // }
356 return template;
357 }
358
359 /***
360 * Return a FreeMarker template. It will not be added to the
361 * cache.
362 *
363 * @param templateName A String with the name of the template.
364 * @return A Template.
365 * @exception IOException, if there was an I/O problem.
366 */
367 public Template getNonCachedTemplate(String templateName)
368 throws IOException
369 {
370 templateName = templateName.replace('/', File.separatorChar);
371 File file = new File(path, templateName);
372 if (file.canRead())
373 {
374 return new Template(file);
375 }
376 // else
377 // {
378 // Exception e = new Exception("Template " + templateName +
379 // " could not be read.");
380 // Log.error ( e );
381 // throw e;
382 // }
383 return null;
384 }
385
386 /***
387 * This method sets up the FreeMarker template cache.
388 *
389 * @param config A ServletConfig.
390 * @exception Exception, a generic exception.
391 */
392 private void initFreeMarker() throws Exception
393 {
394 Configuration config = getConfiguration();
395
396 path = config.getString("templates", "/templates");
397
398 // If possible, transform paths to be webapp root relative.
399 path = TurbineServlet.getRealPath(path);
400
401 // Store the converted path in service properties for Turbine
402 // based providers.
403 config.setProperty("templates", path);
404
405 templateCache = new FileTemplateCache(path);
406 templateCache.addCacheListener(this);
407 templateCache.startAutoUpdate();
408 }
409
410 /***
411 * Method called by templateCache.
412 *
413 * @param e A CacheEvent.
414 */
415 public void cacheUnavailable(CacheEvent e)
416 {
417 Log.error("Cache unavailable: " + e.getException().toString());
418 }
419
420 /***
421 * Method called by templateCache.
422 *
423 * @param e A CacheEvent.
424 */
425 public void elementUpdated(CacheEvent e)
426 {
427 Log.info("Template updated: " + e.getElementName());
428 }
429
430 /***
431 * Method called by templateCache.
432 *
433 * @param e A CacheEvent.
434 */
435 public void elementUpdateFailed(CacheEvent e)
436 {
437 Log.error("Update of template " + e.getElementName() +
438 " failed: " + e.getException().toString());
439 }
440
441 /***
442 * Method called by templateCache.
443 *
444 * @param e A CacheEvent.
445 */
446 public void elementRemoved(CacheEvent e)
447 {
448 Log.warn("Template removed: " + e.getElementName());
449 }
450 }
This page was automatically generated by Maven