KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jpublish > view > velocity > VelocityViewRenderer


1 /*--
2
3  Copyright (C) 2001-2003 Aetrion LLC.
4  All rights reserved.
5  
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions
8  are met:
9  
10  1. Redistributions of source code must retain the above copyright
11     notice, this list of conditions, and the following disclaimer.
12  
13  2. Redistributions in binary form must reproduce the above copyright
14     notice, this list of conditions, and the disclaimer that follows
15     these conditions in the documentation and/or other materials
16     provided with the distribution.
17
18  3. The name "JPublish" must not be used to endorse or promote products
19     derived from this software without prior written permission. For
20     written permission, please contact info@aetrion.com.
21  
22  4. Products derived from this software may not be called "JPublish", nor
23     may "JPublish" appear in their name, without prior written permission
24     from Aetrion LLC (info@aetrion.com).
25  
26  In addition, the authors of this software request (but do not require)
27  that you include in the end-user documentation provided with the
28  redistribution and/or in the software itself an acknowledgement equivalent
29  to the following:
30      "This product includes software developed by
31       Aetrion LLC (http://www.aetrion.com/)."
32
33  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
34  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
35  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36  DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
37  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
39  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
41  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
42  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43  POSSIBILITY OF SUCH DAMAGE.
44
45  For more information on JPublish, please see <http://www.jpublish.org/>.
46  
47  */

48
49 package org.jpublish.view.velocity;
50
51 import java.io.*;
52 import java.util.Properties JavaDoc;
53
54 import com.anthonyeden.lib.config.Configuration;
55 import com.anthonyeden.lib.config.ConfigurationException;
56 import com.anthonyeden.lib.util.IOUtilities;
57 import com.anthonyeden.lib.util.MessageUtilities;
58 import org.apache.commons.collections.ExtendedProperties;
59 import org.apache.commons.logging.Log;
60 import org.apache.commons.logging.LogFactory;
61 import org.apache.commons.vfs.FileContent;
62 import org.apache.commons.vfs.FileObject;
63 import org.apache.commons.vfs.FileSystemException;
64 import org.apache.commons.vfs.FileSystemManager;
65 import org.apache.velocity.app.VelocityEngine;
66 import org.apache.velocity.runtime.RuntimeConstants;
67 import org.jpublish.JPublishEngine;
68 import org.jpublish.JPublishRuntimeException;
69 import org.jpublish.RequestContext;
70 import org.jpublish.page.Page;
71 import org.jpublish.view.AbstractViewRenderer;
72 import org.jpublish.view.ViewRenderException;
73
74 /**
75  * ViewRenderer which uses the Velocity template engine from the Apache Jakarta group to render content.
76  *
77  * @author Anthony Eden
78  * @since 2.0
79  */

80
81 public class VelocityViewRenderer extends AbstractViewRenderer {
82
83     private static final String JavaDoc DEFAULT_PROPERTIES_PATH =
84             "WEB-INF/velocity.properties";
85
86     // Here are the names of Velocity 1.2 properties that can contains paths.
87
/*
88     private static final String[] velocityKeys = {
89         "runtime.log", "file.resource.loader.path", "velocimacro.library"
90     };
91     */

92     private Log log = LogFactory.getLog(VelocityViewRenderer.class);
93     private VelocityEngine velocityEngine = new VelocityEngine();
94     private Properties JavaDoc velocityProperties = new Properties JavaDoc();
95
96     private boolean resourceCacheEnabled = false;
97     private int resourceCacheInterval = 2;
98
99     /**
100      * Return true if the resource cache is enabled.
101      *
102      * @return True if the resource cache is enabled
103      */

104
105     public boolean isResourceCacheEnabled() {
106         return resourceCacheEnabled;
107     }
108
109     /**
110      * Set to true to enable resource caching.
111      *
112      * @param resourceCacheEnabled True to enable resource caching
113      */

114
115     public void setResourceCacheEnabled(boolean resourceCacheEnabled) {
116         if (log.isDebugEnabled()) {
117             log.debug("Resource cache enabled: " + resourceCacheEnabled);
118         }
119         this.resourceCacheEnabled = resourceCacheEnabled;
120     }
121
122     /**
123      * Set to "true" to enable resource caching.
124      *
125      * @param resourceCacheEnabled "true" to enable resource caching
126      */

127
128     public void setResourceCacheEnabled(String JavaDoc resourceCacheEnabled) {
129         setResourceCacheEnabled("true".equals(resourceCacheEnabled));
130     }
131
132     /**
133      * Get the resource cache interval. This value is used to determine how often the resource cache should be checked
134      * for modified templates.
135      *
136      * @return The resource cache interval
137      */

138
139     public int getResourceCacheInterval() {
140         return resourceCacheInterval;
141     }
142
143     /**
144      * Set the resource cache interval. This value is used to determine how often the resource cache should be checked
145      * for modified templates.
146      *
147      * @param resourceCacheInterval The new resource cache interval
148      */

149
150     public void setResourceCacheInterval(int resourceCacheInterval) {
151         if (log.isDebugEnabled()) {
152             log.debug("Resource cache interval: " + resourceCacheInterval);
153         }
154         this.resourceCacheInterval = resourceCacheInterval;
155     }
156
157     /**
158      * Set the resource cache interval. This value is used to determine how often the resource cache should be checked
159      * for modified templates.
160      *
161      * @param resourceCacheInterval The new resource cache interval
162      */

163
164     public void setResourceCacheInterval(String JavaDoc resourceCacheInterval) {
165         if (resourceCacheInterval != null) {
166             setResourceCacheInterval(Integer.parseInt(resourceCacheInterval));
167         }
168     }
169
170     /**
171      * Initialize the ViewRenderer.
172      */

173
174     public void init() {
175         try {
176             log.debug("init()");
177              
178             // it may be necessary to put caching support here, in which case
179
// the cache parameters should be specified in the view config.
180

181             ExtendedProperties eprops = new ExtendedProperties();
182             eprops.putAll(velocityProperties);
183             eprops.addProperty(RuntimeConstants.RESOURCE_LOADER, "jpublish");
184             eprops.setProperty("jpublish.resource.loader.description",
185                     "JPublish internal resource loader.");
186             eprops.setProperty("jpublish.resource.loader.class",
187                     "org.jpublish.view.velocity.JPublishResourceLoader");
188             eprops.setProperty("jpublish.resource.loader.siteContext", siteContext);
189
190             if (resourceCacheEnabled) {
191                 eprops.setProperty("jpublish.resource.loader.cache", "true");
192                 eprops.setProperty("jpublish.resource.loader.modificationCheckInterval",
193                         Integer.toString(getResourceCacheInterval()));
194             }
195
196             velocityEngine.setExtendedProperties(eprops);
197
198             log.debug("Initializing VelocityEngine");
199             velocityEngine.init();
200
201             log.info("Resource loader: " + velocityEngine.getProperty(VelocityEngine.RESOURCE_LOADER));
202         } catch (Exception JavaDoc e) {
203             Object JavaDoc[] args = {e.getMessage()};
204             throw new JPublishRuntimeException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE,
205                     "initError", args),
206                     e);
207         }
208
209     }
210
211     /**
212      * Render the view.
213      *
214      * @param context The RequestContext
215      * @param path The path to the template
216      * @param out The Writer to write the rendered view
217      * @throws IOException
218      * @throws ViewRenderException
219      */

220
221     public void render(RequestContext context, String JavaDoc path, Writer out)
222             throws IOException, ViewRenderException {
223         try {
224             Page page = context.getPage();
225
226             if (log.isDebugEnabled()) {
227                 log.debug("Rendering: " + path);
228                 log.debug("Content encoding: " + page.getEncoding());
229             }
230
231             VelocityViewContext viewContext = new VelocityViewContext(context);
232             velocityEngine.mergeTemplate(path, page.getEncoding(), viewContext,
233                     out);
234             //velocityEngine.mergeTemplate(path, viewContext, out);
235
} catch (IOException e) {
236             throw e;
237         } catch (NullPointerException JavaDoc e) {
238             Object JavaDoc[] args = {};
239             throw new ViewRenderException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE, "renderErrorNull",
240                     args), e);
241         } catch (Exception JavaDoc e) {
242             Object JavaDoc[] args = {path, e.getMessage()};
243             throw new ViewRenderException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE, "renderError",
244                     args), e);
245         }
246     }
247
248     /**
249      * Render the view.
250      *
251      * @param context The RequestContext
252      * @param path The path to the template
253      * @param out The OutputStream to write the rendered view
254      * @throws IOException
255      * @throws ViewRenderException
256      */

257
258     public void render(RequestContext context, String JavaDoc path, OutputStream out)
259             throws IOException, ViewRenderException {
260         render(context, path, new OutputStreamWriter(out));
261     }
262
263     /**
264      * Render the view.
265      *
266      * <p>Note that the implementation of this method results in no template caching which can affect performance. This
267      * method should only be used in cases where the template is generated dynamically (i.e. through pipelining.)</p>
268      *
269      * @param context The RequestContext
270      * @param path The path to the content
271      * @param in The Reader providing the raw content
272      * @param out The Writer to write the rendered view
273      * @throws IOException
274      * @throws ViewRenderException
275      */

276
277     public void render(RequestContext context, String JavaDoc path, Reader in,
278             Writer out) throws IOException, ViewRenderException {
279         try {
280             if (log.isDebugEnabled()) {
281                 log.debug("Rendering: " + path);
282             }
283
284             VelocityViewContext viewContext = new VelocityViewContext(context);
285             velocityEngine.evaluate(viewContext, out, path, in);
286         } catch (IOException e) {
287             throw e;
288         } catch (Exception JavaDoc e) {
289             Object JavaDoc[] args = {path, e.getMessage()};
290             throw new ViewRenderException(MessageUtilities.getMessage(getClass(), JPublishEngine.MESSAGE_PACKAGE, "renderError",
291                     args), e);
292         }
293     }
294
295     /**
296      * Render the view.
297      *
298      * <p>Note that the implementation of this method results in no template caching which can affect performance. This
299      * method should only be used in cases where the template is generated dynamically (i.e. through pipelining.)</p>
300      *
301      * @param context The RequestContext
302      * @param path The path to the content
303      * @param in The InputStream providing the raw content
304      * @param out The OutputStream to write the rendered view
305      * @throws IOException
306      * @throws ViewRenderException
307      */

308
309     public void render(RequestContext context, String JavaDoc path, InputStream in,
310             OutputStream out) throws IOException, ViewRenderException {
311         render(context, path, new InputStreamReader(in),
312                 new OutputStreamWriter(out));
313     }
314
315     /**
316      * Load the configuration for the view.
317      *
318      * @param configuration The configuration object
319      */

320
321     public void loadConfiguration(Configuration configuration)
322             throws ConfigurationException {
323
324         setResourceCacheEnabled(configuration.getChildValue("resource-cache-enabled"));
325         setResourceCacheInterval(configuration.getChildValue("resource-cache-interval"));
326
327         String JavaDoc propertiesPath =
328                 configuration.getChildValue("velocity-properties");
329
330         try {
331
332             if (propertiesPath == null) {
333                 propertiesPath = DEFAULT_PROPERTIES_PATH;
334             }
335
336             FileSystemManager fileSystemManager =
337                     siteContext.getContextFileSystemManager();
338             FileObject baseFile = fileSystemManager.getBaseFile();
339             FileObject propertiesFile = fileSystemManager.resolveFile(baseFile, propertiesPath);
340
341             if (propertiesFile.exists()) {
342                 loadVelocityProperties(propertiesFile, configuration);
343             } else {
344                 log.warn("No velocity.properties file found");
345             }
346         } catch (IOException e) {
347             Object JavaDoc[] args = {propertiesPath};
348             throw new ConfigurationException(MessageUtilities.getMessage(getClass(), "org.jpublish",
349                     "velocityPropertiesIOError", args),
350                     e);
351         }
352     }
353
354     private void loadVelocityProperties(FileObject file,
355             Configuration configuration) throws IOException, FileSystemException {
356         if (log.isDebugEnabled()) {
357             log.debug("Velocity properties file: " + file);
358         }
359
360         FileContent content = file.getContent();
361         InputStream in = null;
362         try {
363             in = content.getInputStream();
364             velocityProperties.load(in);
365             
366             // I am not quite sure how to handle the code below. It depends on
367
// access to the local file system which is no longer guaranteed.
368
// For now I have just disabled it.
369

370             /*
371             Configuration config = configuration.getChild("velocity-properties");
372             if(config != null &&
373                "true".equals(config.getAttribute("relative-paths"))
374             {
375                 for (int i=0; i<velocityKeys.length; i++) {
376                     String value = velocityProperties.getProperty(velocityKeys[i]);
377                     if (value != null && value.trim().length() > 0) {
378                         FileObject file = fileSystem.resolveFile(value);
379                         if (file instanceof LocalFile) {
380                             LocalFile localFile = (LocalFile)file;
381                             File realFile = localFile.getLocalFile();
382                             velocityProperties.setProperty(velocityKeys[i],
383                                 file.toString());
384                         }
385                     }
386                 }
387             }
388             */

389
390         } finally {
391             IOUtilities.close(in);
392         }
393     }
394
395 }
396
Popular Tags