View Javadoc
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 }