FileResolverAdapter.java
package fr.sii.ogham.template.freemarker.adapter;
import java.io.File;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import fr.sii.ogham.core.resource.resolver.DelegateResourceResolver;
import fr.sii.ogham.core.resource.resolver.FileResolver;
import fr.sii.ogham.core.resource.resolver.ResourceResolver;
import fr.sii.ogham.template.exception.ResolverAdapterConfigurationException;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
* Adapter that converts general {@link FileResolver} into FreeMarker specific
* {@link FileTemplateLoader}.
*
* @author Cyril Dejonghe
*
*/
public class FileResolverAdapter extends AbstractFreeMarkerTemplateLoaderOptionsAdapter {
private final File baseDir;
public FileResolverAdapter() {
this(new File("/"));
}
public FileResolverAdapter(File baseDir) {
super();
this.baseDir = baseDir;
}
@Override
public boolean supports(ResourceResolver resolver) {
ResourceResolver actualResolver = resolver instanceof DelegateResourceResolver ? ((DelegateResourceResolver) resolver).getActualResourceResolver() : resolver;
return actualResolver instanceof FileResolver;
}
@Override
public TemplateLoader adapt(ResourceResolver resolver) throws ResolverAdapterConfigurationException {
try {
return new FileTemplateLoaderAllowingAbsolutePaths(baseDir);
} catch (IOException e) {
throw new ResolverAdapterConfigurationException("Invalid configuration for " + FileTemplateLoader.class.getSimpleName(), resolver, e);
}
}
private static class FileTemplateLoaderAllowingAbsolutePaths extends FileTemplateLoader {
private static final boolean SEP_IS_SLASH = File.separatorChar == '/';
public FileTemplateLoaderAllowingAbsolutePaths(File baseDir) throws IOException {
super(baseDir, true);
}
@Override
public Object findTemplateSource(String name) throws IOException {
// TODO: add security option to enable/disable absolute paths outside of baseDir
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
@Override
public File run() throws IOException {
File source = new File(name);
if (source.isAbsolute() && source.isFile()) {
return source;
}
source = new File(baseDir, SEP_IS_SLASH ? name : name.replace('/', File.separatorChar));
if (!source.isFile()) {
return null;
}
return source;
}
});
} catch (PrivilegedActionException e) {
throw (IOException) e.getException();
}
}
}
}