001package org.avaje.freemarker.layout; 002 003import java.io.IOException; 004import java.io.Reader; 005 006import javax.servlet.ServletContext; 007 008import org.avaje.freemarker.util.IOUtil; 009 010import freemarker.cache.TemplateLoader; 011import freemarker.cache.WebappTemplateLoader; 012 013/** 014 * Simple layout inheritance wrapper for a TemplateLoader. 015 */ 016public final class InheritLayoutTemplateLoader implements TemplateLoader { 017 018 private final TemplateLoader wrapped; 019 020 private final RawTemplateInherit inheritHandler; 021 022 /** 023 * Create a WebappTemplateLoader loader and wrap it with inheritance layout handling. 024 */ 025 public static TemplateLoader createWebappLoader(ServletContext servletContext, String templatePath) { 026 return createWebappLoader(servletContext, templatePath, null); 027 } 028 029 /** 030 * Create a TemplateLoader additionally specifying a ContentFilter. 031 */ 032 public static TemplateLoader createWebappLoader(ServletContext servletContext, String templatePath, ContentFilter contentFilter) { 033 return wrap(new WebappTemplateLoader(servletContext, templatePath), contentFilter); 034 } 035 036 /** 037 * Wrap a TemplateLoader with inheritance layout handling. 038 */ 039 public static TemplateLoader wrap(TemplateLoader baseLoader, ContentFilter contentFilter) { 040 return new InheritLayoutTemplateLoader(baseLoader, contentFilter); 041 } 042 043 /** 044 * Create wrapping a TemplateLoader. 045 */ 046 public InheritLayoutTemplateLoader(TemplateLoader wrapped, ContentFilter contentFilter) { 047 this.wrapped = wrapped; 048 this.inheritHandler = new RawTemplateInherit(new Source(wrapped), contentFilter); 049 } 050 051 public Object findTemplateSource(String name) throws IOException { 052 Object o = wrapped.findTemplateSource(name); 053 if (o == null) { 054 return null; 055 } 056 return new SourceWrapper(name, o); 057 } 058 059 public long getLastModified(Object templateSource) { 060 return wrapped.getLastModified(((SourceWrapper) templateSource).wrappedSource); 061 } 062 063 public void closeTemplateSource(Object templateSource) throws IOException { 064 wrapped.closeTemplateSource(((SourceWrapper) templateSource).wrappedSource); 065 } 066 067 public Reader getReader(Object templateSource, String encoding) throws IOException { 068 069 return inheritHandler.getReader(((SourceWrapper) templateSource).templateName, encoding); 070 } 071 072 private static final class SourceWrapper { 073 final String templateName; 074 final Object wrappedSource; 075 076 private SourceWrapper(String templateName, Object wrappedSource) { 077 this.templateName = templateName; 078 this.wrappedSource = wrappedSource; 079 } 080 } 081 082 private static class Source implements RawTemplateSource { 083 084 private final TemplateLoader wrapped; 085 086 Source(TemplateLoader wrapped) { 087 this.wrapped = wrapped; 088 } 089 090 public String getSource(String templateName, String encoding) throws IOException { 091 092 try { 093 Object s = wrapped.findTemplateSource(templateName); 094 Reader reader = wrapped.getReader(s, encoding); 095 return IOUtil.read(reader); 096 } catch (Exception e) { 097 throw new IOException("Error loading source for template: "+templateName, e); 098 } 099 } 100 } 101 102}