Implement multi-location template loading to look for a template first in the themes directory, then in the vitro template directory.
This commit is contained in:
parent
a0c93fda6d
commit
7c72f0f37c
4 changed files with 55 additions and 29 deletions
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller;
|
package edu.cornell.mannlib.vitro.webapp.controller;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
@ -13,6 +14,7 @@ import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
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.utils.StringUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.view.menu.TabMenu;
|
import edu.cornell.mannlib.vitro.webapp.view.menu.TabMenu;
|
||||||
import edu.cornell.mannlib.vitro.webapp.web.PortalWebUtil;
|
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.Configuration;
|
||||||
import freemarker.template.Template;
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
|
@ -34,11 +41,12 @@ import freemarker.template.TemplateModelException;
|
||||||
|
|
||||||
public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
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;
|
private static final int FILTER_SECURITY_LEVEL = LoginFormBean.EDITOR;
|
||||||
|
|
||||||
public static Configuration config = null;
|
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 VitroRequest vreq;
|
||||||
protected HttpServletResponse response;
|
protected HttpServletResponse response;
|
||||||
|
@ -50,6 +58,7 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
// a getBody() and getTitle() method and use the parent doGet() method.
|
// a getBody() and getTitle() method and use the parent doGet() method.
|
||||||
public void doGet( HttpServletRequest request, HttpServletResponse response )
|
public void doGet( HttpServletRequest request, HttpServletResponse response )
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
doSetup(request, response);
|
doSetup(request, response);
|
||||||
setTitle();
|
setTitle();
|
||||||
|
@ -161,19 +170,19 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
protected void doSetup(HttpServletRequest request, HttpServletResponse response) {
|
protected void doSetup(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
super.doGet(request,response);
|
super.doGet(request,response);
|
||||||
} catch (ServletException e1) {
|
} catch (ServletException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e1.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch (IOException e1) {
|
} catch (IOException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e1.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
vreq = new VitroRequest(request);
|
vreq = new VitroRequest(request);
|
||||||
this.response = response;
|
this.response = response;
|
||||||
portal = vreq.getPortal();
|
portal = vreq.getPortal();
|
||||||
|
|
||||||
// RY Can this be removed? Do templates need it? Ideally, they should not.
|
// 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.
|
// Only needed for some weird stuff in search box that I think is only used in old default theme.
|
||||||
int portalId = portal.getPortalId();
|
int portalId = portal.getPortalId();
|
||||||
|
@ -183,6 +192,8 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
log.error("Can't set shared variable 'portalId'.");
|
log.error("Can't set shared variable 'portalId'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTemplateLoader();
|
||||||
|
|
||||||
TabMenu menu = getTabMenu(portalId);
|
TabMenu menu = getTabMenu(portalId);
|
||||||
root.put("tabMenu", menu);
|
root.put("tabMenu", menu);
|
||||||
|
|
||||||
|
@ -226,7 +237,6 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
}
|
}
|
||||||
|
|
||||||
urls.put("about", getUrl(Controllers.ABOUT + "?home=" + portalId));
|
urls.put("about", getUrl(Controllers.ABOUT + "?home=" + portalId));
|
||||||
urls.put("aboutFM", getUrl(Controllers.ABOUT + "-fm?home=" + portalId)); // TEMPORARY
|
|
||||||
if (ContactMailServlet.getSmtpHostFromProperties() != null) {
|
if (ContactMailServlet.getSmtpHostFromProperties() != null) {
|
||||||
urls.put("contact", getUrl(Controllers.CONTACT_URL + "?home=" + portalId));
|
urls.put("contact", getUrl(Controllers.CONTACT_URL + "?home=" + portalId));
|
||||||
}
|
}
|
||||||
|
@ -277,6 +287,32 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
root.put("copyright", copyright);
|
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) {
|
public static String getUrl(String path) {
|
||||||
if ( ! path.startsWith("/") ) {
|
if ( ! path.startsWith("/") ) {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
|
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet;
|
import edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet;
|
||||||
import edu.cornell.mannlib.vitro.webapp.view.ViewObject;
|
import edu.cornell.mannlib.vitro.webapp.view.ViewObject;
|
||||||
|
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.DefaultObjectWrapper;
|
import freemarker.template.DefaultObjectWrapper;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
|
@ -27,24 +28,14 @@ public class FreeMarkerSetup implements ServletContextListener {
|
||||||
|
|
||||||
ServletContext sc = event.getServletContext();
|
ServletContext sc = event.getServletContext();
|
||||||
|
|
||||||
// RY Change this to multi-location template scheme
|
|
||||||
String templatePath = sc.getRealPath("/templates/freemarker");
|
|
||||||
|
|
||||||
Configuration cfg = new Configuration();
|
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.
|
// Specify the data source where the template files come from.
|
||||||
try {
|
// try {
|
||||||
cfg.setDirectoryForTemplateLoading(new File(templatePath));
|
// cfg.setDirectoryForTemplateLoading(new File(templatePath));
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
log.error("Error specifying template directory.");
|
// log.error("Error specifying template directory.");
|
||||||
}
|
// }
|
||||||
|
|
||||||
// RY This setting won't take effect until we use Configuration.getTemplate() to
|
// RY This setting won't take effect until we use Configuration.getTemplate() to
|
||||||
// create templates.
|
// create templates.
|
||||||
|
@ -69,6 +60,7 @@ public class FreeMarkerSetup implements ServletContextListener {
|
||||||
String contextPath = sc.getContextPath();
|
String contextPath = sc.getContextPath();
|
||||||
FreeMarkerHttpServlet.contextPath = contextPath;
|
FreeMarkerHttpServlet.contextPath = contextPath;
|
||||||
ViewObject.contextPath = contextPath;
|
ViewObject.contextPath = contextPath;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void contextDestroyed(ServletContextEvent event) {
|
public void contextDestroyed(ServletContextEvent event) {
|
||||||
|
|
|
@ -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
|
// 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
|
// come from the db should be accessible to the template to change the text. But we need them here
|
||||||
// to apply the "active" mechanism.
|
// to apply the "active" mechanism.
|
||||||
addItem("Index", "/browsecontroller");
|
addItem("Index", "/browsecontroller");
|
||||||
addItem("Index - FM", "/browse");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<li><a href="${urls.about}$">About</a></li>,
|
<li><a href="${urls.about}$">About</a></li>,
|
||||||
<li><a href="${urls.aboutFM}">About - FM</a></li>,
|
|
||||||
<#if urls.contact??>
|
<#if urls.contact??>
|
||||||
<li><a href="${urls.contact}">Contact Us</a></li>
|
<li><a href="${urls.contact}">Contact Us</a></li>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
Loading…
Add table
Reference in a new issue