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
|
||||
means that a cached copy of each template will be used for 60 seconds
|
||||
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>
|
||||
</tr>
|
||||
<tr class="odd_row">
|
||||
|
@ -713,7 +713,7 @@
|
|||
see the effect of changes to the text strings.
|
||||
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.
|
||||
<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>
|
||||
</tr>
|
||||
<tr class="odd_row">
|
||||
|
@ -725,6 +725,24 @@
|
|||
</td>
|
||||
</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>
|
||||
</table>
|
||||
<h3 id="deploy">VI. Compile and deploy</h3>
|
||||
|
|
|
@ -141,7 +141,7 @@ RDFService.languageFilter = true
|
|||
# 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
|
||||
# on each request. This permits developers to immediately see the effect of
|
||||
|
@ -152,7 +152,7 @@ RDFService.languageFilter = 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
|
||||
# is read from disk on each request. This permits developers to immediately
|
||||
|
@ -162,3 +162,12 @@ RDFService.languageFilter = 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 String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatFreemarkerCache";
|
||||
private static final String PROPERTY_DEVELOPER_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters";
|
||||
|
||||
private final String themeDir;
|
||||
private final ServletContext context;
|
||||
private final ApplicationBean appBean;
|
||||
private final ConfigurationProperties props;
|
||||
|
||||
FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) {
|
||||
|
||||
this.themeDir = themeDir;
|
||||
this.context = context;
|
||||
this.appBean = appBean;
|
||||
this.props = ConfigurationProperties.getBean(context);
|
||||
|
||||
String flag = ConfigurationProperties.getBean(context).getProperty(
|
||||
PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
||||
String flag = props.getProperty(PROPERTY_DEVELOPER_DEFEAT_CACHE, "false");
|
||||
if (Boolean.valueOf(flag.trim())) {
|
||||
log.debug("Disabling Freemarker template caching in development build.");
|
||||
setTemplateUpdateDelay(0); // no template caching in development
|
||||
|
@ -211,8 +213,14 @@ public class FreemarkerConfiguration extends Configuration {
|
|||
log.error("Error creating template loaders");
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override getTemplate(), so we can apply DataGetters to all included
|
||||
|
|
Loading…
Add table
Reference in a new issue