From 7c72f0f37ca6719e66c4f2b4cc9b15ff1c85f650 Mon Sep 17 00:00:00 2001 From: rjy7 Date: Wed, 12 May 2010 15:08:56 +0000 Subject: [PATCH] Implement multi-location template loading to look for a template first in the themes directory, then in the vitro template directory. --- .../controller/FreeMarkerHttpServlet.java | 58 +++++++++++++++---- .../webapp/servlet/setup/FreeMarkerSetup.java | 22 +++---- .../vitro/webapp/view/menu/TabMenu.java | 3 +- .../freemarker/components/identity.ftl | 1 - 4 files changed, 55 insertions(+), 29 deletions(-) diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/FreeMarkerHttpServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/FreeMarkerHttpServlet.java index 8f425d589..f4fd9efff 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/FreeMarkerHttpServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/FreeMarkerHttpServlet.java @@ -2,6 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.controller; +import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -13,6 +14,7 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -27,6 +29,11 @@ import edu.cornell.mannlib.vitro.webapp.beans.Portal; import edu.cornell.mannlib.vitro.webapp.utils.StringUtils; import edu.cornell.mannlib.vitro.webapp.view.menu.TabMenu; import edu.cornell.mannlib.vitro.webapp.web.PortalWebUtil; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.FileTemplateLoader; +import freemarker.cache.MultiTemplateLoader; +import freemarker.cache.TemplateLoader; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; @@ -34,11 +41,12 @@ import freemarker.template.TemplateModelException; public class FreeMarkerHttpServlet extends VitroHttpServlet { - private static final Log log = LogFactory.getLog(FreeMarkerHttpServlet.class.getName()); + private static final long serialVersionUID = 1L; + private static final Log log = LogFactory.getLog(FreeMarkerHttpServlet.class.getName()); private static final int FILTER_SECURITY_LEVEL = LoginFormBean.EDITOR; public static Configuration config = null; - public static String contextPath = null; // RY or do we need to store the entire ServletContext? + public static String contextPath = null; protected VitroRequest vreq; protected HttpServletResponse response; @@ -50,6 +58,7 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet { // a getBody() and getTitle() method and use the parent doGet() method. public void doGet( HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException { + try { doSetup(request, response); setTitle(); @@ -161,19 +170,19 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet { protected void doSetup(HttpServletRequest request, HttpServletResponse response) { try { - super.doGet(request,response); - } catch (ServletException e1) { + super.doGet(request,response); + } catch (ServletException e) { // TODO Auto-generated catch block - e1.printStackTrace(); - } catch (IOException e1) { + e.printStackTrace(); + } catch (IOException e) { // TODO Auto-generated catch block - e1.printStackTrace(); + e.printStackTrace(); } - + vreq = new VitroRequest(request); this.response = response; - portal = vreq.getPortal(); - + portal = vreq.getPortal(); + // RY Can this be removed? Do templates need it? Ideally, they should not. // Only needed for some weird stuff in search box that I think is only used in old default theme. int portalId = portal.getPortalId(); @@ -183,6 +192,8 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet { log.error("Can't set shared variable 'portalId'."); } + setTemplateLoader(); + TabMenu menu = getTabMenu(portalId); root.put("tabMenu", menu); @@ -226,7 +237,6 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet { } urls.put("about", getUrl(Controllers.ABOUT + "?home=" + portalId)); - urls.put("aboutFM", getUrl(Controllers.ABOUT + "-fm?home=" + portalId)); // TEMPORARY if (ContactMailServlet.getSmtpHostFromProperties() != null) { urls.put("contact", getUrl(Controllers.CONTACT_URL + "?home=" + portalId)); } @@ -277,6 +287,32 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet { root.put("copyright", copyright); } } + + // Define template locations. Template loader will look first in the theme-specific + // location, then in the vitro location. + // RY We cannot do this in FreeMarkerSetup because (a) the theme depends on the portal, + // and we have multi-portal installations, and (b) we need to support theme-switching on the fly. + // To make more efficient, we could do this once, and then have a listener that does it again + // when theme is switched.BUT this doesn't support (a), only (b), so we have to do it on every request. + private final void setTemplateLoader() { + + // RY If this is needed in other methods, put in instance var + ServletContext context = getServletContext(); + String themeTemplateDir = context.getRealPath(portal.getThemeDir()) + "/ftl"; + String vitroTemplateDir = context.getRealPath("/templates/freemarker"); + + try { + FileTemplateLoader themeFtl = new FileTemplateLoader(new File(themeTemplateDir)); + FileTemplateLoader vitroFtl = new FileTemplateLoader(new File(vitroTemplateDir)); + ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), ""); + TemplateLoader[] loaders = new TemplateLoader[] { themeFtl, vitroFtl, ctl }; + MultiTemplateLoader mtl = new MultiTemplateLoader(loaders); + config.setTemplateLoader(mtl); + } catch (IOException e) { + log.error("Error loading templates"); + } + + } public static String getUrl(String path) { if ( ! path.startsWith("/") ) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/FreeMarkerSetup.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/FreeMarkerSetup.java index 3c304bfff..aa7b3566b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/FreeMarkerSetup.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/FreeMarkerSetup.java @@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet; import edu.cornell.mannlib.vitro.webapp.view.ViewObject; + import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.TemplateException; @@ -27,24 +28,14 @@ public class FreeMarkerSetup implements ServletContextListener { ServletContext sc = event.getServletContext(); - // RY Change this to multi-location template scheme - String templatePath = sc.getRealPath("/templates/freemarker"); - Configuration cfg = new Configuration(); - /* **** RY - Here's what I want to do to avoid having to pass in the contextPath to every view object created (in order for them to create their URLs): - Subclass Configuration. Add a static variable CONTEXT_PATH to it. Set that value here, and define a getter also. Then when creating - urls in view object methods like getUrl(), we can reference that configuration value. None of this is possible unless we can use - the method ServletContext.getContextPath(), new to Servlet API 2.5 andn therefore requiring tomcat 6 rather than 5. - */ - // Specify the data source where the template files come from. - try { - cfg.setDirectoryForTemplateLoading(new File(templatePath)); - } catch (IOException e) { - log.error("Error specifying template directory."); - } +// try { +// cfg.setDirectoryForTemplateLoading(new File(templatePath)); +// } catch (IOException e) { +// log.error("Error specifying template directory."); +// } // RY This setting won't take effect until we use Configuration.getTemplate() to // create templates. @@ -69,6 +60,7 @@ public class FreeMarkerSetup implements ServletContextListener { String contextPath = sc.getContextPath(); FreeMarkerHttpServlet.contextPath = contextPath; ViewObject.contextPath = contextPath; + } public void contextDestroyed(ServletContextEvent event) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/view/menu/TabMenu.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/view/menu/TabMenu.java index 705c90ab1..49e8d6e64 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/view/menu/TabMenu.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/view/menu/TabMenu.java @@ -44,8 +44,7 @@ public class TabMenu extends MainMenu { // Hard-coded tabs. It's not really a good idea to have these here, since any menu item that doesn't // come from the db should be accessible to the template to change the text. But we need them here // to apply the "active" mechanism. - addItem("Index", "/browsecontroller"); - addItem("Index - FM", "/browse"); + addItem("Index", "/browsecontroller"); } } diff --git a/webapp/web/templates/freemarker/components/identity.ftl b/webapp/web/templates/freemarker/components/identity.ftl index 07b5778f9..dfb8c0a02 100644 --- a/webapp/web/templates/freemarker/components/identity.ftl +++ b/webapp/web/templates/freemarker/components/identity.ftl @@ -24,7 +24,6 @@
  • About
  • , -
  • About - FM
  • , <#if urls.contact??>
  • Contact Us