如何渲染路径中有符号链接的freemarker模板?

时间:2013-06-10 22:03:49

标签: java content-management-system symlink freemarker

我正在尝试使用FreeMarker来呈现来自CMS路径的一些模板,这些模板恰好包含符号链接(在Linux下)。我们的CMS代码处理模板的路径,例如,此路径:

/var/cms/live/display/main.html

真指出:

/var/cms/trunk/127/display/main.html

/var/cms/live是基本目录,而/display/main.html是路径。

就我而言,live是一个符号链接 - 在本例中是trunk/127。仅供参考:主干是我们的SVN分支。当我们的CMS系统下载新版本的CMS文件(例如)trunk-128.zip时,它会将其解压缩到trunk/128,然后将符号链接(原子地)更改为trunk/128。大。

问题是FreeMarker似乎缓存了trunk/127路径。它无法识别文件/var/cms/live/display/main.html已更新,如果删除trunk/127树,则会生成500错误。

500 Unable to load template: /display/main.html

如何让FreeMarker缓存正确的路径?

1 个答案:

答案 0 :(得分:2)

问题原来是FreeMarker的FileTemplateLoader课程。它对传递给构造函数的基目录进行baseDir.getCanonicalFile(...)调用。当我们的应用程序启动时,基本目录/var/cms/live将被/var/cms/trunk/127/解析为真实路径getCanonicalFile(...),因此将忽略对符号链接的任何未来更改。

它在构造函数中执行此操作,因此我们不得不创建自己的LocalFileTemplateLoader,如下所示。

它只是TemplateLoader的基本弹簧加载实现。然后,当我们构建FreeMarker配置时,我们设置了模板加载器:

 Configuration config = new Configuration();
 LocalTemplateLoader loader = new LocalTemplateLoader();
 // this is designed for spring
 loader.setBaseDir("/var/cms/live");
 config.setTemplateLoader(loader);
 ...

这是我们的LocalFileTemplateLoader代码。 Full class on pastebin

public class LocalFileTemplateLoader implements TemplateLoader {

    public File baseDir;

    @Override
    public Object findTemplateSource(String name) {
        File source = new File(baseDir, name);
        if (source.isFile()) {
            return source;
        } else {
            return null;
        }
    }

    @Override
    public long getLastModified(Object templateSource) {
        if (templateSource instanceof File) {
            return new Long(((File) templateSource).lastModified());
        } else {
            throw new IllegalArgumentException("templateSource is an unknown type: " + templateSource.getClass());
        }
    }

    @Override
    public Reader getReader(Object templateSource, String encoding) throws IOException {
        if (templateSource instanceof File) {
            return new InputStreamReader(new FileInputStream((File) templateSource), encoding);
        } else {
            throw new IllegalArgumentException("templateSource is an unknown type: " + templateSource.getClass());
        }
    }

    @Override
    public void closeTemplateSource(Object templateSource) {
        // noop
    }

    @Required
    public void setBaseDir(File baseDir) {
        this.baseDir = baseDir;
        // it may not exist yet because CMS is going to download and create it
    }
}