Repository: incubator-freemarker Updated Branches: refs/heads/3 f8d405744 -> 3d0fdc8c7
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java b/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java index 8c4a48d..a54128f 100644 --- a/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java +++ b/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java @@ -19,14 +19,27 @@ package freemarker.test; import java.io.IOException; +import java.io.InputStream; import java.io.Reader; +import java.io.Serializable; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.input.ReaderInputStream; import freemarker.cache.TemplateLoader; +import freemarker.cache.TemplateLoaderSession; +import freemarker.cache.TemplateLoadingResult; +import freemarker.cache.TemplateLoadingResultStatus; +import freemarker.cache.TemplateLoadingSource; import freemarker.test.utility.TestUtil; +/** + * Removes the Apache copyright boiler plate from the beginning of the template, so that they don't mess up the expected + * template output. This can interfere with tests that try to test I/O errors and such low level things, so use with + * care. + */ public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader { private final TemplateLoader innerTemplateLoader; @@ -35,16 +48,38 @@ public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader { this.innerTemplateLoader = innerTemplateLoader; } - public Object findTemplateSource(String name) throws IOException { - return innerTemplateLoader.findTemplateSource(name); + @Override + public TemplateLoaderSession createSession() { + return null; + } + + @Override + public TemplateLoadingResult load(String name, TemplateLoadingSource ifSourceDiffersFrom, + Serializable ifVersionDiffersFrom, TemplateLoaderSession session) throws IOException { + TemplateLoadingResult result = innerTemplateLoader.load(name, ifSourceDiffersFrom, ifVersionDiffersFrom, session); + if (result.getStatus() != TemplateLoadingResultStatus.OPENED) { + return result; + } + if (result.getInputStream() != null) { + return new TemplateLoadingResult( + result.getSource(), result.getVersion(), getWithoutCopyrightHeader(result.getInputStream()), + result.getTemplateConfiguration()); + } else { + return new TemplateLoadingResult( + result.getSource(), result.getVersion(), getWithoutCopyrightHeader(result.getReader()), + result.getTemplateConfiguration()); + } } - public long getLastModified(Object templateSource) { - return innerTemplateLoader.getLastModified(templateSource); + @Override + public void resetState() { + // Do nothing } - public Reader getReader(Object templateSource, String encoding) throws IOException { - Reader reader = innerTemplateLoader.getReader(templateSource, encoding); + private Reader getWithoutCopyrightHeader(Reader reader) throws IOException { + if (reader == null) { + return null; + } try { String content = IOUtils.toString(reader); return new StringReader(TestUtil.removeFTLCopyrightComment(content)); @@ -53,8 +88,19 @@ public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader { } } - public void closeTemplateSource(Object templateSource) throws IOException { - innerTemplateLoader.closeTemplateSource(templateSource); + private InputStream getWithoutCopyrightHeader(InputStream in) throws IOException { + if (in == null) { + return null; + } + try { + // Encoding then decosing in ISO-8859-1 is binary loseless + String content = IOUtils.toString(in, StandardCharsets.ISO_8859_1.name()); + return new ReaderInputStream( + new StringReader(TestUtil.removeFTLCopyrightComment(content)), + StandardCharsets.ISO_8859_1); + } finally { + in.close(); + } } - + } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/test/MonitoredTemplateLoader.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/test/MonitoredTemplateLoader.java b/src/test/java/freemarker/test/MonitoredTemplateLoader.java index e088ab3..450ee19 100644 --- a/src/test/java/freemarker/test/MonitoredTemplateLoader.java +++ b/src/test/java/freemarker/test/MonitoredTemplateLoader.java @@ -16,31 +16,312 @@ * specific language governing permissions and limitations * under the License. */ - package freemarker.test; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.Serializable; +import java.io.StringReader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.google.common.base.Objects; -import freemarker.cache.StringTemplateLoader; +import freemarker.cache.TemplateLoader; +import freemarker.cache.TemplateLoaderSession; +import freemarker.cache.TemplateLoadingResult; +import freemarker.cache.TemplateLoadingResultStatus; +import freemarker.cache.TemplateLoadingSource; -public class MonitoredTemplateLoader extends StringTemplateLoader { +public class MonitoredTemplateLoader implements TemplateLoader { + + private final List<AbstractTemplateLoader2Event> events + = Collections.synchronizedList(new ArrayList<AbstractTemplateLoader2Event>()); - private final List<String> templatesTried = new ArrayList<String>(); + private Map<String, StoredTemplate> templates + = new ConcurrentHashMap<String, MonitoredTemplateLoader.StoredTemplate>(); + + @Override + public TemplateLoaderSession createSession() { + events.add(CreateSessionEvent.INSTANCE); + return new MonitoredTemplateLoader2Session(); + } + + @Override + public TemplateLoadingResult load(String name, TemplateLoadingSource ifSourceDiffersFrom, Serializable ifVersionDiffersFrom, + TemplateLoaderSession session) + throws IOException { + TemplateLoadingResult result = loadInner(name, ifSourceDiffersFrom, ifVersionDiffersFrom, session); + events.add(new LoadEvent(name, result.getStatus())); + return result; + } + + private TemplateLoadingResult loadInner(String name, TemplateLoadingSource ifSourceDiffersFrom, + Serializable ifVersionDiffersFrom, TemplateLoaderSession session) throws UnsupportedEncodingException { + if (session.isClosed()) { + throw new IllegalArgumentException("Template loader session is already closed."); + } + + StoredTemplate storedTemplate = templates.get(name); + if (storedTemplate == null) { + return TemplateLoadingResult.NOT_FOUND; + } + + TemplateLoadingSource source = storedTemplate.getSource(); + Serializable version = storedTemplate.getVersion(); + if (ifSourceDiffersFrom != null + && ifSourceDiffersFrom.equals(source) + && Objects.equal(ifVersionDiffersFrom, version)) { + return TemplateLoadingResult.NOT_MODIFIED; + } + + String content = storedTemplate.getContent(); + return storedTemplate.inputStreamEncoding == null + ? new TemplateLoadingResult(source, version, new StringReader(content), null) + : new TemplateLoadingResult(source, version, + new ByteArrayInputStream(content.getBytes(storedTemplate.inputStreamEncoding)), null); + } @Override - public Object findTemplateSource(String name) { - templatesTried.add(name); - return super.findTemplateSource(name); + public void resetState() { + events.add(ResetStateEvent.INSTANCE); + } + + public StoredTemplate putTextTemplate(String name, String content) { + return putTextTemplate(name, "v1", content); + } + + public StoredTemplate putTextTemplate(String name, Serializable version, String content) { + StoredTemplate storedTemplate = new StoredTemplate(name, version, content, null); + templates.put(name, storedTemplate); + return storedTemplate; + } + + public StoredTemplate putBinaryTemplate(String name, String content) { + return putBinaryTemplate(name, content, "v1"); + } + + public StoredTemplate putBinaryTemplate(String name, String content, Serializable version) { + return putBinaryTemplate(name, content, null, version); + } + + public StoredTemplate putBinaryTemplate(String name, String content, + Charset inputStreamEncoding, Serializable version) { + StoredTemplate storedTemplate = new StoredTemplate(name, version, content, + inputStreamEncoding != null ? inputStreamEncoding : StandardCharsets.UTF_8); + templates.put(name, storedTemplate); + return storedTemplate; + } + + public List<AbstractTemplateLoader2Event> getEvents() { + return events; + } + + /** + * Gets a filtered event list. + */ + @SuppressWarnings("unchecked") + public <E extends AbstractTemplateLoader2Event> List<E> getEvents(Class<E> eventClass) { + List<E> result = new ArrayList<>(); + for (AbstractTemplateLoader2Event event : events) { + if (eventClass.isInstance(event)) { + result.add((E) event); + } + } + return result; + } + + /** + * Extract from the {@link #getEvents()} the template names for which {@link TemplateLoader#load} was called. + */ + public List<String> getLoadNames() { + List<String> result = new ArrayList<>(); + for (AbstractTemplateLoader2Event event : events) { + if (event instanceof LoadEvent) { + result.add(((LoadEvent) event).name); + } + } + return result; + } + + public void clearEvents() { + events.clear(); + } + + @SuppressWarnings("serial") + public static class StoredTemplate implements TemplateLoadingSource { + private String name; + private Serializable version; + private String content; + private Charset inputStreamEncoding; + + private StoredTemplate(String name, Serializable version, String content, Charset inputStreamEncoding) { + this.name = name; + this.version = version; + this.content = content; + this.inputStreamEncoding = inputStreamEncoding; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public TemplateLoadingSource getSource() { + return this; + } + + public Serializable getVersion() { + return version; + } + + public void setVersion(Serializable version) { + this.version = version; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Charset getInputStreamEncoding() { + return inputStreamEncoding; + } + + public void setInputStreamEncoding(Charset inputStreamEncoding) { + this.inputStreamEncoding = inputStreamEncoding; + } + } - public List<String> getTemplatesTried() { - return templatesTried; + public abstract static class AbstractTemplateLoader2Event { + // empty } + + public static class LoadEvent extends AbstractTemplateLoader2Event { + private final String name; + private final TemplateLoadingResultStatus resultStatus; + + public LoadEvent(String name, TemplateLoadingResultStatus resultStatus) { + this.name = name; + this.resultStatus = resultStatus; + } + + public String getName() { + return name; + } + + public TemplateLoadingResultStatus getResultStatus() { + return resultStatus; + } - public void clear() { - templatesTried.clear(); + @Override + public String toString() { + return "LoadEvent [name=" + name + ", resultStatus=" + resultStatus + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((resultStatus == null) ? 0 : resultStatus.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + LoadEvent other = (LoadEvent) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (resultStatus != other.resultStatus) + return false; + return true; + } + } + + public static class ResetStateEvent extends AbstractTemplateLoader2Event { + public static ResetStateEvent INSTANCE = new ResetStateEvent(); + + private ResetStateEvent() { + // + } + + @Override + public String toString() { + return "ResetStateEvent []"; + } + + } + + public static class CreateSessionEvent extends AbstractTemplateLoader2Event { + + public static CreateSessionEvent INSTANCE = new CreateSessionEvent(); + + private CreateSessionEvent() { + // + } + + @Override + public String toString() { + return "CreateSessionEvent []"; + } + + } + + public static class CloseSessionEvent extends AbstractTemplateLoader2Event { + + public static CloseSessionEvent INSTANCE = new CloseSessionEvent(); + + private CloseSessionEvent() { + // + } + + @Override + public String toString() { + return "CloseSessionEvent []"; + } + + } + + public class MonitoredTemplateLoader2Session implements TemplateLoaderSession { + + private boolean closed; + + @Override + public void close() { + closed = true; + events.add(CloseSessionEvent.INSTANCE); + } + + @Override + public boolean isClosed() { + return closed; + } + + } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/test/TemplateTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/test/TemplateTest.java b/src/test/java/freemarker/test/TemplateTest.java index 5a1cdec..b1d22f6 100644 --- a/src/test/java/freemarker/test/TemplateTest.java +++ b/src/test/java/freemarker/test/TemplateTest.java @@ -19,12 +19,15 @@ package freemarker.test; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -33,8 +36,8 @@ import org.apache.commons.io.IOUtils; import org.junit.Ignore; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import freemarker.cache.ByteArrayTemplateLoader; import freemarker.cache.MultiTemplateLoader; -import freemarker.cache.StringTemplateLoader; import freemarker.cache.TemplateLoader; import freemarker.core.ParseException; import freemarker.template.Configuration; @@ -166,33 +169,33 @@ public abstract class TemplateTest { protected void addTemplate(String name, String content) { Configuration cfg = getConfiguration(); TemplateLoader tl = cfg.getTemplateLoader(); - StringTemplateLoader stl; + ByteArrayTemplateLoader btl; if (tl != null) { - stl = extractStringTemplateLoader(tl); + btl = extractByteArrayTemplateLoader(tl); } else { - stl = new StringTemplateLoader(); - cfg.setTemplateLoader(stl); + btl = new ByteArrayTemplateLoader(); + cfg.setTemplateLoader(btl); } - stl.putTemplate(name, content); + btl.putTemplate(name, content.getBytes(StandardCharsets.UTF_8)); } - private StringTemplateLoader extractStringTemplateLoader(TemplateLoader tl) { + private ByteArrayTemplateLoader extractByteArrayTemplateLoader(TemplateLoader tl) { if (tl instanceof MultiTemplateLoader) { MultiTemplateLoader mtl = (MultiTemplateLoader) tl; for (int i = 0; i < mtl.getTemplateLoaderCount(); i++) { TemplateLoader tli = mtl.getTemplateLoader(i); - if (tli instanceof StringTemplateLoader) { - return (StringTemplateLoader) tli; + if (tli instanceof ByteArrayTemplateLoader) { + return (ByteArrayTemplateLoader) tli; } } throw new IllegalStateException( - "The template loader was a MultiTemplateLoader that didn't contain StringTemplateLoader: " + "The template loader was a MultiTemplateLoader that didn't contain ByteArrayTemplateLoader: " + tl); - } else if (tl instanceof StringTemplateLoader) { - return (StringTemplateLoader) tl; + } else if (tl instanceof ByteArrayTemplateLoader) { + return (ByteArrayTemplateLoader) tl; } else { throw new IllegalStateException( - "The template loader was already set to a non-StringTemplateLoader non-MultiTemplateLoader: " + "The template loader was already set to a non-ByteArrayTemplateLoader non-MultiTemplateLoader: " + tl); } }
