Author: musachy Date: Sat Jun 30 08:57:13 2007 New Revision: 552165 URL: http://svn.apache.org/viewvc?view=rev&rev=552165 Log: WW-1661 Implementation of Freemarker caching for Struts2 * Will be set to false by default * Set to false when devMode is true * Set struts.freemarker.templatesCache=true to enable it
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?view=diff&rev=552165&r1=552164&r2=552165 ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Sat Jun 30 08:57:13 2007 @@ -75,6 +75,9 @@ /** The org.apache.struts2.views.freemarker.FreemarkerManager implementation class */ public static final String STRUTS_FREEMARKER_MANAGER_CLASSNAME = "struts.freemarker.manager.classname"; + + /** Cache Freemarker templates */ + public static final String STRUTS_FREEMARKER_CACHE_TEMPLATES = "struts.freemarker.templatesCache"; /** org.apache.struts2.views.velocity.VelocityManager implementation class */ public static final String STRUTS_VELOCITY_MANAGER_CLASSNAME = "struts.velocity.manager.classname"; Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java?view=diff&rev=552165&r1=552164&r2=552165 ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java Sat Jun 30 08:57:13 2007 @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.Writer; +import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -33,12 +35,13 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.StrutsConstants; import org.apache.struts2.views.freemarker.FreemarkerManager; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ClassLoaderUtil; import com.opensymphony.xwork2.util.ValueStack; import freemarker.template.Configuration; @@ -51,6 +54,10 @@ static Class bodyContent = null; private FreemarkerManager freemarkerManager; + private HashMap<String, freemarker.template.Template> templates = new HashMap<String, freemarker.template.Template>(); + private HashSet<String> missingTemplates = new HashSet<String>(); + private boolean freemarkerCaching = false; + static { try { bodyContent = ClassLoaderUtil.loadClass("javax.servlet.jsp.tagext.BodyContent", @@ -71,7 +78,7 @@ } public void renderTemplate(TemplateRenderingContext templateContext) throws Exception { - // get the various items required from the stack + // get the various items required from the stack ValueStack stack = templateContext.getStack(); Map context = stack.getContext(); ServletContext servletContext = (ServletContext) context.get(ServletActionContext.SERVLET_CONTEXT); @@ -91,13 +98,32 @@ for (Iterator iterator = templates.iterator(); iterator.hasNext();) { Template t = (Template) iterator.next(); templateName = getFinalTemplateName(t); - try { - // try to load, and if it works, stop at the first one - template = config.getTemplate(templateName); - break; - } catch (IOException e) { - if (exception == null) { - exception = e; + if (freemarkerCaching) { + if (!isTemplateMissing(templateName)) { + try { + template = findInCache(templateName); // look in cache first + if (template == null) { + // try to load, and if it works, stop at the first one + template = config.getTemplate(templateName); + addToCache(templateName, template); + } + break; + } catch (IOException e) { + addToMissingTemplateCache(templateName); + if (exception == null) { + exception = e; + } + } + } + } else { + try { + // try to load, and if it works, stop at the first one + template = config.getTemplate(templateName); + break; + } catch (IOException e) { + if (exception == null) { + exception = e; + } } } } @@ -153,5 +179,41 @@ protected String getSuffix() { return "ftl"; + } + + protected void addToMissingTemplateCache(String templateName) { + synchronized(missingTemplates) { + missingTemplates.add(templateName); + } + } + + protected boolean isTemplateMissing(String templateName) { + synchronized(missingTemplates) { + return missingTemplates.contains(templateName); + } + } + + protected void addToCache(String templateName, + freemarker.template.Template template) { + synchronized(templates) { + templates.put(templateName, template); + } + } + + protected freemarker.template.Template findInCache(String templateName) { + synchronized(templates) { + return (freemarker.template.Template) templates.get(templateName); + } + } + + /** + * Enables or disables Struts caching of Freemarker templates. By default disabled. + * Set struts.freemarker.templatesCache=true to enable cache + * @param caching true if the template engine should cache freemarker template + * internally + */ + @Inject(StrutsConstants.STRUTS_FREEMARKER_CACHE_TEMPLATES) + public void setCacheTemplates(String cacheTemplates) { + freemarkerCaching = "true".equals(cacheTemplates); } } Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java?view=diff&rev=552165&r1=552164&r2=552165 ============================================================================== --- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java (original) +++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java Sat Jun 30 08:57:13 2007 @@ -163,6 +163,7 @@ if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) { props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true"); props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, "true"); + props.setProperty(StrutsConstants.STRUTS_FREEMARKER_CACHE_TEMPLATES, "false"); // Convert struts properties into ones that xwork expects props.setProperty("devMode", "true"); } else { Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties?view=diff&rev=552165&r1=552164&r2=552165 ============================================================================== --- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties (original) +++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties Sat Jun 30 08:57:13 2007 @@ -145,6 +145,10 @@ ### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager #struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager +### Enables caching of FreeMarker templates +### Has the same effect as copying the templates under WEB_APP/templates +#struts.freemarker.templatesCache=true + ### See the StrutsBeanWrapper javadocs for more information struts.freemarker.wrapper.altMap=true