📄 templatecache.java
字号:
if(debug)
{
logger.debug("Compiling FreeMarker template " +
debugName + " from " + newlyFoundSource);
}
// If we get here, then we need to (re)load the template
Object source = cachedTemplate.source;
cachedTemplate.template =
loadTemplate(loader, name, locale, encoding, parse, source);
cachedTemplate.lastModified =
lastModified == Long.MIN_VALUE
? loader.getLastModified(source)
: lastModified;
return cachedTemplate.template;
}
finally
{
if(newlyFoundSource != null)
{
loader.closeTemplateSource(newlyFoundSource);
}
}
}
}
private Template loadTemplate(TemplateLoader loader, String name, Locale locale, String encoding,
boolean parse, Object source)
throws IOException
{
Template template;
Reader reader = loader.getReader(source, encoding);
try
{
if(parse)
{
try {
template = new Template(name, reader, config, encoding);
}
catch (Template.WrongEncodingException wee) {
encoding = wee.specifiedEncoding;
reader = loader.getReader(source, encoding);
template = new Template(name, reader, config, encoding);
}
template.setLocale(locale);
}
else
{
// Read the contents into a StringWriter, then construct a single-textblock
// template from it.
StringWriter sw = new StringWriter();
char[] buf = new char[4096];
for(;;)
{
int charsRead = reader.read(buf);
if (charsRead > 0)
{
sw.write(buf, 0, charsRead);
}
else if(charsRead == -1)
{
break;
}
}
template = Template.getPlainTextTemplate(name, sw.toString(), config);
template.setLocale(locale);
}
template.setEncoding(encoding);
}
finally
{
reader.close();
}
return template;
}
/**
* Gets the delay in milliseconds between checking for newer versions of a
* template source.
* @return the current value of the delay
*/
public synchronized long getDelay()
{
return delay;
}
/**
* Sets the delay in milliseconds between checking for newer versions of a
* template sources.
* @param delay the new value of the delay
*/
public synchronized void setDelay(long delay)
{
this.delay = delay;
}
/**
* Returns if localized template lookup is enabled or not.
*/
public synchronized boolean getLocalizedLookup()
{
return localizedLookup;
}
/**
* Setis if localized template lookup is enabled or not.
*/
public synchronized void setLocalizedLookup(boolean localizedLookup)
{
this.localizedLookup = localizedLookup;
}
/**
* Removes all entries from the cache, forcing reloading of templates
* on subsequent {@link #getTemplate(String, Locale, String, boolean)}
* calls.
*/
public void clear()
{
synchronized (storage) {
storage.clear();
}
}
public static String getFullTemplatePath(Environment env, String parentTemplateDir, String templateNameString)
{
if (!env.isClassicCompatible()) {
if (templateNameString.indexOf("://") >0) {
;
}
else if (templateNameString.length() > 0 && templateNameString.charAt(0) == '/') {
int protIndex = parentTemplateDir.indexOf("://");
if (protIndex >0) {
templateNameString = parentTemplateDir.substring(0, protIndex + 2) + templateNameString;
} else {
templateNameString = templateNameString.substring(1);
}
}
else {
templateNameString = parentTemplateDir + templateNameString;
}
}
return templateNameString;
}
private Object findTemplateSource(String name, Locale locale)
throws
IOException
{
if (localizedLookup) {
int lastDot = name.lastIndexOf('.');
String prefix = lastDot == -1 ? name : name.substring(0, lastDot);
String suffix = lastDot == -1 ? "" : name.substring(lastDot);
String localeName = LOCALE_SEPARATOR + locale.toString();
StringBuffer buf = new StringBuffer(name.length() + localeName.length());
buf.append(prefix);
for (;;)
{
buf.setLength(prefix.length());
String path = buf.append(localeName).append(suffix).toString();
Object templateSource = acquireTemplateSource(path);
if (templateSource != null)
{
return templateSource;
}
int lastUnderscore = localeName.lastIndexOf('_');
if (lastUnderscore == -1)
break;
localeName = localeName.substring(0, lastUnderscore);
}
return null;
}
else
{
return acquireTemplateSource(name);
}
}
private Object acquireTemplateSource(String path) throws IOException
{
int asterisk = path.indexOf(ASTERISK);
// Shortcut in case there is no acquisition
if(asterisk == -1)
{
return mainLoader.findTemplateSource(path);
}
StringTokenizer tok = new StringTokenizer(path, "/");
int lastAsterisk = -1;
List tokpath = new ArrayList();
while(tok.hasMoreTokens())
{
String pathToken = tok.nextToken();
if(pathToken.equals(ASTERISKSTR))
{
if(lastAsterisk != -1)
{
tokpath.remove(lastAsterisk);
}
lastAsterisk = tokpath.size();
}
tokpath.add(pathToken);
}
String basePath = concatPath(tokpath, 0, lastAsterisk);
String resourcePath = concatPath(tokpath, lastAsterisk + 1, tokpath.size());
if(resourcePath.endsWith("/"))
{
resourcePath = resourcePath.substring(0, resourcePath.length() - 1);
}
StringBuffer buf = new StringBuffer(path.length()).append(basePath);
int l = basePath.length();
boolean debug = logger.isDebugEnabled();
for(;;)
{
String fullPath = buf.append(resourcePath).toString();
if(debug)
{
logger.debug("Trying to find template source " + fullPath);
}
Object templateSource = mainLoader.findTemplateSource(fullPath);
if(templateSource != null)
{
return templateSource;
}
if(l == 0)
{
return null;
}
l = basePath.lastIndexOf(SLASH, l - 2) + 1;
buf.setLength(l);
}
}
private String concatPath(List path, int from, int to)
{
StringBuffer buf = new StringBuffer((to - from) * 16);
for(int i = from; i < to; ++i)
{
buf.append(path.get(i)).append('/');
}
return buf.toString();
}
private static String normalizeName(String name) {
if (name.indexOf("://") >0) {
return name;
}
for(;;) {
int parentDirPathLoc = name.indexOf(PARENT_DIR_PATH);
if(parentDirPathLoc == 0) {
// If it starts with /../, then it reaches outside the template
// root.
return null;
}
if(parentDirPathLoc == -1) {
if(name.startsWith(PARENT_DIR_PATH_PREFIX)) {
// Another attempt to reach out of template root.
return null;
}
break;
}
int previousSlashLoc = name.lastIndexOf(SLASH, parentDirPathLoc - 1);
name = name.substring(0, previousSlashLoc + 1) +
name.substring(parentDirPathLoc + PARENT_DIR_PATH.length());
}
for(;;) {
int currentDirPathLoc = name.indexOf(CURRENT_DIR_PATH);
if(currentDirPathLoc == -1) {
if(name.startsWith(CURRENT_DIR_PATH_PREFIX)) {
name = name.substring(CURRENT_DIR_PATH_PREFIX.length());
}
break;
}
name = name.substring(0, currentDirPathLoc) +
name.substring(currentDirPathLoc + CURRENT_DIR_PATH.length() - 1);
}
// Editing can leave us with a leading slash; strip it.
if(name.length() > 1 && name.charAt(0) == SLASH) {
name = name.substring(1);
}
return name;
}
/**
* This class holds a (name, locale) pair and is used as the key in
* the cached templates map.
*/
private static final class TemplateKey
{
private final String name;
private final Locale locale;
private final String encoding;
private final boolean parse;
TemplateKey(String name, Locale locale, String encoding, boolean parse)
{
this.name = name;
this.locale = locale;
this.encoding = encoding;
this.parse = parse;
}
public boolean equals(Object o)
{
if (o instanceof TemplateKey)
{
TemplateKey tk = (TemplateKey)o;
return
parse == tk.parse &&
name.equals(tk.name) &&
locale.equals(tk.locale) &&
encoding.equals(tk.encoding);
}
return false;
}
public int hashCode()
{
return
name.hashCode() ^
locale.hashCode() ^
encoding.hashCode() ^
(parse ? Boolean.FALSE : Boolean.TRUE).hashCode();
}
}
/**
* This class holds the cached template and associated information
* (the source object, and the last-checked and last-modified timestamps).
* It is used as the value in the cached templates map.
*/
private static final class CachedTemplate
{
Template template;
Object source;
long lastChecked;
long lastModified;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -