freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [2/5] incubator-freemarker git commit: - Totally redesigned TemplateLoader interface. The FM2 TemplateLoader can't be adapted (wrapped) to it, but usually
Date Fri, 10 Feb 2017 23:47:06 GMT
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/main/javacc/FTL.jj
----------------------------------------------------------------------
diff --git a/src/main/javacc/FTL.jj b/src/main/javacc/FTL.jj
index 2d40054..e200ddc 100644
--- a/src/main/javacc/FTL.jj
+++ b/src/main/javacc/FTL.jj
@@ -76,6 +76,8 @@ public class FMParser {
     private int autoEscapingPolicy;
     private boolean autoEscaping;
     private ParserConfiguration pCfg;
+    private TemplateSpecifiedEncodingHandler templateSpecifiedEncodingHandler;
+    private boolean templateSpecifiedEncodingHandlerInvoked;
 
     /** Keeps track of #list and #foreach nesting. */
     private List/*<ParserIteratorBlockContext>*/ iteratorBlockContexts;
@@ -94,8 +96,9 @@ public class FMParser {
     private LinkedList escapes = new LinkedList();
     private int mixedContentNesting; // for stripText
 
-    FMParser(Template template, Reader reader, ParserConfiguration pCfg) {
-        this(template, true, readerToTokenManager(reader, pCfg), pCfg);
+    FMParser(Template template, Reader reader, ParserConfiguration pCfg,
+    		TemplateSpecifiedEncodingHandler templateSpecifiedEncodingHandler) {
+        this(template, true, readerToTokenManager(reader, pCfg), pCfg, templateSpecifiedEncodingHandler);
     }
 
     private static FMParserTokenManager readerToTokenManager(Reader reader, ParserConfiguration pCfg) {
@@ -104,11 +107,15 @@ public class FMParser {
         return new FMParserTokenManager(simpleCharStream);
     }
 
-    FMParser(Template template, boolean newTemplate, FMParserTokenManager tkMan, ParserConfiguration pCfg) {
+    FMParser(Template template, boolean newTemplate, FMParserTokenManager tkMan, ParserConfiguration pCfg,
+    		TemplateSpecifiedEncodingHandler templateSpecifiedEncodingHandler) {
         this(tkMan);
 
         NullArgumentException.check(pCfg);
         this.pCfg = pCfg;
+        
+        NullArgumentException.check(templateSpecifiedEncodingHandler);
+        this.templateSpecifiedEncodingHandler = templateSpecifiedEncodingHandler;
 
         NullArgumentException.check(template);
         this.template = template;
@@ -4049,10 +4056,8 @@ void HeaderElement() :
                             if (vs == null) {
                                 throw new ParseException("Expected a string constant for \"" + ks + "\".", exp);
                             }
-                            String encoding = template.getEncoding();
-                            if (encoding != null && !encoding.equalsIgnoreCase(vs)) {
-                                throw new Template.WrongEncodingException(vs, encoding);
-                            }
+                            templateSpecifiedEncodingHandlerInvoked = true;
+                            templateSpecifiedEncodingHandler.handle(vs, template.getEncoding());
                         } else if (ks.equalsIgnoreCase("STRIP_WHITESPACE") || ks.equals("stripWhitespace")) {
                             this.stripWhitespace = getBoolean(exp, true);
                         } else if (ks.equalsIgnoreCase("STRIP_TEXT") || ks.equals("stripText")) {
@@ -4241,6 +4246,13 @@ TemplateElement Root() :
         LOOKAHEAD([<STATIC_TEXT_WS>](<TRIVIAL_FTL_HEADER>|<FTL_HEADER>))
         HeaderElement()
     ]
+    {
+        if (!templateSpecifiedEncodingHandlerInvoked) {
+	        templateSpecifiedEncodingHandlerInvoked = true;
+	        templateSpecifiedEncodingHandler.handle(null, template.getEncoding());
+        }
+    }
+    
     children = MixedContentElements()
     <EOF>
     {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/manual/en_US/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/src/manual/en_US/FM3-CHANGE-LOG.txt b/src/manual/en_US/FM3-CHANGE-LOG.txt
index 4ba48fb..c860692 100644
--- a/src/manual/en_US/FM3-CHANGE-LOG.txt
+++ b/src/manual/en_US/FM3-CHANGE-LOG.txt
@@ -1,3 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+ 
 Because the Manual won't be updated for a good while, I will lead
 the FreeMarer 3 changelog here:
 
@@ -17,4 +36,28 @@ the FreeMarer 3 changelog here:
 - Removed the strict_syntax setting, and so also the support for FTL tags without #. This was a FreeMarker 1.x
   compatibility option.
 - Removed deprecated FMParser contstructors.
-- Minimum Java version increased to 7, but without try-with-resource as that's unavailable before Android 4.4 KitKat.
\ No newline at end of file
+- Minimum Java version increased to 7, but without try-with-resource as that's unavailable before Android 4.4 KitKat.
+- Totally redesigned TemplateLoader interface. The FM2 TemplateLoader can't be adapted (wrapped) to it, but usually
+  it's fairly trivial to "rearrange" an old custom TemplateLoader for the new interface. The new TemplateLoader comes
+  with several advantages, such as:
+  - It can work more efficiently with sophisticated storage mechanisms like a database, as it's now possible to pack
+    together the existence check, the last modification change check, and reading operations into less storage level
+    operations (like you can do all of them with a single SQL statement).
+  - The new TemplateLoader allows returning the template content either as an InputStream or as a Reader. Almost all
+    TemplateLoader-s should return InputStream, and FreeMarker takes care of charset issues transparently (as a result,
+    TemplateLoader-s don't have to support re-reading a template anymore, as we solve charset detection misses in
+    memory). TemplateLoader-s that are inherently backed by text (String-s), such as templates stored in a varchar or
+    CLOB column, should return a Reader. Note that templates created from a Reader will have template.getEncoding()
+    null (logically, as no charset was involved), which was impossible in FreeMarker 2.
+  - The change detection of the template doesn't have to rely on a millisecond resolution timestamp anymore; you can
+    use what's most appropriate for the storage mechanism, such as a cryptographic hash or a revision number.
+  - Template lookups (where you try multiple names until you find the best template) can now be transactional and/or
+    atomic if the backing storage mechanism supports that, by utilizing the TemplateLoaderSession interface.
+  - TemplateLoader can now return template-level settings like the output format (MIME type basically) of the loaded
+    template, in case the backing storage stores such extra information. This mechanism can be used together with
+    the TemplateConfiguration mechanism (already familiar from FreeMarker 2), and overrides the individual settings
+    coming from there.
+- Template constructors won't close the Reader passed in as agrument anymore (because a Reader should be closed
+  by who has created it). This avoids some surprises from the past, such as the unablility to reset a Reader to a mark
+  after parsing. If you call those constructors, be sure that you close the Reader yourself. (Obviously, it doesn't
+  mater for StringReader-s.)

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java b/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
index e4b14f3..8878a48 100644
--- a/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
+++ b/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
@@ -18,9 +18,13 @@
  */
 package freemarker.cache;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
 
 import org.apache.commons.io.IOUtils;
 import org.junit.Test;
@@ -38,10 +42,10 @@ public class MultiTemplateLoaderTest {
         stl2.putTemplate("both.ftl", "both 2");
         
         MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { stl1, stl2 });
-        assertEquals("1", getTemplate(mtl, "1.ftl"));
-        assertEquals("2", getTemplate(mtl, "2.ftl"));
-        assertEquals("both 1", getTemplate(mtl, "both.ftl"));
-        assertNull(getTemplate(mtl, "neither.ftl"));
+        assertEquals("1", getTemplateContent(mtl, "1.ftl"));
+        assertEquals("2", getTemplateContent(mtl, "2.ftl"));
+        assertEquals("both 1", getTemplateContent(mtl, "both.ftl"));
+        assertNull(getTemplateContent(mtl, "neither.ftl"));
     }
 
     @Test
@@ -58,28 +62,37 @@ public class MultiTemplateLoaderTest {
         StringTemplateLoader stl1 = new StringTemplateLoader();
         stl1.putTemplate("both.ftl", "both 1");
         
-        StringTemplateLoader stl2 = new StringTemplateLoader();
-        stl2.putTemplate("both.ftl", "both 2");
+        ByteArrayTemplateLoader stl2 = new ByteArrayTemplateLoader();
+        stl2.putTemplate("both.ftl", "both 2".getBytes(StandardCharsets.UTF_8));
 
         MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { stl1, stl2 });
         mtl.setSticky(sticky);
         
-        assertEquals("both 1", getTemplate(mtl, "both.ftl"));
+        assertEquals("both 1", getTemplateContent(mtl, "both.ftl"));
         assertTrue(stl1.removeTemplate("both.ftl"));
-        assertEquals("both 2", getTemplate(mtl, "both.ftl"));
+        assertEquals("both 2", getTemplateContent(mtl, "both.ftl"));
         stl1.putTemplate("both.ftl", "both 1");
-        assertEquals(sticky ? "both 2" : "both 1", getTemplate(mtl, "both.ftl"));
+        assertEquals(sticky ? "both 2" : "both 1", getTemplateContent(mtl, "both.ftl"));
         assertTrue(stl2.removeTemplate("both.ftl"));
-        assertEquals("both 1", getTemplate(mtl, "both.ftl"));
+        assertEquals("both 1", getTemplateContent(mtl, "both.ftl"));
     }
     
-    private String getTemplate(TemplateLoader tl, String name) throws IOException {
-        Object tSrc = tl.findTemplateSource(name);
-        if (tSrc == null) {
-            return null;
+    private String getTemplateContent(TemplateLoader tl, String name) throws IOException {
+        TemplateLoaderSession ses = tl.createSession();
+        try {
+            TemplateLoadingResult res = tl.load(name, null, null, ses);
+            if (res.getStatus() == TemplateLoadingResultStatus.NOT_FOUND) {
+                return null;
+            }
+            return IOUtils.toString(
+                    res.getReader() != null
+                            ? res.getReader()
+                            : new InputStreamReader(res.getInputStream(), StandardCharsets.UTF_8));
+        } finally {
+            if (ses != null) {
+                ses.close();
+            }
         }
-        
-        return IOUtils.toString(tl.getReader(tSrc, "UTF-8"));
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/cache/TemplateCacheTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/TemplateCacheTest.java b/src/test/java/freemarker/cache/TemplateCacheTest.java
index b1988b2..53763ca 100644
--- a/src/test/java/freemarker/cache/TemplateCacheTest.java
+++ b/src/test/java/freemarker/cache/TemplateCacheTest.java
@@ -19,29 +19,40 @@
 
 package freemarker.cache;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
-import java.io.Reader;
-import java.net.URL;
+import java.io.Serializable;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.Locale;
 
 import org.hamcrest.Matchers;
 import org.junit.Test;
 
+import com.google.common.collect.ImmutableList;
+
 import freemarker.core.ParseException;
 import freemarker.template.Configuration;
 import freemarker.template.MalformedTemplateNameException;
 import freemarker.template.Template;
 import freemarker.template.TemplateNotFoundException;
-import freemarker.template.Version;
+import freemarker.test.MonitoredTemplateLoader;
+import freemarker.test.MonitoredTemplateLoader.CloseSessionEvent;
+import freemarker.test.MonitoredTemplateLoader.CreateSessionEvent;
+import freemarker.test.MonitoredTemplateLoader.LoadEvent;
 
 public class TemplateCacheTest {
 
     @Test
     public void testCachedException() throws Exception {
         MockTemplateLoader loader = new MockTemplateLoader();
-        TemplateCache cache = new TemplateCache(loader, new StrongCacheStorage());
+        TemplateCache cache = new TemplateCache(
+                loader, new StrongCacheStorage(), new Configuration(Configuration.VERSION_3_0_0));
         cache.setDelay(1000L);
         loader.setThrowException(true);
         try {
@@ -49,7 +60,7 @@ public class TemplateCacheTest {
             fail();
         } catch (IOException e) {
             assertEquals("mock IO exception", e.getMessage());
-            assertEquals(1, loader.getFindCount());
+            assertEquals(1, loader.getLoadAttemptCount());
             try {
                 cache.getTemplate("t", Locale.getDefault(), "", true);
                 fail();
@@ -59,7 +70,7 @@ public class TemplateCacheTest {
                         Matchers.allOf(Matchers.containsString("There was an error loading the template on an " +
                         "earlier attempt")));
                 assertSame(e, e2.getCause());
-                assertEquals(1, loader.getFindCount());
+                assertEquals(1, loader.getLoadAttemptCount());
                 try {
                     Thread.sleep(1100L);
                     cache.getTemplate("t", Locale.getDefault(), "", true);
@@ -67,7 +78,7 @@ public class TemplateCacheTest {
                 } catch (IOException e3) {
                     // Cache had to retest
                     assertEquals("mock IO exception", e.getMessage());
-                    assertEquals(2, loader.getFindCount());
+                    assertEquals(2, loader.getLoadAttemptCount());
                 }
             }
         }
@@ -80,47 +91,46 @@ public class TemplateCacheTest {
         cache.setDelay(1000L);
         cache.setLocalizedLookup(false);
         assertNull(cache.getTemplate("t", Locale.getDefault(), "", true));
-        assertEquals(1, loader.getFindCount());
+        assertEquals(1, loader.getLoadAttemptCount());
         assertNull(cache.getTemplate("t", Locale.getDefault(), "", true));
         // Still 1 - returned cached exception
-        assertEquals(1, loader.getFindCount());
+        assertEquals(1, loader.getLoadAttemptCount());
         Thread.sleep(1100L);
         assertNull(cache.getTemplate("t", Locale.getDefault(), "", true));
         // Cache had to retest
-        assertEquals(2, loader.getFindCount());
+        assertEquals(2, loader.getLoadAttemptCount());
     }
 
     private static class MockTemplateLoader implements TemplateLoader {
         private boolean throwException;
-        private int findCount; 
+        private int loadAttemptCount; 
         
         public void setThrowException(boolean throwException) {
            this.throwException = throwException;
         }
         
-        public int getFindCount() {
-            return findCount;
+        public int getLoadAttemptCount() {
+            return loadAttemptCount;
         }
         
-        public void closeTemplateSource(Object templateSource)
-                throws IOException {
+        @Override
+        public TemplateLoaderSession createSession() {
+            return null;
         }
 
-        public Object findTemplateSource(String name) throws IOException {
-            ++findCount;
+        @Override
+        public TemplateLoadingResult load(String name, TemplateLoadingSource ifSourceDiffersFrom,
+                Serializable ifVersionDiffersFrom, TemplateLoaderSession session) throws IOException {
+            ++loadAttemptCount;
             if (throwException) {
                 throw new IOException("mock IO exception");
             }
-            return null;
+            return TemplateLoadingResult.NOT_FOUND;
         }
 
-        public long getLastModified(Object templateSource) {
-            return 0;
-        }
-
-        public Reader getReader(Object templateSource, String encoding)
-                throws IOException {
-            return null;
+        @Override
+        public void resetState() {
+            //
         }
         
     }
@@ -194,103 +204,180 @@ public class TemplateCacheTest {
     }
 
     @Test
-    public void testZeroUpdateDelay() throws IOException {
-        Configuration cfg = new Configuration();
+    public void testZeroUpdateDelay() throws IOException, InterruptedException {
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setLocale(Locale.US);
         cfg.setCacheStorage(new StrongCacheStorage());
-        StringTemplateLoader loader = new StringTemplateLoader();
+        MonitoredTemplateLoader loader = new MonitoredTemplateLoader();
         cfg.setTemplateLoader(loader);
-        cfg.setTemplateUpdateDelay(0);
+        cfg.setTemplateUpdateDelayMilliseconds(0);
         for (int i = 1; i <= 3; i++) {
-            loader.putTemplate("t.ftl", "v" + i, i);
+            loader.putTextTemplate("t.ftl", "v" + i);
             assertEquals("v" + i, cfg.getTemplate("t.ftl").toString());
         }
+
+        loader.clearEvents();
+        loader.putTextTemplate("t.ftl", "v8");
+        assertEquals("v8", cfg.getTemplate("t.ftl").toString());
+        assertEquals("v8", cfg.getTemplate("t.ftl").toString());
+        loader.putTextTemplate("t.ftl", "v9");
+        assertEquals("v9", cfg.getTemplate("t.ftl").toString());
+        assertEquals("v9", cfg.getTemplate("t.ftl").toString());
+        assertEquals(
+                ImmutableList.of(
+                        new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v8
+                        new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED),
+
+                        new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v8
+                        new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED),
+                        
+                        new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v9
+                        new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED),
+
+                        new LoadEvent("t_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND), // v9
+                        new LoadEvent("t_en.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED)
+                ),
+                loader.getEvents(LoadEvent.class));
         
-        loader.putTemplate("t.ftl", "v10", 10);
+        cfg.setLocalizedLookup(false);
+        loader.clearEvents();
+        loader.putTextTemplate("t.ftl", "v10");
         assertEquals("v10", cfg.getTemplate("t.ftl").toString());
-        loader.putTemplate("t.ftl", "v11", 10); // same time stamp, different content
-        assertEquals("v10", cfg.getTemplate("t.ftl").toString()); // still v10
-        assertEquals("v10", cfg.getTemplate("t.ftl").toString()); // still v10
+        loader.putTextTemplate("t.ftl", "v11"); // same time stamp, different content
+        assertEquals("v11", cfg.getTemplate("t.ftl").toString());
+        assertEquals("v11", cfg.getTemplate("t.ftl").toString());
+        assertEquals("v11", cfg.getTemplate("t.ftl").toString());
+        Thread.sleep(17L);
+        assertEquals("v11", cfg.getTemplate("t.ftl").toString());
+        loader.putTextTemplate("t.ftl", "v12");
+        assertEquals("v12", cfg.getTemplate("t.ftl").toString());
+        assertEquals("v12", cfg.getTemplate("t.ftl").toString());
+        assertEquals(
+                ImmutableList.of(
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), // v10
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), // v11
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED),
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.OPENED), // v12
+                        new LoadEvent("t.ftl", TemplateLoadingResultStatus.NOT_MODIFIED)
+                ),
+                loader.getEvents(LoadEvent.class));
     }
     
     @Test
-    public void testIncompatibleImprovementsChangesURLConCaching() throws IOException {
-        Version newVersion = Configuration.VERSION_2_3_21;
-        Version oldVersion = Configuration.VERSION_2_3_20;
+    public void testWrongEncodingReload() throws IOException {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
+        cfg.setLocale(Locale.US);
+        
+        MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
+        tl.putBinaryTemplate("utf-8_en.ftl", "<#ftl encoding='utf-8'>Béka");
+        tl.putBinaryTemplate("utf-8.ftl", "Bar");
+        tl.putBinaryTemplate("iso-8859-1_en_US.ftl", "<#ftl encoding='ISO-8859-1'>Béka", StandardCharsets.ISO_8859_1,
+                "v1");
+        cfg.setTemplateLoader(tl);
         
         {
-            Configuration cfg = new Configuration(oldVersion);
-            cfg.setTemplateUpdateDelay(0);
-            final MonitoredClassTemplateLoader templateLoader = new MonitoredClassTemplateLoader();
-            assertNull(templateLoader.getURLConnectionUsesCaches());
-            cfg.setTemplateLoader(templateLoader);
-            
-            assertNull(templateLoader.getLastTemplateSourceModification());
-            cfg.getTemplate("test.ftl");
-            assertNull(templateLoader.getLastTemplateSourceModification());
+            Template t = cfg.getTemplate("utf-8.ftl", "Utf-8");
+            assertEquals("utf-8.ftl", t.getName());
+            assertEquals("utf-8_en.ftl", t.getSourceName());
+            assertEquals("Utf-8", t.getEncoding());
+            assertEquals("Béka", t.toString());
             
-            cfg.setIncompatibleImprovements(newVersion);
-            assertNull(templateLoader.getLastTemplateSourceModification());
-            cfg.getTemplate("test.ftl");
-            assertEquals(Boolean.FALSE, templateLoader.getLastTemplateSourceModification());
+            assertEquals(
+                    ImmutableList.of(
+                            CreateSessionEvent.INSTANCE,
+                            new LoadEvent("utf-8_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                            new LoadEvent("utf-8_en.ftl", TemplateLoadingResultStatus.OPENED),
+                            CloseSessionEvent.INSTANCE),
+                    tl.getEvents());
+        }
+        
+        {
+            tl.clearEvents();
             
-            templateLoader.setURLConnectionUsesCaches(Boolean.valueOf(true));
-            templateLoader.setLastTemplateSourceModification(null);
-            cfg.getTemplate("test.ftl");
-            assertNull(templateLoader.getLastTemplateSourceModification());
+            Template t = cfg.getTemplate("utf-8.ftl", "ISO-8859-5");
+            assertEquals("utf-8.ftl", t.getName());
+            assertEquals("utf-8_en.ftl", t.getSourceName());
+            assertEquals("utf-8", t.getEncoding());
+            assertEquals("Béka", t.toString());
             
-            templateLoader.setURLConnectionUsesCaches(Boolean.valueOf(false));
-            templateLoader.setLastTemplateSourceModification(null);
-            cfg.getTemplate("test.ftl");
-            assertNull(templateLoader.getLastTemplateSourceModification());
-
-            templateLoader.setURLConnectionUsesCaches(null);
-            templateLoader.setLastTemplateSourceModification(null);
-            cfg.getTemplate("test.ftl");
-            assertEquals(Boolean.FALSE, templateLoader.getLastTemplateSourceModification());
+            assertEquals(
+                    ImmutableList.of(
+                            CreateSessionEvent.INSTANCE,
+                            new LoadEvent("utf-8_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                            new LoadEvent("utf-8_en.ftl", TemplateLoadingResultStatus.OPENED),
+                            CloseSessionEvent.INSTANCE),
+                    tl.getEvents());
+        }
+        
+        {
+            tl.clearEvents();
             
-            templateLoader.setURLConnectionUsesCaches(null);
-            cfg.setIncompatibleImprovements(oldVersion);
-            templateLoader.setLastTemplateSourceModification(null);
-            cfg.getTemplate("test.ftl");
-            assertNull(templateLoader.getLastTemplateSourceModification());
+            Template t = cfg.getTemplate("iso-8859-1.ftl", "utf-8");
+            assertEquals("iso-8859-1.ftl", t.getName());
+            assertEquals("iso-8859-1_en_US.ftl", t.getSourceName());
+            assertEquals("ISO-8859-1", t.getEncoding());
+            assertEquals("Béka", t.toString());
             
-            cfg.setTemplateLoader(new MultiTemplateLoader(
-                    new TemplateLoader[] { new MultiTemplateLoader(
-                                    new TemplateLoader[] { templateLoader }) }));
-            cfg.setIncompatibleImprovements(newVersion);
-            cfg.getTemplate("test.ftl");
-            assertEquals(Boolean.FALSE, templateLoader.getLastTemplateSourceModification());
+            assertEquals(
+                    ImmutableList.of(
+                            CreateSessionEvent.INSTANCE,
+                            new LoadEvent("iso-8859-1_en_US.ftl", TemplateLoadingResultStatus.OPENED),
+                            CloseSessionEvent.INSTANCE),
+                    tl.getEvents());
         }
     }
-    
+
     @Test
-    public void testWrongEncodingReload() throws IOException {
+    public void testNoWrongEncodingForTemplateLoader2WithReader() throws IOException {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         cfg.setLocale(Locale.US);
         
-        StringTemplateLoader tl = new StringTemplateLoader();
-        tl.putTemplate("utf-8_en.ftl", "<#ftl encoding='utf-8'>Foo");
-        tl.putTemplate("utf-8.ftl", "Bar");
+        MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
+        tl.putTextTemplate("foo_en.ftl", "<#ftl encoding='utf-8'>ő");
+        tl.putTextTemplate("foo.ftl", "B");
         cfg.setTemplateLoader(tl);
         
         {
-            Template t = cfg.getTemplate("utf-8.ftl", "Utf-8");
-            assertEquals("utf-8.ftl", t.getName());
-            assertEquals("utf-8_en.ftl", t.getSourceName());
-            assertEquals("Utf-8", t.getEncoding());
-            assertEquals("Foo", t.toString());
+            Template t = cfg.getTemplate("foo.ftl", "Utf-8");
+            assertEquals("foo.ftl", t.getName());
+            assertEquals("foo_en.ftl", t.getSourceName());
+            assertNull(t.getEncoding());
+            assertEquals("ő", t.toString());
+            
+            assertEquals(
+                    ImmutableList.of(
+                            CreateSessionEvent.INSTANCE,
+                            new LoadEvent("foo_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                            new LoadEvent("foo_en.ftl", TemplateLoadingResultStatus.OPENED),
+                            CloseSessionEvent.INSTANCE),                
+                    tl.getEvents());
         }
         
         {
-            Template t = cfg.getTemplate("utf-8.ftl", "Utf-16");
-            assertEquals("utf-8.ftl", t.getName());
-            assertEquals("utf-8_en.ftl", t.getSourceName());
-            assertEquals("utf-8", t.getEncoding());
-            assertEquals("Foo", t.toString());
+            tl.clearEvents();
+            
+            Template t = cfg.getTemplate("foo.ftl", "iso-8859-1");
+            assertEquals("foo.ftl", t.getName());
+            assertEquals("foo_en.ftl", t.getSourceName());
+            assertNull(t.getEncoding());
+            assertEquals("ő", t.toString());
+            
+            assertEquals(
+                    ImmutableList.of(
+                            CreateSessionEvent.INSTANCE,
+                            new LoadEvent("foo_en_US.ftl", TemplateLoadingResultStatus.NOT_FOUND),
+                            new LoadEvent("foo_en.ftl", TemplateLoadingResultStatus.OPENED),
+                            CloseSessionEvent.INSTANCE),                
+                    tl.getEvents());
         }
     }
-
+    
     @Test
     public void testEncodingSelection() throws IOException {
         Locale hungary = new Locale("hu", "HU"); 
@@ -298,11 +385,11 @@ public class TemplateCacheTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         cfg.setDefaultEncoding("utf-8");
         
-        StringTemplateLoader tl = new StringTemplateLoader();
-        tl.putTemplate("t.ftl", "Foo");
-        tl.putTemplate("t_de.ftl", "Vuu");
-        tl.putTemplate("t2.ftl", "<#ftl encoding='UTF-16LE'>Foo");
-        tl.putTemplate("t2_de.ftl", "<#ftl encoding='UTF-16BE'>Vuu");
+        MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
+        tl.putBinaryTemplate("t.ftl", "Foo");
+        tl.putBinaryTemplate("t_de.ftl", "Vuu");
+        tl.putBinaryTemplate("t2.ftl", "<#ftl encoding='ISO-8859-5'>пример", Charset.forName("ISO-8859-5"), "v1");
+        tl.putBinaryTemplate("t2_de.ftl", "<#ftl encoding='ISO-8859-5'>пример", Charset.forName("ISO-8859-5"), "v1");
         cfg.setTemplateLoader(tl);
 
         // No locale-to-encoding mapping exists yet:
@@ -343,22 +430,22 @@ public class TemplateCacheTest {
             Template t = cfg.getTemplate("t2.ftl", Locale.CHINESE);
             assertEquals("t2.ftl", t.getName());
             assertEquals("t2.ftl", t.getSourceName());
-            assertEquals("UTF-16LE", t.getEncoding());
-            assertEquals("Foo", t.toString());
+            assertEquals("ISO-8859-5", t.getEncoding());
+            assertEquals("пример", t.toString());
         }
         {
             Template t = cfg.getTemplate("t2.ftl", Locale.GERMANY);
             assertEquals("t2.ftl", t.getName());
             assertEquals("t2_de.ftl", t.getSourceName());
-            assertEquals("UTF-16BE", t.getEncoding());
-            assertEquals("Vuu", t.toString());
+            assertEquals("ISO-8859-5", t.getEncoding());
+            assertEquals("пример", t.toString());
         }
         {
             Template t = cfg.getTemplate("t2.ftl", hungary);
             assertEquals("t2.ftl", t.getName());
             assertEquals("t2.ftl", t.getSourceName());
-            assertEquals("UTF-16LE", t.getEncoding());
-            assertEquals("Foo", t.toString());
+            assertEquals("ISO-8859-5", t.getEncoding());
+            assertEquals("пример", t.toString());
         }
     }
     
@@ -390,44 +477,5 @@ public class TemplateCacheTest {
             // expected
         }
     }
-    
-    private static class MonitoredClassTemplateLoader extends ClassTemplateLoader {
-        
-        private Boolean lastTemplateSourceModification;
-
-        public MonitoredClassTemplateLoader() {
-            super(TemplateCacheTest.class, "");
-        }
-
-        @Override
-        public Object findTemplateSource(String name) throws IOException {
-            final URL url = getURL(name);
-            if (url == null) return null;
-            return new SpyingURLTemplateSource(url, getURLConnectionUsesCaches());
-        }
-
-        Boolean getLastTemplateSourceModification() {
-            return lastTemplateSourceModification;
-        }
-
-        void setLastTemplateSourceModification(Boolean lastTemplateSourceModification) {
-            this.lastTemplateSourceModification = lastTemplateSourceModification;
-        }
-        
-        private class SpyingURLTemplateSource extends URLTemplateSource {
-            
-            SpyingURLTemplateSource(URL url, Boolean useCaches) throws IOException {
-                super(url, useCaches);
-            }
-
-            @Override
-            void setUseCaches(boolean useCaches) {
-                setLastTemplateSourceModification(Boolean.valueOf(useCaches));
-                super.setUseCaches(useCaches);
-            }
-            
-        }
-        
-    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/cache/TemplateConfigurationFactoryTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/TemplateConfigurationFactoryTest.java b/src/test/java/freemarker/cache/TemplateConfigurationFactoryTest.java
index 663eed2..af54e0a 100644
--- a/src/test/java/freemarker/cache/TemplateConfigurationFactoryTest.java
+++ b/src/test/java/freemarker/cache/TemplateConfigurationFactoryTest.java
@@ -18,8 +18,12 @@
  */
 package freemarker.cache;
 
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -173,7 +177,7 @@ public class TemplateConfigurationFactoryTest {
         tcf.setConfiguration(cfg);
         
         try {
-            tcf.setConfiguration(Configuration.getDefaultConfiguration());
+            tcf.setConfiguration(new Configuration(Configuration.VERSION_3_0_0));
             fail();
         } catch (IllegalStateException e) {
             assertThat(e.getMessage(), containsString("TemplateConfigurationFactory"));
@@ -190,12 +194,12 @@ public class TemplateConfigurationFactoryTest {
 
     private void assertNotApplicable(TemplateConfigurationFactory tcf, String sourceName)
             throws IOException, TemplateConfigurationFactoryException {
-        assertNull(tcf.get(sourceName, "dummy"));
+        assertNull(tcf.get(sourceName, DummyTemplateLoadingSource.INSTANCE));
     }
 
     private void assertApplicable(TemplateConfigurationFactory tcf, String sourceName, TemplateConfiguration... expectedTCs)
             throws IOException, TemplateConfigurationFactoryException {
-        TemplateConfiguration mergedTC = tcf.get(sourceName, "dummy");
+        TemplateConfiguration mergedTC = tcf.get(sourceName, DummyTemplateLoadingSource.INSTANCE);
         assertNotNull("TC should have its parents Configuration set", mergedTC.getParentConfiguration());
         List<String> mergedTCAttNames = Arrays.asList(mergedTC.getCustomAttributeNames());
 
@@ -227,4 +231,9 @@ public class TemplateConfigurationFactoryTest {
         return false;
     }
     
+    @SuppressWarnings("serial")
+    private static class DummyTemplateLoadingSource implements TemplateLoadingSource {
+        private static DummyTemplateLoadingSource INSTANCE = new DummyTemplateLoadingSource();
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/cache/TemplateNameFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/TemplateNameFormatTest.java b/src/test/java/freemarker/cache/TemplateNameFormatTest.java
index 499e751..ff9013e 100644
--- a/src/test/java/freemarker/cache/TemplateNameFormatTest.java
+++ b/src/test/java/freemarker/cache/TemplateNameFormatTest.java
@@ -19,9 +19,11 @@
 
 package freemarker.cache;
 
-import static freemarker.test.hamcerst.Matchers.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static freemarker.test.hamcerst.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Locale;
@@ -227,7 +229,7 @@ public class TemplateNameFormatTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
 
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("foo\\bar.ftl", "");
+        tl.putTextTemplate("foo\\bar.ftl", "");
         cfg.setTemplateLoader(tl);
 
         {
@@ -241,8 +243,8 @@ public class TemplateNameFormatTest {
                             "foo\\bar_en_US.ftl",
                             "foo\\bar_en.ftl",
                             name),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
         }
 
         try {
@@ -255,8 +257,8 @@ public class TemplateNameFormatTest {
                             "foo\\missing_en_US.ftl",
                             "foo\\missing_en.ftl",
                             "foo\\missing.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/core/IncludeAndImportConfigurableLayersTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/IncludeAndImportConfigurableLayersTest.java b/src/test/java/freemarker/core/IncludeAndImportConfigurableLayersTest.java
index 96259d3..8ec5ede 100644
--- a/src/test/java/freemarker/core/IncludeAndImportConfigurableLayersTest.java
+++ b/src/test/java/freemarker/core/IncludeAndImportConfigurableLayersTest.java
@@ -26,7 +26,6 @@ import org.junit.Test;
 
 import freemarker.cache.ConditionalTemplateConfigurationFactory;
 import freemarker.cache.FileNameGlobMatcher;
-import freemarker.cache.StringTemplateLoader;
 import freemarker.template.Configuration;
 import freemarker.template.Template;
 import freemarker.test.TemplateTest;
@@ -317,9 +316,7 @@ public class IncludeAndImportConfigurableLayersTest extends TemplateTest {
     
     @Override
     protected Configuration createConfiguration() throws Exception {
-        Configuration cfg = new Configuration(Configuration.VERSION_2_3_24);
-        cfg.setTemplateLoader(new StringTemplateLoader());
-        return cfg;
+        return new Configuration(Configuration.VERSION_2_3_24);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/core/IncludeAndImportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/IncludeAndImportTest.java b/src/test/java/freemarker/core/IncludeAndImportTest.java
index 28161e5..8edbcf2 100644
--- a/src/test/java/freemarker/core/IncludeAndImportTest.java
+++ b/src/test/java/freemarker/core/IncludeAndImportTest.java
@@ -18,8 +18,11 @@
  */
 package freemarker.core;
 
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.lang.reflect.Method;
@@ -28,7 +31,6 @@ import java.lang.reflect.Modifier;
 import org.junit.Before;
 import org.junit.Test;
 
-import freemarker.cache.StringTemplateLoader;
 import freemarker.core.Environment.LazilyInitializedNamespace;
 import freemarker.core.Environment.Namespace;
 import freemarker.template.Configuration;
@@ -40,13 +42,6 @@ import freemarker.test.TemplateTest;
 @SuppressWarnings("boxing")
 public class IncludeAndImportTest extends TemplateTest {
 
-    @Override
-    protected Configuration createConfiguration() throws Exception {
-        Configuration cfg = super.createConfiguration();
-        cfg.setTemplateLoader(new StringTemplateLoader());
-        return cfg;
-    }
-
     @Before
     public void setup() {
         addTemplate("inc1.ftl", "[inc1]<#global inc1Cnt = (inc1Cnt!0) + 1><#global history = (history!) + 'I'>");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java b/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
index a77777c..976cb79 100644
--- a/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
+++ b/src/test/java/freemarker/core/ObjectBuilderSettingsTest.java
@@ -32,7 +32,7 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.io.IOException;
-import java.io.Reader;
+import java.io.Serializable;
 import java.io.Writer;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -54,6 +54,9 @@ import com.google.common.collect.ImmutableMap;
 import freemarker.cache.CacheStorage;
 import freemarker.cache.MruCacheStorage;
 import freemarker.cache.TemplateLoader;
+import freemarker.cache.TemplateLoaderSession;
+import freemarker.cache.TemplateLoadingResult;
+import freemarker.cache.TemplateLoadingSource;
 import freemarker.core.subpkg.PublicWithMixedConstructors;
 import freemarker.ext.beans.BeansWrapper;
 import freemarker.template.Configuration;
@@ -1504,22 +1507,19 @@ public class ObjectBuilderSettingsTest {
     public static class DummyTemplateLoader implements TemplateLoader {
 
         @Override
-        public Object findTemplateSource(String name) throws IOException {
+        public TemplateLoaderSession createSession() {
             return null;
         }
 
         @Override
-        public long getLastModified(Object templateSource) {
-            return 0;
-        }
-
-        @Override
-        public Reader getReader(Object templateSource, String encoding) throws IOException {
-            return null;
+        public TemplateLoadingResult load(String name, TemplateLoadingSource ifSourceDiffersFrom,
+                Serializable ifVersionDiffersFrom, TemplateLoaderSession session) throws IOException {
+            return TemplateLoadingResult.NOT_FOUND;
         }
 
         @Override
-        public void closeTemplateSource(Object templateSource) throws IOException {
+        public void resetState() {
+            // Do nothing
         }
         
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/core/TemplatGetEncodingTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/TemplatGetEncodingTest.java b/src/test/java/freemarker/core/TemplatGetEncodingTest.java
index a8ca84d..eb6578f 100644
--- a/src/test/java/freemarker/core/TemplatGetEncodingTest.java
+++ b/src/test/java/freemarker/core/TemplatGetEncodingTest.java
@@ -18,13 +18,17 @@
  */
 package freemarker.core;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 
 import org.junit.Test;
 
-import freemarker.cache.StringTemplateLoader;
+import freemarker.cache.ByteArrayTemplateLoader;
 import freemarker.cache.StrongCacheStorage;
 import freemarker.template.Configuration;
 import freemarker.template.MalformedTemplateNameException;
@@ -38,9 +42,9 @@ public class TemplatGetEncodingTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         {
             cfg.setDefaultEncoding("ISO-8859-2");
-            StringTemplateLoader tl = new StringTemplateLoader();
-            tl.putTemplate("t", "test");
-            tl.putTemplate("tnp", "<#test>");
+            ByteArrayTemplateLoader tl = new ByteArrayTemplateLoader();
+            tl.putTemplate("t", "test".getBytes(StandardCharsets.UTF_8));
+            tl.putTemplate("tnp", "<#test>".getBytes(StandardCharsets.UTF_8));
             cfg.setTemplateLoader(tl);
             cfg.setCacheStorage(new StrongCacheStorage());
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/ext/jsp/RealServletContainertTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/jsp/RealServletContainertTest.java b/src/test/java/freemarker/ext/jsp/RealServletContainertTest.java
index f3ef4cf..685a6e5 100644
--- a/src/test/java/freemarker/ext/jsp/RealServletContainertTest.java
+++ b/src/test/java/freemarker/ext/jsp/RealServletContainertTest.java
@@ -47,7 +47,7 @@ import com.google.common.collect.ImmutableSet;
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import freemarker.cache.ClassTemplateLoader;
 import freemarker.cache.TemplateLoader;
-import freemarker.cache.WebappTemplateLoader;
+import freemarker.cache.WebAppTemplateLoader;
 import freemarker.ext.beans.BeansWrapper;
 import freemarker.ext.beans.BeansWrapperBuilder;
 import freemarker.ext.servlet.FreemarkerServlet;
@@ -432,7 +432,7 @@ public class RealServletContainertTest extends WebAppTestCase {
             cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
             cfg.setLogTemplateExceptions(true);
             cfg.setObjectWrapper(new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build());
-            cfg.setTemplateLoader(new WebappTemplateLoader(getServletContext()));
+            cfg.setTemplateLoader(new WebAppTemplateLoader(getServletContext()));
             return cfg;
         }
 
@@ -452,7 +452,7 @@ public class RealServletContainertTest extends WebAppTestCase {
             
             {
                 TemplateLoader tl = cfg.getTemplateLoader();
-                assertTrue(tl instanceof WebappTemplateLoader);
+                assertTrue(tl instanceof WebAppTemplateLoader);
             }
             
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
index 396e4ca..e97e7e2 100644
--- a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
+++ b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
@@ -18,11 +18,22 @@
  */
 package freemarker.ext.servlet;
 
-import static freemarker.ext.servlet.FreemarkerServlet.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_CONTENT_TYPE;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_OVERRIDE_RESPONSE_LOCALE;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_RESPONSE_CHARACTER_ENCODING;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_VALUE_ALWAYS;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_VALUE_NEVER;
+import static freemarker.ext.servlet.FreemarkerServlet.INIT_PARAM_VALUE_WHEN_TEMPLATE_HAS_MIME_TYPE;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
 import java.nio.charset.UnsupportedCharsetException;
 import java.util.Locale;
 
@@ -38,10 +49,10 @@ import org.springframework.mock.web.MockHttpServletResponse;
 import org.springframework.mock.web.MockServletConfig;
 import org.springframework.mock.web.MockServletContext;
 
+import freemarker.cache.ByteArrayTemplateLoader;
 import freemarker.cache.ConditionalTemplateConfigurationFactory;
 import freemarker.cache.FileNameGlobMatcher;
 import freemarker.cache.FirstMatchTemplateConfigurationFactory;
-import freemarker.cache.StringTemplateLoader;
 import freemarker.cache.TemplateLoader;
 import freemarker.core.Environment;
 import freemarker.core.TemplateConfiguration;
@@ -567,23 +578,38 @@ public class FreemarkerServletTest {
         protected TemplateLoader createTemplateLoader(String templatePath) throws IOException {
             // Override default template loader
             if (templatePath.equals("class://")) {
-                StringTemplateLoader tl = new StringTemplateLoader();
+                ByteArrayTemplateLoader tl = new ByteArrayTemplateLoader();
                 
-                tl.putTemplate(FOO_FTL, "foo");
-                tl.putTemplate(FOO_SRC_UTF8_FTL, "foo");
-                tl.putTemplate(FOO_OUT_UTF8_FTL, "foo");
-                tl.putTemplate(CONTENT_TYPE_ATTR_FTL, "<#ftl attributes={ 'content_type': 'text/plain' }>foo");
-                tl.putTemplate(CONTENT_TYPE_ATTR_WITH_CHARSET_FTL, "<#ftl attributes={ 'content_type': 'text/plain; charset=UTF-8' }>foo");
-                tl.putTemplate(OUTPUT_FORMAT_HEADER_FTL, "<#ftl outputFormat='plainText'>foo");
+                tl.putTemplate(FOO_FTL, "foo"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(FOO_SRC_UTF8_FTL, "foo"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(FOO_OUT_UTF8_FTL, "foo"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(CONTENT_TYPE_ATTR_FTL, "<#ftl attributes={ 'content_type': 'text/plain' }>foo"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(CONTENT_TYPE_ATTR_WITH_CHARSET_FTL,
+                        "<#ftl attributes={ 'content_type': 'text/plain; charset=UTF-8' }>foo"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(OUTPUT_FORMAT_HEADER_FTL, "<#ftl outputFormat='plainText'>foo"
+                        .getBytes(StandardCharsets.UTF_8));
                 
-                tl.putTemplate(STD_OUTPUT_FORMAT_HTML_FTL, "<#ftl outputFormat='HTML'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_XHTML_FTL, "<#ftl outputFormat='XHTML'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_XML_FTL, "<#ftl outputFormat='XML'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, "<#ftl outputFormat='JavaScript'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_JSON_FTL, "<#ftl outputFormat='JSON'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_CSS_FTL, "<#ftl outputFormat='CSS'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, "<#ftl outputFormat='plainText'>");
-                tl.putTemplate(STD_OUTPUT_FORMAT_RTF_FTL, "<#ftl outputFormat='RTF'>");
+                tl.putTemplate(STD_OUTPUT_FORMAT_HTML_FTL, "<#ftl outputFormat='HTML'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_XHTML_FTL, "<#ftl outputFormat='XHTML'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_XML_FTL, "<#ftl outputFormat='XML'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, "<#ftl outputFormat='JavaScript'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_JSON_FTL, "<#ftl outputFormat='JSON'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_CSS_FTL, "<#ftl outputFormat='CSS'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, "<#ftl outputFormat='plainText'>"
+                        .getBytes(StandardCharsets.UTF_8));
+                tl.putTemplate(STD_OUTPUT_FORMAT_RTF_FTL, "<#ftl outputFormat='RTF'>"
+                        .getBytes(StandardCharsets.UTF_8));
                 
                 return tl;
             } else {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/ext/servlet/InitParamParserTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/servlet/InitParamParserTest.java b/src/test/java/freemarker/ext/servlet/InitParamParserTest.java
index 4408d0d..1970035 100644
--- a/src/test/java/freemarker/ext/servlet/InitParamParserTest.java
+++ b/src/test/java/freemarker/ext/servlet/InitParamParserTest.java
@@ -18,8 +18,13 @@
  */
 package freemarker.ext.servlet;
 
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.Collections;
@@ -30,7 +35,7 @@ import com.google.common.collect.ImmutableList;
 
 import freemarker.cache.ClassTemplateLoader;
 import freemarker.cache.MultiTemplateLoader;
-import freemarker.cache.WebappTemplateLoader;
+import freemarker.cache.WebAppTemplateLoader;
 import freemarker.template.Configuration;
 import freemarker.template.MockServletContext;
 
@@ -64,28 +69,28 @@ public class InitParamParserTest {
 
     @Test
     public void testCreateTemplateLoader() throws IOException {
-        Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
 
         {
             ClassTemplateLoader ctl = (ClassTemplateLoader) InitParamParser.createTemplateLoader(
                     "classpath:templates",
                     cfg, this.getClass(), null);
             assertEquals("templates/", ctl.getBasePackagePath());
-            assertNull(ctl.getURLConnectionUsesCaches());
+            assertEquals(Boolean.FALSE, ctl.getURLConnectionUsesCaches());
         }
 
         {
             ClassTemplateLoader ctl = (ClassTemplateLoader) InitParamParser.createTemplateLoader(
-                    "classpath:templates?settings(URLConnectionUsesCaches=false)",
+                    "classpath:templates?settings(URLConnectionUsesCaches=true)",
                     cfg, this.getClass(), null);
             assertEquals("templates/", ctl.getBasePackagePath());
-            assertEquals(Boolean.FALSE, ctl.getURLConnectionUsesCaches());
+            assertEquals(Boolean.TRUE, ctl.getURLConnectionUsesCaches());
         }
 
         {
             MultiTemplateLoader mtl = (MultiTemplateLoader) InitParamParser.createTemplateLoader(
                     "["
-                    + "templates?settings(URLConnectionUsesCaches=false, attemptFileAccess=false), "
+                    + "templates?settings(URLConnectionUsesCaches=null, attemptFileAccess=false), "
                     + "foo/templates?settings(URLConnectionUsesCaches=true), "
                     + "classpath:templates, "
                     + "classpath:foo/templates?settings(URLConnectionUsesCaches=true)"
@@ -94,16 +99,16 @@ public class InitParamParserTest {
 
             assertEquals(4, mtl.getTemplateLoaderCount());
             
-            final WebappTemplateLoader tl1 = (WebappTemplateLoader) mtl.getTemplateLoader(0);
-            assertEquals(Boolean.FALSE, tl1.getURLConnectionUsesCaches());
+            final WebAppTemplateLoader tl1 = (WebAppTemplateLoader) mtl.getTemplateLoader(0);
+            assertNull(tl1.getURLConnectionUsesCaches());
             assertFalse(tl1.getAttemptFileAccess());
             
-            final WebappTemplateLoader tl2 = (WebappTemplateLoader) mtl.getTemplateLoader(1);
+            final WebAppTemplateLoader tl2 = (WebAppTemplateLoader) mtl.getTemplateLoader(1);
             assertEquals(Boolean.TRUE, tl2.getURLConnectionUsesCaches());
             assertTrue(tl2.getAttemptFileAccess());
             
             final ClassTemplateLoader tl3 = (ClassTemplateLoader) mtl.getTemplateLoader(2);
-            assertNull(tl3.getURLConnectionUsesCaches());
+            assertEquals(Boolean.FALSE, tl3.getURLConnectionUsesCaches());
             
             final ClassTemplateLoader tl4 = (ClassTemplateLoader) mtl.getTemplateLoader(3);
             assertEquals(Boolean.TRUE, tl4.getURLConnectionUsesCaches());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/manual/ExamplesTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/ExamplesTest.java b/src/test/java/freemarker/manual/ExamplesTest.java
index 6ea8254..2ffcb55 100644
--- a/src/test/java/freemarker/manual/ExamplesTest.java
+++ b/src/test/java/freemarker/manual/ExamplesTest.java
@@ -24,9 +24,9 @@ import java.util.Properties;
 
 import org.junit.Ignore;
 
+import freemarker.cache.ByteArrayTemplateLoader;
 import freemarker.cache.ClassTemplateLoader;
 import freemarker.cache.MultiTemplateLoader;
-import freemarker.cache.StringTemplateLoader;
 import freemarker.cache.TemplateLoader;
 import freemarker.template.Configuration;
 import freemarker.test.TemplateTest;
@@ -54,7 +54,7 @@ public abstract class ExamplesTest extends TemplateTest {
 
     protected void setupTemplateLoaders(Configuration cfg) {
         cfg.setTemplateLoader(new MultiTemplateLoader(
-                new TemplateLoader[] { new StringTemplateLoader(), new ClassTemplateLoader(this.getClass(), "") }));
+                new TemplateLoader[] { new ByteArrayTemplateLoader(), new ClassTemplateLoader(this.getClass(), "") }));
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/template/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index 58b8724..31e8e53 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertThat;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.lang.reflect.Field;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -49,8 +50,8 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import freemarker.cache.ByteArrayTemplateLoader;
 import freemarker.cache.CacheStorageWithGetSize;
-import freemarker.cache.FileTemplateLoader;
 import freemarker.cache.NullCacheStorage;
 import freemarker.cache.SoftCacheStorage;
 import freemarker.cache.StringTemplateLoader;
@@ -102,7 +103,6 @@ public class ConfigurationTest extends TestCase {
         
         Configuration cfg = new Configuration();
         assertUsesLegacyObjectWrapper(cfg);
-        assertUsesLegacyTemplateLoader(cfg);
         assertEquals(cfg.getIncompatibleImprovements(), Configuration.VERSION_2_3_0);
         
         cfg.setIncompatibleImprovements(newVersion);
@@ -111,10 +111,8 @@ public class ConfigurationTest extends TestCase {
         
         cfg.setIncompatibleImprovements(oldVersion);
         assertUsesLegacyObjectWrapper(cfg);
-        assertUsesLegacyTemplateLoader(cfg);
         cfg.setIncompatibleImprovements(oldVersion);
         assertUsesLegacyObjectWrapper(cfg);
-        assertUsesLegacyTemplateLoader(cfg);
         
         cfg.setIncompatibleImprovements(newVersion);
         assertUsesNewObjectWrapper(cfg);
@@ -126,7 +124,6 @@ public class ConfigurationTest extends TestCase {
         cfg.setObjectWrapper(new SimpleObjectWrapper());
         cfg.setIncompatibleImprovements(oldVersion);
         assertSame(SimpleObjectWrapper.class, cfg.getObjectWrapper().getClass());
-        assertUsesLegacyTemplateLoader(cfg);
         
         cfg.setTemplateLoader(new StringTemplateLoader());
         cfg.setIncompatibleImprovements(newVersion);
@@ -149,7 +146,6 @@ public class ConfigurationTest extends TestCase {
 
         cfg.setIncompatibleImprovements(oldVersion);
         assertUsesLegacyObjectWrapper(cfg);
-        assertUsesLegacyTemplateLoader(cfg);
 
         cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_22);
         assertUses2322ObjectWrapper(cfg);
@@ -163,7 +159,6 @@ public class ConfigurationTest extends TestCase {
         
         cfg.setIncompatibleImprovements(oldVersion);
         assertUsesLegacyObjectWrapper(cfg);
-        assertUsesLegacyTemplateLoader(cfg);
         
         // ---
         
@@ -222,7 +217,7 @@ public class ConfigurationTest extends TestCase {
         }
         
         assertFalse(cfg.isTemplateLoaderExplicitlySet());
-        assertTrue(cfg.getTemplateLoader() instanceof FileTemplateLoader);
+        assertNull(cfg.getTemplateLoader());
         //
         cfg.setTemplateLoader(null);
         assertTrue(cfg.isTemplateLoaderExplicitlySet());
@@ -230,11 +225,11 @@ public class ConfigurationTest extends TestCase {
         //
         for (int i = 0; i < 3; i++) {
             if (i == 2) {
-                cfg.setTemplateLoader(cfg.getTemplateLoader());
+                cfg.setTemplateLoader(new StringTemplateLoader());
             }
             cfg.unsetTemplateLoader();
             assertFalse(cfg.isTemplateLoaderExplicitlySet());
-            assertTrue(cfg.getTemplateLoader() instanceof FileTemplateLoader);
+            assertNull(cfg.getTemplateLoader());
         }
         
         assertFalse(cfg.isTemplateLookupStrategyExplicitlySet());
@@ -279,22 +274,7 @@ public class ConfigurationTest extends TestCase {
     }
     
     public void testTemplateLoadingErrors() throws Exception {
-        Configuration cfg = new Configuration();
-        try {
-            cfg.getTemplate("missing.ftl");
-            fail();
-        } catch (TemplateNotFoundException e) {
-            assertThat(e.getMessage(), allOf(containsString("wasn't set"), containsString("default")));
-        }
-        
-        cfg = new Configuration(Configuration.VERSION_2_3_21);
-        try {
-            cfg.getTemplate("missing.ftl");
-            fail();
-        } catch (TemplateNotFoundException e) {
-            assertThat(e.getMessage(), allOf(containsString("wasn't set"), not(containsString("default"))));
-        }
-        
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
         cfg.setClassForTemplateLoading(this.getClass(), "nosuchpackage");
         try {
             cfg.getTemplate("missing.ftl");
@@ -318,10 +298,6 @@ public class ConfigurationTest extends TestCase {
         assertNull(cfg.getTemplateLoader());
     }
     
-    private void assertUsesLegacyTemplateLoader(Configuration cfg) {
-        assertTrue(cfg.getTemplateLoader() instanceof FileTemplateLoader);
-    }
-    
     public void testVersion() {
         Version v = Configuration.getVersion();
         assertTrue(v.intValue() > _TemplateAPI.VERSION_INT_2_3_20);
@@ -375,10 +351,10 @@ public class ConfigurationTest extends TestCase {
         cfg.setDefaultEncoding(latin1);
         cfg.setEncoding(hu, latin2);
         
-        StringTemplateLoader tl = new StringTemplateLoader();
-        tl.putTemplate(tFtl, "${1}");
-        tl.putTemplate(tEnFtl, "${1}");
-        tl.putTemplate(tUtf8Ftl, "<#ftl encoding='utf-8'>");
+        ByteArrayTemplateLoader tl = new ByteArrayTemplateLoader();
+        tl.putTemplate(tFtl, "${1}".getBytes(StandardCharsets.UTF_8));
+        tl.putTemplate(tEnFtl, "${1}".getBytes(StandardCharsets.UTF_8));
+        tl.putTemplate(tUtf8Ftl, "<#ftl encoding='utf-8'>".getBytes(StandardCharsets.UTF_8));
         cfg.setTemplateLoader(tl);
         
         // 1 args:

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/template/TemplateLookupStrategyTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/TemplateLookupStrategyTest.java b/src/test/java/freemarker/template/TemplateLookupStrategyTest.java
index 2a40c62..e0e4af4 100644
--- a/src/test/java/freemarker/template/TemplateLookupStrategyTest.java
+++ b/src/test/java/freemarker/template/TemplateLookupStrategyTest.java
@@ -19,7 +19,11 @@
 
 package freemarker.template;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.io.StringWriter;
@@ -54,8 +58,8 @@ public class TemplateLookupStrategyTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("test.ftl", "");
-        tl.putTemplate("aa/test.ftl", "");
+        tl.putTextTemplate("test.ftl", "");
+        tl.putTextTemplate("aa/test.ftl", "");
         cfg.setTemplateLoader(tl);
         
         cfg.setTemplateLookupStrategy(MyTemplateLookupStrategy.INSTANCE);
@@ -67,8 +71,8 @@ public class TemplateLookupStrategyTest {
             fail();
         } catch (TemplateNotFoundException e) {
             assertEquals("missing.ftl", e.getTemplateName());
-            assertEquals(ImmutableList.of("aa/missing.ftl", "missing.ftl"), tl.getTemplatesTried());
-            tl.clear();
+            assertEquals(ImmutableList.of("aa/missing.ftl", "missing.ftl"), tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -78,8 +82,8 @@ public class TemplateLookupStrategyTest {
             assertEquals("aa/test.ftl", t.getSourceName());
             assertEquals(locale, t.getLocale());
             assertNull(t.getCustomLookupCondition());
-            assertEquals(ImmutableList.of("aa/test.ftl"), tl.getTemplatesTried());
-            tl.clear();
+            assertEquals(ImmutableList.of("aa/test.ftl"), tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
     }
@@ -89,11 +93,11 @@ public class TemplateLookupStrategyTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("test.ftl", "");
-        tl.putTemplate("test_aa.ftl", "");
-        tl.putTemplate("test_aa_BB.ftl", "");
-        tl.putTemplate("test_aa_BB_CC.ftl", "");
-        tl.putTemplate("test_aa_BB_CC_DD.ftl", "");
+        tl.putTextTemplate("test.ftl", "");
+        tl.putTextTemplate("test_aa.ftl", "");
+        tl.putTextTemplate("test_aa_BB.ftl", "");
+        tl.putTextTemplate("test_aa_BB_CC.ftl", "");
+        tl.putTextTemplate("test_aa_BB_CC_DD.ftl", "");
         cfg.setTemplateLoader(tl);
         
         try {
@@ -108,8 +112,8 @@ public class TemplateLookupStrategyTest {
                             "missing_aa_BB.ftl",
                             "missing_aa.ftl",
                             "missing.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -121,8 +125,8 @@ public class TemplateLookupStrategyTest {
             assertEquals("missing.ftl", e.getTemplateName());
             assertEquals(
                     ImmutableList.of("missing_xx.ftl", "missing.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -134,8 +138,8 @@ public class TemplateLookupStrategyTest {
             assertEquals("missing.ftl", e.getTemplateName());
             assertEquals(
                     ImmutableList.of("missing.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         cfg.setLocalizedLookup(true);
@@ -147,8 +151,8 @@ public class TemplateLookupStrategyTest {
             assertEquals("_a_b_.ftl", e.getTemplateName());
             assertEquals(
                     ImmutableList.of("_a_b__xx_YY.ftl", "_a_b__xx.ftl", "_a_b_.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
 
@@ -160,9 +164,9 @@ public class TemplateLookupStrategyTest {
                 assertEquals("test_aa_BB_CC_DD.ftl", t.getSourceName());
                 assertEquals(locale, t.getLocale());
                 assertNull(t.getCustomLookupCondition());
-                assertEquals(ImmutableList.of("test_aa_BB_CC_DD.ftl"), tl.getTemplatesTried());
+                assertEquals(ImmutableList.of("test_aa_BB_CC_DD.ftl"), tl.getLoadNames());
                 assertNull(t.getCustomLookupCondition());
-                tl.clear();
+                tl.clearEvents();
                 cfg.clearTemplateCache();
             }
             
@@ -173,8 +177,8 @@ public class TemplateLookupStrategyTest {
                 assertEquals("test_aa_BB_CC.ftl", t.getSourceName());
                 assertEquals(locale, t.getLocale());
                 assertNull(t.getCustomLookupCondition());
-                assertEquals(ImmutableList.of("test_aa_BB_CC_XX.ftl", "test_aa_BB_CC.ftl"), tl.getTemplatesTried());
-                tl.clear();
+                assertEquals(ImmutableList.of("test_aa_BB_CC_XX.ftl", "test_aa_BB_CC.ftl"), tl.getLoadNames());
+                tl.clearEvents();
                 cfg.clearTemplateCache();
             }
             
@@ -187,8 +191,8 @@ public class TemplateLookupStrategyTest {
                 assertNull(t.getCustomLookupCondition());
                 assertEquals(
                         ImmutableList.of("test_aa_BB_XX_XX.ftl", "test_aa_BB_XX.ftl", "test_aa_BB.ftl"),
-                        tl.getTemplatesTried());
-                tl.clear();
+                        tl.getLoadNames());
+                tl.clearEvents();
                 cfg.clearTemplateCache();
             }
     
@@ -202,8 +206,8 @@ public class TemplateLookupStrategyTest {
                 assertNull(t.getCustomLookupCondition());
                 assertEquals(
                         ImmutableList.of("test.ftl"),
-                        tl.getTemplatesTried());
-                tl.clear();
+                        tl.getLoadNames());
+                tl.clearEvents();
                 cfg.clearTemplateCache();
                 cfg.setLocalizedLookup(true);
             }
@@ -217,8 +221,8 @@ public class TemplateLookupStrategyTest {
                 assertNull(t.getCustomLookupCondition());
                 assertEquals(
                         ImmutableList.of("test_aa_XX_XX_XX.ftl", "test_aa_XX_XX.ftl", "test_aa_XX.ftl", "test_aa.ftl"),
-                        tl.getTemplatesTried());
-                tl.clear();
+                        tl.getLoadNames());
+                tl.clearEvents();
                 cfg.clearTemplateCache();
             }
             
@@ -232,8 +236,8 @@ public class TemplateLookupStrategyTest {
                 assertEquals(
                         ImmutableList.of(
                                 "test_xx_XX_XX_XX.ftl", "test_xx_XX_XX.ftl", "test_xx_XX.ftl", "test_xx.ftl", "test.ftl"),
-                        tl.getTemplatesTried());
-                tl.clear();
+                        tl.getLoadNames());
+                tl.clearEvents();
                 cfg.clearTemplateCache();
             }
             
@@ -247,8 +251,8 @@ public class TemplateLookupStrategyTest {
                 assertEquals(
                         ImmutableList.of(
                             "test_xx_BB_CC_DD.ftl", "test_xx_BB_CC.ftl", "test_xx_BB.ftl", "test_xx.ftl", "test.ftl"),
-                        tl.getTemplatesTried());
-                tl.clear();
+                        tl.getLoadNames());
+                tl.clearEvents();
                 cfg.clearTemplateCache();
             }
         }
@@ -259,9 +263,9 @@ public class TemplateLookupStrategyTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("t.ftl", "");
-        tl.putTemplate("sub/i.ftl", "");
-        tl.putTemplate("x/sub/i.ftl", "");
+        tl.putTextTemplate("t.ftl", "");
+        tl.putTextTemplate("sub/i.ftl", "");
+        tl.putTextTemplate("x/sub/i.ftl", "");
         cfg.setTemplateLoader(tl);
 
         final Locale locale = new Locale("xx");
@@ -276,8 +280,8 @@ public class TemplateLookupStrategyTest {
                     ImmutableList.of(
                         "x/y/sub/i_xx.ftl", "x/sub/i_xx.ftl", "sub/i_xx.ftl",
                         "x/y/sub/i.ftl", "x/sub/i.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
 
@@ -291,8 +295,8 @@ public class TemplateLookupStrategyTest {
                     ImmutableList.of(
                         "a/b/sub/i_xx.ftl", "a/sub/i_xx.ftl", "sub/i_xx.ftl",
                         "a/b/sub/i.ftl", "a/sub/i.ftl", "sub/i.ftl"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
     }
@@ -318,17 +322,17 @@ public class TemplateLookupStrategyTest {
         final String t2OtherLocaleExpectedOutput = "i3 at foo.com";
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("@foo.com/t.ftl", tAtFooComContent);
-        tl.putTemplate("@bar.com/t.ftl", tAtBarComContent);
-        tl.putTemplate("@default/t.ftl", tAtDefaultContent);
-        tl.putTemplate("@foo.com/i.ftl", iAtFooComContent);
-        tl.putTemplate("@baaz.com/i.ftl", iAtBaazComContent);
-        tl.putTemplate("@default/i_xx.ftl", iXxAtDefaultContent);
-        tl.putTemplate("@default/i.ftl", iAtDefaultContent);
-        tl.putTemplate("@foo.com/t2.ftl", "<#import 'i2.ftl' as i2 />${proof}");
-        tl.putTemplate("@default/i2.ftl", "<#import 'i3.ftl' as i3 />");
-        tl.putTemplate("@foo.com/i3.ftl", "<#global proof = '" + t2OtherLocaleExpectedOutput + "'>");
-        tl.putTemplate("@foo.com/i3_xx.ftl", "<#global proof = '" + t2XxLocaleExpectedOutput + "'>");
+        tl.putTextTemplate("@foo.com/t.ftl", tAtFooComContent);
+        tl.putTextTemplate("@bar.com/t.ftl", tAtBarComContent);
+        tl.putTextTemplate("@default/t.ftl", tAtDefaultContent);
+        tl.putTextTemplate("@foo.com/i.ftl", iAtFooComContent);
+        tl.putTextTemplate("@baaz.com/i.ftl", iAtBaazComContent);
+        tl.putTextTemplate("@default/i_xx.ftl", iXxAtDefaultContent);
+        tl.putTextTemplate("@default/i.ftl", iAtDefaultContent);
+        tl.putTextTemplate("@foo.com/t2.ftl", "<#import 'i2.ftl' as i2 />${proof}");
+        tl.putTextTemplate("@default/i2.ftl", "<#import 'i3.ftl' as i3 />");
+        tl.putTextTemplate("@foo.com/i3.ftl", "<#global proof = '" + t2OtherLocaleExpectedOutput + "'>");
+        tl.putTextTemplate("@foo.com/i3_xx.ftl", "<#global proof = '" + t2XxLocaleExpectedOutput + "'>");
         cfg.setTemplateLoader(tl);
         
         cfg.setTemplateLookupStrategy(new DomainTemplateLookupStrategy());
@@ -344,15 +348,15 @@ public class TemplateLookupStrategyTest {
             assertEquals(tAtFooComContent, t.toString());
             assertEquals(
                     ImmutableList.of("@foo.com/t_xx.ftl", "@foo.com/t.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             assertOutputEquals(tAtFooComWithoutIncludeContent + iAtFooComContent, t);
             assertEquals(
                     ImmutableList.of("@foo.com/i_xx.ftl", "@foo.com/i.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
 
@@ -367,17 +371,17 @@ public class TemplateLookupStrategyTest {
             assertEquals(tAtBarComContent, t.toString());
             assertEquals(
                     ImmutableList.of("@bar.com/t_xx.ftl", "@bar.com/t.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             assertOutputEquals(tAtBarComWithoutIncludeContent + iXxAtDefaultContent, t);
             assertEquals(
                     ImmutableList.of(
                             "@bar.com/i_xx.ftl", "@bar.com/i.ftl",
                             "@default/i_xx.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -394,15 +398,15 @@ public class TemplateLookupStrategyTest {
                     ImmutableList.of(
                             "@baaz.com/t_xx_YY.ftl", "@baaz.com/t_xx.ftl", "@baaz.com/t.ftl",
                             "@default/t_xx_YY.ftl", "@default/t_xx.ftl", "@default/t.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             assertOutputEquals(tAtDefaultWithoutIncludeContent + iAtBaazComContent, t);
             assertEquals(
                     ImmutableList.of("@baaz.com/i_xx_YY.ftl", "@baaz.com/i_xx.ftl", "@baaz.com/i.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -419,9 +423,9 @@ public class TemplateLookupStrategyTest {
                     ImmutableList.of(
                             "@nosuch.com/i_xx_YY.ftl", "@nosuch.com/i_xx.ftl", "@nosuch.com/i.ftl",
                             "@default/i_xx_YY.ftl", "@default/i_xx.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
 
@@ -437,9 +441,9 @@ public class TemplateLookupStrategyTest {
             assertEquals(iAtDefaultContent, t.toString());
             assertEquals(
                     ImmutableList.of("@nosuch.com/i.ftl", "@default/i.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.setLocalizedLookup(true);
             cfg.clearTemplateCache();
         }
@@ -454,9 +458,9 @@ public class TemplateLookupStrategyTest {
                             "@foo.com/t2_xx.ftl", "@foo.com/t2.ftl",
                             "@foo.com/i2_xx.ftl", "@foo.com/i2.ftl", "@default/i2_xx.ftl", "@default/i2.ftl",
                             "@foo.com/i3_xx.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -470,9 +474,9 @@ public class TemplateLookupStrategyTest {
                             "@foo.com/t2_yy.ftl", "@foo.com/t2.ftl",
                             "@foo.com/i2_yy.ftl", "@foo.com/i2.ftl", "@default/i2_yy.ftl", "@default/i2.ftl",
                             "@foo.com/i3_yy.ftl", "@foo.com/i3.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -487,9 +491,9 @@ public class TemplateLookupStrategyTest {
                             "@foo.com/t2.ftl",
                             "@foo.com/i2.ftl", "@default/i2.ftl",
                             "@foo.com/i3.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.setLocalizedLookup(true);
             cfg.clearTemplateCache();
         }
@@ -500,9 +504,9 @@ public class TemplateLookupStrategyTest {
             cfg.getTemplate("i3.ftl", locale, domain, "utf-8", true, false); 
             assertEquals(
                     ImmutableList.of("@foo.com/i3_xx.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -519,9 +523,9 @@ public class TemplateLookupStrategyTest {
                     ImmutableList.of(
                             "@bar.com/i3_xx.ftl", "@bar.com/i3.ftl",
                             "@default/i3_xx.ftl", "@default/i3.ftl"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
             
-            tl.clear();
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -532,8 +536,8 @@ public class TemplateLookupStrategyTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("test.txt", "");
-        tl.putTemplate("test_aa.txt", "");
+        tl.putTextTemplate("test.txt", "");
+        tl.putTextTemplate("test_aa.txt", "");
         cfg.setTemplateLoader(tl);
         
         try {
@@ -546,8 +550,8 @@ public class TemplateLookupStrategyTest {
                             "missing_aa_BB.txt",
                             "missing_aa.txt",
                             "missing.txt"),
-                    tl.getTemplatesTried());
-            tl.clear();
+                    tl.getLoadNames());
+            tl.clearEvents();
             cfg.clearTemplateCache();
         }
         
@@ -559,7 +563,7 @@ public class TemplateLookupStrategyTest {
                     ImmutableList.of(
                             "test_aa_BB.txt",
                             "test_aa.txt"),
-                    tl.getTemplatesTried());
+                    tl.getLoadNames());
         }
     }
 
@@ -568,8 +572,8 @@ public class TemplateLookupStrategyTest {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
         
         MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
-        tl.putTemplate("test.ftl", "");
-        tl.putTemplate("test_aa.ftl", "<#wrong>");
+        tl.putTextTemplate("test.ftl", "");
+        tl.putTextTemplate("test_aa.ftl", "<#wrong>");
         cfg.setTemplateLoader(tl);
         
         try {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3d0fdc8c/src/test/java/freemarker/template/TemplateNotFoundMessageTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/TemplateNotFoundMessageTest.java b/src/test/java/freemarker/template/TemplateNotFoundMessageTest.java
index c96015c..e2ea960 100644
--- a/src/test/java/freemarker/template/TemplateNotFoundMessageTest.java
+++ b/src/test/java/freemarker/template/TemplateNotFoundMessageTest.java
@@ -19,9 +19,12 @@
 
 package freemarker.template;
 
-import static freemarker.test.hamcerst.Matchers.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static freemarker.test.hamcerst.Matchers.containsStringIgnoringCase;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
@@ -36,7 +39,7 @@ import freemarker.cache.TemplateLoader;
 import freemarker.cache.TemplateLookupContext;
 import freemarker.cache.TemplateLookupResult;
 import freemarker.cache.TemplateLookupStrategy;
-import freemarker.cache.WebappTemplateLoader;
+import freemarker.cache.WebAppTemplateLoader;
 
 public class TemplateNotFoundMessageTest {
 
@@ -59,9 +62,9 @@ public class TemplateNotFoundMessageTest {
 
     @Test
     public void testWebappTemplateLoader() throws IOException {
-        final String errMsg = failWith(new WebappTemplateLoader(new MockServletContext(), "WEB-INF/templates"));
+        final String errMsg = failWith(new WebAppTemplateLoader(new MockServletContext(), "WEB-INF/templates"));
         showErrorMessage(errMsg);
-        assertThat(errMsg, containsString("WebappTemplateLoader"));
+        assertThat(errMsg, containsString("WebAppTemplateLoader"));
         assertThat(errMsg, containsString("MyApp"));
         assertThat(errMsg, containsString("WEB-INF/templates"));
     }
@@ -83,12 +86,12 @@ public class TemplateNotFoundMessageTest {
     @Test
     public void testMultiTemplateLoader() throws IOException {
         final String errMsg = failWith(new MultiTemplateLoader(new TemplateLoader[] {
-                new WebappTemplateLoader(new MockServletContext(), "WEB-INF/templates"),
+                new WebAppTemplateLoader(new MockServletContext(), "WEB-INF/templates"),
                 new ClassTemplateLoader(this.getClass(), "foo/bar")
         }));
         showErrorMessage(errMsg);
         assertThat(errMsg, containsString("MultiTemplateLoader"));
-        assertThat(errMsg, containsString("WebappTemplateLoader"));
+        assertThat(errMsg, containsString("WebAppTemplateLoader"));
         assertThat(errMsg, containsString("MyApp"));
         assertThat(errMsg, containsString("WEB-INF/templates"));
         assertThat(errMsg, containsString("ClassTemplateLoader"));
@@ -97,18 +100,10 @@ public class TemplateNotFoundMessageTest {
 
     @Test
     public void testDefaultTemplateLoader() throws IOException {
-        Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
-        {
-            String errMsg = failWith(cfg);
-            showErrorMessage(errMsg);
-            assertThat(errMsg, allOf(containsString("setTemplateLoader"), containsString("dangerous")));
-        }
-        {
-            cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_21);
-            String errMsg = failWith(cfg);
-            showErrorMessage(errMsg);
-            assertThat(errMsg, allOf(containsString("setTemplateLoader"), containsString("null")));
-        }
+        Configuration cfg = new Configuration(Configuration.VERSION_3_0_0);
+        String errMsg = failWith(cfg);
+        showErrorMessage(errMsg);
+        assertThat(errMsg, allOf(containsString("setTemplateLoader"), containsString("null")));
     }
     
     @Test



Mime
View raw message