VIVO-11 Add delimiters to Freemarker templates
If enabled by an option in runtime.properties
This commit is contained in:
parent
bb6b2fa970
commit
f350c28d24
4 changed files with 169 additions and 8 deletions
|
@ -692,7 +692,7 @@
|
||||||
see the effect of changes to the template. The default is <code>false</code>, which
|
see the effect of changes to the template. The default is <code>false</code>, which
|
||||||
means that a cached copy of each template will be used for 60 seconds
|
means that a cached copy of each template will be used for 60 seconds
|
||||||
before the disk is checked for a new version.
|
before the disk is checked for a new version.
|
||||||
<br/><b>Setting this option to "true" slows down VIVO performance.</b>
|
<br/><b>Setting this option to "true" slows down Vitro performance.</b>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd_row">
|
<tr class="odd_row">
|
||||||
|
@ -713,7 +713,7 @@
|
||||||
see the effect of changes to the text strings.
|
see the effect of changes to the text strings.
|
||||||
The default is <code>false</code>, which means that the language file is
|
The default is <code>false</code>, which means that the language file is
|
||||||
read when VIVO starts up, or when a new theme is selected.
|
read when VIVO starts up, or when a new theme is selected.
|
||||||
<br/><b>Setting this option to "true" slows down VIVO performance.</b>
|
<br/><b>Setting this option to "true" slows down Vitro performance.</b>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd_row">
|
<tr class="odd_row">
|
||||||
|
@ -725,6 +725,24 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<b>For developers only.</b>
|
||||||
|
Add starting and ending delimiters to each Freemarker template, so you can see
|
||||||
|
which template were invoked by viewing the generated HTML.
|
||||||
|
The default is <code>false</code>.
|
||||||
|
<br/><b>Setting this option to "true" slows down Vitro performance.</b>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd_row blue">
|
||||||
|
<td>
|
||||||
|
developer.insertFreemarkerDelimiters = true
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
false
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h3 id="deploy">VI. Compile and deploy</h3>
|
<h3 id="deploy">VI. Compile and deploy</h3>
|
||||||
|
|
|
@ -141,7 +141,7 @@ RDFService.languageFilter = true
|
||||||
# languages.selectableLocales = en, es, fr
|
# languages.selectableLocales = en, es, fr
|
||||||
|
|
||||||
#
|
#
|
||||||
# For developers only: Setting this option to "true" slows down VIVO performance.
|
# For developers only: Setting this option to "true" slows down Vitro performance.
|
||||||
#
|
#
|
||||||
# Defeat the Freemarker template cache, so each template is read from disk
|
# Defeat the Freemarker template cache, so each template is read from disk
|
||||||
# on each request. This permits developers to immediately see the effect of
|
# on each request. This permits developers to immediately see the effect of
|
||||||
|
@ -152,7 +152,7 @@ RDFService.languageFilter = true
|
||||||
# developer.defeatFreemarkerCache = true
|
# developer.defeatFreemarkerCache = true
|
||||||
|
|
||||||
#
|
#
|
||||||
# For developers only: Setting this option to "true" slows down VIVO performance.
|
# For developers only: Setting this option to "true" slows down Vitro performance.
|
||||||
#
|
#
|
||||||
# Defeat the cache of language-specific text strings, so the language file
|
# Defeat the cache of language-specific text strings, so the language file
|
||||||
# is read from disk on each request. This permits developers to immediately
|
# is read from disk on each request. This permits developers to immediately
|
||||||
|
@ -162,3 +162,12 @@ RDFService.languageFilter = true
|
||||||
#
|
#
|
||||||
# developer.defeatI18nCache = true
|
# developer.defeatI18nCache = true
|
||||||
|
|
||||||
|
#
|
||||||
|
# For developers only: Setting this option to "true" slows down Vitro performance.
|
||||||
|
#
|
||||||
|
# Add starting and ending delimiters to each Freemarker template, so you can see
|
||||||
|
# which template were invoked by viewing the generated HTML. The default is
|
||||||
|
# <code>false</code>.
|
||||||
|
#
|
||||||
|
# developer.insertFreemarkerDelimiters = true
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import freemarker.cache.TemplateLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap a TemplateLoader, so each time a template is read, delimiters will be
|
||||||
|
* inserted at the beginning and end. This makes it easier for a developer can
|
||||||
|
* see what lines of HTML come from which templates.
|
||||||
|
*
|
||||||
|
* TemplateLoader returns a token object when finding a template, and then
|
||||||
|
* recognizes that object when it is used as an argument to getLastModified() or
|
||||||
|
* getReader(). In order to keep track of the template name, we wrap the token
|
||||||
|
* object and the name in a token of our own.
|
||||||
|
*
|
||||||
|
* Taking the easy way out and reading in the entire template into a string.
|
||||||
|
* This limits the template size to less than 2^31 characters (~2 GBytes). That
|
||||||
|
* seems adequate.
|
||||||
|
*/
|
||||||
|
public class DelimitingTemplateLoader implements TemplateLoader {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(DelimitingTemplateLoader.class);
|
||||||
|
|
||||||
|
private final TemplateLoader innerLoader;
|
||||||
|
|
||||||
|
public DelimitingTemplateLoader(TemplateLoader innerLoader) {
|
||||||
|
this.innerLoader = innerLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object findTemplateSource(String name) throws IOException {
|
||||||
|
Object innerTS = innerLoader.findTemplateSource(name);
|
||||||
|
if (innerTS == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new DelimitingTemplateSource(name, innerTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLastModified(Object templateSource) {
|
||||||
|
DelimitingTemplateSource dts = (DelimitingTemplateSource) templateSource;
|
||||||
|
return innerLoader.getLastModified(dts.ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Reader getReader(Object templateSource, String encoding)
|
||||||
|
throws IOException {
|
||||||
|
DelimitingTemplateSource dts = (DelimitingTemplateSource) templateSource;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("<!-- FM_BEGIN ").append(dts.name).append(" -->");
|
||||||
|
sb.append(readTemplateSource(encoding, dts.ts));
|
||||||
|
sb.append("<!-- FM_END ").append(dts.name).append(" -->\n");
|
||||||
|
return new StringReader(sb.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder readTemplateSource(String encoding, Object ts)
|
||||||
|
throws IOException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
Reader reader = innerLoader.getReader(ts, encoding);
|
||||||
|
char[] buffer = new char[8192];
|
||||||
|
int howmany;
|
||||||
|
while (-1 != (howmany = reader.read(buffer))) {
|
||||||
|
sb.append(buffer, 0, howmany);
|
||||||
|
}
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeTemplateSource(Object templateSource) throws IOException {
|
||||||
|
DelimitingTemplateSource dts = (DelimitingTemplateSource) templateSource;
|
||||||
|
innerLoader.closeTemplateSource(dts.ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Helper classes
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data object, wrapping the template name and the templateSource object
|
||||||
|
* from the inner TemplateLoader.
|
||||||
|
*/
|
||||||
|
private static class DelimitingTemplateSource {
|
||||||
|
public final String name;
|
||||||
|
public final Object ts;
|
||||||
|
|
||||||
|
public DelimitingTemplateSource(String name, Object ts) {
|
||||||
|
if (name == null) {
|
||||||
|
throw new NullPointerException("name may not be null.");
|
||||||
|
}
|
||||||
|
if (ts == null) {
|
||||||
|
throw new NullPointerException("ts may not be null.");
|
||||||
|
}
|
||||||
|
this.name = name;
|
||||||
|
this.ts = ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name.hashCode() ^ ts.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!o.getClass().equals(this.getClass())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DelimitingTemplateSource that = (DelimitingTemplateSource) o;
|
||||||
|
return this.name.equals(that.name) && this.ts.equals(that.ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,19 +50,21 @@ public class FreemarkerConfiguration extends Configuration {
|
||||||
private static final Log log = LogFactory.getLog(FreemarkerConfiguration.class);
|
private static final Log log = LogFactory.getLog(FreemarkerConfiguration.class);
|
||||||
|
|
||||||
private static final String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatFreemarkerCache";
|
private static final String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatFreemarkerCache";
|
||||||
|
private static final String PROPERTY_DEVELOPER_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters";
|
||||||
|
|
||||||
private final String themeDir;
|
private final String themeDir;
|
||||||
private final ServletContext context;
|
private final ServletContext context;
|
||||||
private final ApplicationBean appBean;
|
private final ApplicationBean appBean;
|
||||||
|
private final ConfigurationProperties props;
|
||||||
|
|
||||||
FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) {
|
FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) {
|
||||||
|
|
||||||
this.themeDir = themeDir;
|
this.themeDir = themeDir;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.appBean = appBean;
|
this.appBean = appBean;
|
||||||
|
this.props = ConfigurationProperties.getBean(context);
|
||||||
|
|
||||||
String flag = ConfigurationProperties.getBean(context).getProperty(
|
String flag = props.getProperty(PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
||||||
PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
|
||||||
if (Boolean.valueOf(flag.trim())) {
|
if (Boolean.valueOf(flag.trim())) {
|
||||||
log.debug("Disabling Freemarker template caching in development build.");
|
log.debug("Disabling Freemarker template caching in development build.");
|
||||||
setTemplateUpdateDelay(0); // no template caching in development
|
setTemplateUpdateDelay(0); // no template caching in development
|
||||||
|
@ -211,7 +213,13 @@ public class FreemarkerConfiguration extends Configuration {
|
||||||
log.error("Error creating template loaders");
|
log.error("Error creating template loaders");
|
||||||
}
|
}
|
||||||
|
|
||||||
return mtl;
|
// Add the ability to add delimiters to the templates, based on
|
||||||
|
// settings.
|
||||||
|
if (Boolean.valueOf(props.getProperty(PROPERTY_DEVELOPER_INSERT_DELIMITERS))) {
|
||||||
|
return new DelimitingTemplateLoader(mtl);
|
||||||
|
} else {
|
||||||
|
return mtl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue