NIHVIVO-3200 Make the FreemarkerConfigurationLoader a static utility class with a local cache, instead of having the loader as a context attribute and the cache as another context attribute.

This commit is contained in:
j2blake 2011-10-03 20:16:55 +00:00
parent dc450cd25c
commit bded986b92
5 changed files with 52 additions and 88 deletions

View file

@ -75,10 +75,7 @@ public abstract class VitroAjaxController extends HttpServlet {
* its data through a template.
*/
protected final Configuration getFreemarkerConfiguration(VitroRequest vreq) {
ServletContext context = getServletContext();
FreemarkerConfigurationLoader loader =
FreemarkerConfigurationLoader.getFreemarkerConfigurationLoader(context);
return loader.getConfig(vreq);
return FreemarkerConfigurationLoader.getConfig(vreq, getServletContext());
}
/**

View file

@ -2,6 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
@ -11,79 +12,54 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import freemarker.template.Configuration;
public class FreemarkerConfigurationLoader {
private static final Log log = LogFactory.getLog(FreemarkerConfigurationLoader.class);
public class FreemarkerConfigurationLoader {
private static final Log log = LogFactory
.getLog(FreemarkerConfigurationLoader.class);
private ServletContext context;
public FreemarkerConfigurationLoader(ServletContext context){
this.context = context;
context.setAttribute("FreemarkerConfigurationLoader", this);
}
/**
* @return Under serious error conditions this will return null.
*/
public static FreemarkerConfigurationLoader getFreemarkerConfigurationLoader(ServletContext context){
if( context!=null){
FreemarkerConfigurationLoader fcl = (FreemarkerConfigurationLoader)
context.getAttribute("FreemarkerConfigurationLoader");
if( fcl == null ){
log.error("Must be constructed before calling " +
"getFreemarkerConfigurationLoader(), usually this is done by FreemarkerSetup");
return null;
}
return fcl;
}else{
log.error("getFreemarkerConfigurationLoader() must not be called with a null context");
return null;
}
}
public FreemarkerConfiguration getConfig(VitroRequest vreq) {
String themeDir = getThemeDir(vreq.getAppBean());
return getConfigForTheme(themeDir, vreq);
}
private static final Map<String, FreemarkerConfiguration> themeToConfigMap = new HashMap<String, FreemarkerConfiguration>();
protected String getThemeDir(ApplicationBean appBean) {
if (appBean == null) {
log.error("Cannot get themeDir from null application bean");
return null;
}
String themeDir = appBean.getThemeDir();
if (themeDir == null) {
log.error("themeDir is null");
return null;
}
public static FreemarkerConfiguration getConfig(VitroRequest vreq,
ServletContext context) {
String themeDir = getThemeDir(vreq.getAppBean());
return getConfigForTheme(themeDir, vreq, context);
}
private static String getThemeDir(ApplicationBean appBean) {
if (appBean == null) {
log.error("Cannot get themeDir from null application bean");
return null;
}
String themeDir = appBean.getThemeDir();
if (themeDir == null) {
log.error("themeDir is null");
return null;
}
return themeDir.replaceAll("/$", "");
}
/**
* The Configuration is theme-specific because:
*
* 1. The template loader is theme-specific, since it specifies a theme
* directory to load templates from.
*
* 2. Shared variables like stylesheets are theme-specific.
*/
private static FreemarkerConfiguration getConfigForTheme(String themeDir,
VitroRequest vreq, ServletContext context) {
synchronized (themeToConfigMap) {
if (themeToConfigMap.containsKey(themeDir)) {
return themeToConfigMap.get(themeDir);
} else {
FreemarkerConfiguration config = new FreemarkerConfiguration(
themeDir, vreq, context);
themeToConfigMap.put(themeDir, config);
return config;
}
}
}
return themeDir.replaceAll("/$", "");
}
protected FreemarkerConfiguration getConfigForTheme(String themeDir, VitroRequest vreq) {
/* The Configuration is theme-specific because:
* 1. The template loader is theme-specific, since it specifies a theme directory to load templates from.
* 2. Shared variables like stylesheets are theme-specific.
*/
@SuppressWarnings("unchecked")
Map<String, FreemarkerConfiguration> themeToConfigMap =
(Map<String, FreemarkerConfiguration>) context.getAttribute("themeToConfigMap");
if( themeToConfigMap == null ) {
log.error("The templating system is not configured correctly. Make sure that you have the FreemarkerSetup context listener in your web.xml.");
// We'll end up with a blank page as well as errors in the log, which is probably fine.
// Doesn't seem like we should throw a checked exception in this case.
return null;
} else if (themeToConfigMap.containsKey(themeDir)) {
return themeToConfigMap.get(themeDir);
} else {
FreemarkerConfiguration config = new FreemarkerConfiguration(themeDir, vreq, context);
themeToConfigMap.put(themeDir, config);
return config;
}
}
}

View file

@ -15,7 +15,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -25,7 +24,6 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.EditOwnAcc
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseMiscellaneousAdminPages;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.TemplateProcessingHelper.TemplateProcessingException;
@ -198,9 +196,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
}
protected FreemarkerConfiguration getConfig(VitroRequest vreq) {
FreemarkerConfigurationLoader loader =
FreemarkerConfigurationLoader.getFreemarkerConfigurationLoader(getServletContext());
return loader.getConfig(vreq);
return FreemarkerConfigurationLoader.getConfig(vreq, getServletContext());
}
/**

View file

@ -2,8 +2,6 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.util.HashMap;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
@ -17,18 +15,17 @@ public class FreemarkerSetup implements ServletContextListener {
private static final Log log = LogFactory.getLog(FreemarkerSetup.class);
@Override
public void contextInitialized(ServletContextEvent event) {
ServletContext sc = event.getServletContext();
sc.setAttribute("themeToConfigMap", new HashMap<String, FreemarkerConfiguration>());
BaseTemplateModel.setServletContext(sc);
FreemarkerComponentGenerator.setServletContext(sc);
UrlBuilder.contextPath = sc.getContextPath();
FreemarkerConfigurationLoader loader = new FreemarkerConfigurationLoader(sc);
log.info("Freemarker templating system initialized.");
}
@Override
public void contextDestroyed(ServletContextEvent event) {
// nothing to do here
}

View file

@ -405,9 +405,7 @@ public class InputElementFormattingTag extends TagSupport {
}
//get freemarker Configuration
FreemarkerConfigurationLoader fConfigLoader
= FreemarkerConfigurationLoader.getFreemarkerConfigurationLoader(pageContext.getServletContext());
Configuration fmConfig = fConfigLoader.getConfig(vreq);
Configuration fmConfig = FreemarkerConfigurationLoader.getConfig(vreq, pageContext.getServletContext());
/* populate the pieces */
String classStr = doClass();