PageRenderTime 26ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/java/src/org/jpublish/view/velocity/VelocityViewRenderer.java

http://jpublish.googlecode.com/
Java | 287 lines | 171 code | 52 blank | 64 comment | 24 complexity | 0717dc8f6e6c2b2a92879f9355da930a MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. /*
  2. * Copyright 2004-2007 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. package org.jpublish.view.velocity;
  18. import com.anthonyeden.lib.config.Configuration;
  19. import com.anthonyeden.lib.config.ConfigurationException;
  20. import com.anthonyeden.lib.util.IOUtilities;
  21. import com.atlassian.util.profiling.UtilTimerStack;
  22. import org.apache.commons.collections.ExtendedProperties;
  23. import org.apache.commons.logging.Log;
  24. import org.apache.commons.logging.LogFactory;
  25. import org.apache.velocity.app.VelocityEngine;
  26. import org.apache.velocity.exception.VelocityException;
  27. import org.apache.velocity.runtime.RuntimeConstants;
  28. import org.jpublish.JPublishContext;
  29. import org.jpublish.SiteContext;
  30. import org.jpublish.util.CharacterEncodingMap;
  31. import org.jpublish.view.ViewRenderException;
  32. import org.jpublish.view.ViewRenderer;
  33. import javax.servlet.ServletContext;
  34. import java.io.*;
  35. import java.util.Properties;
  36. /**
  37. * ViewRenderer which uses the Velocity template engine from the Apache
  38. * Jakarta group to render content.
  39. *
  40. * @author Anthony Eden
  41. * @author <a href="mailto:florin.patrascu@gmail.com">Florin T.PATRASCU</a>
  42. * @since 2.0
  43. */
  44. public class VelocityViewRenderer implements ViewRenderer {
  45. private static final Log log = LogFactory.getLog(VelocityViewRenderer.class);
  46. private static final String DEFAULT_PROPERTIES_PATH = "WEB-INF/velocity.properties";
  47. // Here are the names of Velocity 1.2 properties that can contains paths.
  48. private static final String[] velocityKeys = {
  49. "runtime.log", "file.resource.loader.path", "velocimacro.library"
  50. };
  51. private SiteContext siteContext;
  52. private final VelocityEngine velocityEngine = new VelocityEngine();
  53. private Properties velocityProperties = new Properties();
  54. private boolean resourceCacheEnabled = false;
  55. private int resourceCacheInterval = 2;
  56. /**
  57. * Set the SiteContext.
  58. *
  59. * @param siteContext The SiteContext
  60. */
  61. public void setSiteContext(SiteContext siteContext) {
  62. log.debug("setSiteContext()");
  63. this.siteContext = siteContext;
  64. }
  65. public boolean isResourceCacheEnabled() {
  66. return resourceCacheEnabled;
  67. }
  68. public void setResourceCacheEnabled(boolean resourceCacheEnabled) {
  69. if (log.isDebugEnabled())
  70. log.debug("Resource cache enabled: " + resourceCacheEnabled);
  71. this.resourceCacheEnabled = resourceCacheEnabled;
  72. }
  73. public void setResourceCacheEnabled(String resourceCacheEnabled) {
  74. setResourceCacheEnabled("true".equals(resourceCacheEnabled));
  75. }
  76. public int getResourceCacheInterval() {
  77. return resourceCacheInterval;
  78. }
  79. public void setResourceCacheInterval(int resourceCacheInterval) {
  80. if (log.isDebugEnabled())
  81. log.debug("Resource cache interval: " + resourceCacheInterval);
  82. this.resourceCacheInterval = resourceCacheInterval;
  83. }
  84. public void setResourceCacheInterval(String resourceCacheInterval) {
  85. if (resourceCacheInterval != null) {
  86. setResourceCacheInterval(Integer.parseInt(resourceCacheInterval));
  87. }
  88. }
  89. /**
  90. * Initialize the ViewRenderer.
  91. *
  92. * @throws Exception Any Exception
  93. */
  94. public void init() throws Exception {
  95. log.debug("init()");
  96. // it may be necessary to put caching support here, in which case
  97. // the cache parameters should be specified in the view config.
  98. ExtendedProperties eprops = new ExtendedProperties();
  99. eprops.putAll(velocityProperties);
  100. eprops.addProperty(RuntimeConstants.RESOURCE_LOADER, "jpublish");
  101. eprops.setProperty("jpublish.resource.loader.description", "JPublish internal resource loader.");
  102. eprops.setProperty("jpublish.resource.loader.class", "org.jpublish.view.velocity.JPublishResourceLoader");
  103. eprops.setProperty("jpublish.resource.loader.siteContext", siteContext);
  104. if (resourceCacheEnabled) {
  105. eprops.setProperty("jpublish.resource.loader.cache", "true");
  106. eprops.setProperty("jpublish.resource.loader.modificationCheckInterval",
  107. Integer.toString(getResourceCacheInterval()));
  108. }
  109. // Apply properties to VelocityEngine.
  110. velocityEngine.setExtendedProperties(eprops);
  111. try {
  112. velocityEngine.init();
  113. velocityEngine.setApplicationAttribute(ServletContext.class.getName(), siteContext.getServletContext());
  114. }
  115. catch (IOException ex) {
  116. throw ex;
  117. }
  118. catch (VelocityException ex) {
  119. throw ex;
  120. }
  121. catch (RuntimeException ex) {
  122. throw ex;
  123. }
  124. catch (Exception ex) {
  125. log.error("Why does VelocityEngine throw a generic checked exception, after all?", ex);
  126. throw new VelocityException(ex.getMessage());
  127. }
  128. log.info("Resource loader: " + velocityEngine.getProperty(VelocityEngine.RESOURCE_LOADER));
  129. }
  130. /**
  131. * Render the view.
  132. *
  133. * @param context The JPublishContext
  134. * @param path The path to the template
  135. * @param in The Reader to read view template from
  136. * @param out The Writer to write the rendered view
  137. * @throws IOException
  138. * @throws ViewRenderException
  139. */
  140. public void render(JPublishContext context, String path, Reader in, Writer out)
  141. throws IOException, ViewRenderException {
  142. CharacterEncodingMap characterEncodingMap = siteContext.getCharacterEncodingManager().getMap(path);
  143. String encoding = characterEncodingMap.getPageEncoding();
  144. if (log.isDebugEnabled()) {
  145. log.debug("render(" + path + ")");
  146. log.debug("Character encoding: " + encoding);
  147. }
  148. try {
  149. UtilTimerStack.push(" ==> /" + path);
  150. VelocityViewContext viewContext = new VelocityViewContext(context);
  151. if (context.get("evaluateVelocityTemplates") != null)
  152. //Florin 15 Feb 2005
  153. velocityEngine.evaluate(viewContext, out, path, in);
  154. else
  155. velocityEngine.mergeTemplate(path, encoding, viewContext, out);
  156. } catch (IOException e) {
  157. log.error(path + ", IO exception: " + e.getMessage());
  158. throw e;
  159. } catch (Exception e) {
  160. log.error(path + ", rendering exception: " + e.getMessage());
  161. throw new ViewRenderException(e);
  162. } finally {
  163. UtilTimerStack.pop(" ==> /" + path);
  164. }
  165. }
  166. /**
  167. * Render the view.
  168. *
  169. * @param context The JPublishContext
  170. * @param path The path to the template
  171. * @param in The InputStream to read view template from
  172. * @param out The OutputStream to write the rendered view
  173. * @throws IOException
  174. * @throws ViewRenderException
  175. */
  176. public void render(JPublishContext context, String path, InputStream in, OutputStream out)
  177. throws IOException, ViewRenderException {
  178. render(context, path, new InputStreamReader(in), new OutputStreamWriter(out));
  179. }
  180. /**
  181. * Load the configuration for the view.
  182. *
  183. * @param configuration The configuration object
  184. */
  185. public void loadConfiguration(Configuration configuration) throws ConfigurationException {
  186. setResourceCacheEnabled(configuration.getChildValue("resource-cache-enabled"));
  187. setResourceCacheInterval(configuration.getChildValue("resource-cache-interval"));
  188. try {
  189. String propertiesPath = configuration.getChildValue("velocity-properties");
  190. if (propertiesPath == null) {
  191. propertiesPath = DEFAULT_PROPERTIES_PATH;
  192. }
  193. File propertiesFile = new File(propertiesPath);
  194. if (!propertiesFile.exists()) {
  195. if (!propertiesFile.isAbsolute()) {
  196. if (log.isDebugEnabled())
  197. log.debug("Velocity properties path is not absolute. " +
  198. "Prepending root: " + siteContext.getRoot());
  199. propertiesFile = new File(siteContext.getRoot(), propertiesFile.getPath());
  200. }
  201. }
  202. if (propertiesFile.exists()) {
  203. if (log.isDebugEnabled())
  204. log.debug("Velocity properties file: " + propertiesFile);
  205. InputStream in = null;
  206. try {
  207. in = new FileInputStream(propertiesFile);
  208. velocityProperties.load(in);
  209. Configuration config = configuration.getChild("velocity-properties");
  210. if (config != null) {
  211. String relativePaths = config.getAttribute("relative-paths");
  212. if ("true".equalsIgnoreCase(relativePaths)) {
  213. for (int i = 0; i < velocityKeys.length; i++) {
  214. String value = velocityProperties.getProperty(velocityKeys[i]);
  215. if (value != null && value.trim().length() > 0) {
  216. File file = new File(value);
  217. if (!file.isAbsolute()) {
  218. file = new File(siteContext.getRoot(), file.getPath());
  219. velocityProperties.setProperty(velocityKeys[i], file.toString());
  220. }
  221. }
  222. }
  223. }
  224. }
  225. } finally {
  226. IOUtilities.close(in);
  227. }
  228. } else {
  229. log.warn("No velocity.properties file found");
  230. }
  231. } catch (IOException e) {
  232. throw new ConfigurationException("IO error: " + e, e);
  233. }
  234. }
  235. }