Backporting Freemarker template caching to 2.0.x tree

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/branches/STRUTS_2_0_X@560881 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
René Gielen
2007-07-30 07:05:55 +00:00
parent 7b2fb236fc
commit acc7495fe9
4 changed files with 79 additions and 14 deletions
@@ -76,6 +76,9 @@ public final class StrutsConstants {
/** 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_TEMPLATES_CACHE = "struts.freemarker.templatesCache";
/** org.apache.struts2.views.velocity.VelocityManager implementation class */
public static final String STRUTS_VELOCITY_MANAGER_CLASSNAME = "struts.velocity.manager.classname";
@@ -22,9 +22,7 @@ package org.apache.struts2.components.template;
import java.io.IOException;
import java.io.Writer;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -33,6 +31,7 @@ import javax.servlet.http.HttpServletResponse;
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;
@@ -41,8 +40,7 @@ import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.ValueStack;
import freemarker.template.Configuration;
import freemarker.template.SimpleHash;
import freemarker.template.*;
/**
* Freemarker based template engine.
@@ -51,6 +49,10 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
static Class bodyContent = null;
private FreemarkerManager freemarkerManager;
private final HashMap<String, freemarker.template.Template> templates = new HashMap<String, freemarker.template.Template>();
private final HashSet<String> missingTemplates = new HashSet<String>();
private boolean freemarkerCaching = false;
static {
try {
bodyContent = ClassLoaderUtil.loadClass("javax.servlet.jsp.tagext.BodyContent",
@@ -88,16 +90,35 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
freemarker.template.Template template = null;
String templateName = null;
Exception exception = null;
for (Iterator iterator = templates.iterator(); iterator.hasNext();) {
Template t = (Template) iterator.next();
for (Object template1 : templates) {
Template t = (Template) template1;
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;
}
}
}
}
@@ -154,4 +175,40 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
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 templates.get(templateName);
}
}
/**
* Enables or disables Struts caching of Freemarker templates. By default disabled.
* Set struts.freemarker.templatesCache=true to enable cache
* @param cacheTemplates "true" if the template engine should cache freemarker template
* internally
*/
@Inject(StrutsConstants.STRUTS_FREEMARKER_TEMPLATES_CACHE)
public void setCacheTemplates(String cacheTemplates) {
freemarkerCaching = "true".equals(cacheTemplates);
}
}
@@ -163,6 +163,7 @@ public class BeanSelectionProvider implements ConfigurationProvider {
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_TEMPLATES_CACHE, "false");
// Convert struts properties into ones that xwork expects
props.setProperty("devMode", "true");
} else {
@@ -164,6 +164,10 @@ struts.dispatcher.parametersWorkaround = false
### 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=false
### See the StrutsBeanWrapper javadocs for more information
struts.freemarker.wrapper.altMap=true