You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2016/06/12 15:20:19 UTC

[2/2] incubator-freemarker git commit: Moved lazyImports and lazyAutoImports settings to the Configurable level, so now it can be set on all 3 levels (most importantly with TemplateConfiguration-s).

Moved lazyImports and lazyAutoImports settings to the Configurable level, so now it can be set on all 3 levels (most importantly with TemplateConfiguration-s).


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/fa855c73
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/fa855c73
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/fa855c73

Branch: refs/heads/2.3-gae
Commit: fa855c735fb9e56341309dc926c383beaed0fc41
Parents: bf13271
Author: ddekany <dd...@apache.org>
Authored: Sun Jun 12 16:50:31 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sun Jun 12 17:19:40 2016 +0200

----------------------------------------------------------------------
 src/main/java/freemarker/core/Configurable.java | 144 +++++++--
 src/main/java/freemarker/core/Environment.java  |   6 +-
 .../freemarker/core/TemplateConfiguration.java  |  14 +
 .../java/freemarker/template/Configuration.java |  84 +----
 src/manual/en_US/book.xml                       |  29 +-
 .../core/AutoImportAndIncludeTest.java          | 261 ---------------
 .../IncludeAndImportConfigurableLayersTest.java | 319 +++++++++++++++++++
 .../core/TemplateConfigurationTest.java         |   6 +-
 .../freemarker/template/ConfigurationTest.java  |   4 +
 src/test/java/freemarker/test/TemplateTest.java |   4 +
 10 files changed, 490 insertions(+), 381 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index d71b64f..8dc4762 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -80,6 +80,7 @@ import freemarker.template.utility.StringUtil;
 public class Configurable {
     static final String C_TRUE_FALSE = "true,false";
     
+    private static final String NULL = "null";
     private static final String DEFAULT = "default";
     private static final String DEFAULT_2_3_0 = "default_2_3_0";
     private static final String JVM_DEFAULT = "JVM default";
@@ -239,6 +240,20 @@ public class Configurable {
     public static final String LOG_TEMPLATE_EXCEPTIONS_KEY = LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE;
 
     /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_IMPORTS_KEY_SNAKE_CASE = "lazy_imports";
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_IMPORTS_KEY_CAMEL_CASE = "lazyImports";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String LAZY_IMPORTS_KEY = LAZY_IMPORTS_KEY_SNAKE_CASE;
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE = "lazy_auto_imports";
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE = "lazyAutoImports";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String LAZY_AUTO_IMPORTS_KEY = LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE;
+    
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
     public static final String AUTO_IMPORT_KEY_SNAKE_CASE = "auto_import";
     /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
     public static final String AUTO_IMPORT_KEY_CAMEL_CASE = "autoImport";
@@ -269,6 +284,8 @@ public class Configurable {
         CUSTOM_NUMBER_FORMATS_KEY_SNAKE_CASE,
         DATE_FORMAT_KEY_SNAKE_CASE,
         DATETIME_FORMAT_KEY_SNAKE_CASE,
+        LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE,
+        LAZY_IMPORTS_KEY_SNAKE_CASE,
         LOCALE_KEY_SNAKE_CASE,
         LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE,
         NEW_BUILTIN_CLASS_RESOLVER_KEY_SNAKE_CASE,
@@ -297,6 +314,8 @@ public class Configurable {
         CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE,
         DATE_FORMAT_KEY_CAMEL_CASE,
         DATETIME_FORMAT_KEY_CAMEL_CASE,
+        LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE,
+        LAZY_IMPORTS_KEY_CAMEL_CASE,
         LOCALE_KEY_CAMEL_CASE,
         LOG_TEMPLATE_EXCEPTIONS_KEY_CAMEL_CASE,
         NEW_BUILTIN_CLASS_RESOLVER_KEY_CAMEL_CASE,
@@ -344,6 +363,9 @@ public class Configurable {
     private Map<String, ? extends TemplateNumberFormatFactory> customNumberFormats;
     private LinkedHashMap<String, String> autoImports;
     private ArrayList<String> autoIncludes;
+    private Boolean lazyImports;
+    private Boolean lazyAutoImports;
+    private boolean lazyAutoImportsSet;
     
     /**
      * Creates a top-level configurable, one that doesn't inherit from a parent, and thus stores the default values.
@@ -426,6 +448,9 @@ public class Configurable {
         customDateFormats = Collections.emptyMap();
         customNumberFormats = Collections.emptyMap();
         
+        lazyImports = false;
+        lazyAutoImportsSet = true;
+        
         initAutoImportsMap();
         initAutoIncludesList();
     }
@@ -1612,6 +1637,81 @@ public class Configurable {
     }
     
     /**
+     * The getter pair of {@link #setLazyImports(boolean)}.
+     * 
+     * @since 2.3.25
+     */
+    public boolean getLazyImports() {
+        return lazyImports != null ? lazyImports.booleanValue() : parent.getLazyImports();
+    }
+    
+    /**
+     * Specifies if {@code <#import ...>} (and {@link Environment#importLib(String, String)}) should delay the loading
+     * and processing of the imported templates until the content of the imported namespace is actually accessed. This
+     * makes the overhead of <em>unused</em> imports negligible. A drawback is that importing a missing or otherwise
+     * broken template will be successful, and the problem will remain hidden until (and if) the namespace content is
+     * actually used. Also, you lose the strict control over when the namespace initializing code in the imported
+     * template will be executed, though it shouldn't mater for well written imported templates anyway. Note that the
+     * namespace initializing code will run with the same {@linkplain Configurable#getLocale() locale} as it was at the
+     * point of the {@code <#import ...>} call (other settings won't be handled specially like that).
+     * 
+     * <p>
+     * The default is {@code false} (and thus imports are eager) for backward compatibility, which can cause
+     * perceivable overhead if you have many imports and only a few of them is used.
+     * 
+     * <p>
+     * This setting also affects {@linkplain #setAutoImports(Map) auto-imports}, unless you have set a non-{@code null}
+     * value with {@link #setLazyAutoImports(Boolean)}.
+     * 
+     * @see #setLazyAutoImports(Boolean)
+     * 
+     * @since 2.3.25
+     */
+    public void setLazyImports(boolean lazyImports) {
+        this.lazyImports = Boolean.valueOf(lazyImports);
+    }
+
+    /**
+     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
+     *  
+     * @since 2.3.25
+     */
+    public boolean isLazyImportsSet() {
+        return lazyImports != null;
+    }
+    
+    /**
+     * The getter pair of {@link #setLazyAutoImports(Boolean)}.
+     * 
+     * @since 2.3.25
+     */
+    public Boolean getLazyAutoImports() {
+        return lazyAutoImportsSet ? lazyAutoImports : parent.getLazyAutoImports();
+    }
+
+    /**
+     * Specifies if {@linkplain #setAutoImports(Map) auto-imports} will be
+     * {@link #setLazyImports(boolean) lazy imports}. This is useful to make the overhead of <em>unused</em>
+     * auto-imports negligible. If this is set to {@code null}, {@link #getLazyImports()} specifies the behavior of
+     * auto-imports too. The default value is {@code null}.
+     * 
+     * @since 2.3.25
+     */
+    public void setLazyAutoImports(Boolean lazyAutoImports) {
+        this.lazyAutoImports = lazyAutoImports;
+        lazyAutoImportsSet = true;
+    }
+    
+    /**
+     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
+     *  
+     * @since 2.3.25
+     */
+    public boolean isLazyAutoImportsSet() {
+        return lazyAutoImportsSet;
+    }
+    
+    /**
      * Adds an invisible <code>#import <i>templateName</i> as <i>namespaceVarName</i></code> at the beginning of the
      * main template (that's the top-level template that wasn't included/imported from another template). While it only
      * affects the main template directly, as the imports will create a global variable there, the imports will be
@@ -1981,6 +2081,26 @@ public class Configurable {
      *       Since 2.3.17.
      *       <br>String value: {@code "true"}, {@code "false"}, {@code "y"},  etc.
      *       
+     *   <li><p>{@code "auto_import"}:
+     *       See {@link Configuration#setAutoImports(Map)}
+     *       <br>String value is something like:
+     *       <br>{@code /lib/form.ftl as f, /lib/widget as w, "/lib/odd name.ftl" as odd}
+     *       
+     *   <li><p>{@code "auto_include"}: Sets the list of auto-includes.
+     *       See {@link Configuration#setAutoIncludes(List)}
+     *       <br>String value is something like:
+     *       <br>{@code /include/common.ftl, "/include/evil name.ftl"}
+     *       
+     *   <li><p>{@code "lazy_auto_imports"}:
+     *       See {@link Configuration#setLazyAutoImports(Boolean)}.
+     *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
+     *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive. Also can be {@code "null"}.
+
+     *   <li><p>{@code "lazy_imports"}:
+     *       See {@link Configuration#setLazyImports(boolean)}.
+     *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
+     *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive.
+     *       
      *   <li><p>{@code "new_builtin_class_resolver"}:
      *       See {@link #setNewBuiltinClassResolver(TemplateClassResolver)}.
      *       Since 2.3.17.
@@ -2058,26 +2178,6 @@ public class Configurable {
      *       {@link Configuration#ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY}
      *       {@code "disable"} for {@link Configuration#DISABLE_AUTO_ESCAPING_POLICY}.
      *       
-     *   <li><p>{@code "auto_import"}:
-     *       See {@link Configuration#setAutoImports(Map)}
-     *       <br>String value is something like:
-     *       <br>{@code /lib/form.ftl as f, /lib/widget as w, "/lib/odd name.ftl" as odd}
-     *       
-     *   <li><p>{@code "auto_include"}: Sets the list of auto-includes.
-     *       See {@link Configuration#setAutoIncludes(List)}
-     *       <br>String value is something like:
-     *       <br>{@code /include/common.ftl, "/include/evil name.ftl"}
-     *       
-     *   <li><p>{@code "lazy_auto_imports"}:
-     *       See {@link Configuration#setLazyAutoImports(Boolean)}.
-     *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
-     *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive. Also can be {@code "null"}.
-
-     *   <li><p>{@code "lazy_imports"}:
-     *       See {@link Configuration#setLazyImports(boolean)}.
-     *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
-     *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive.
-     *       
      *   <li><p>{@code "default_encoding"}:
      *       See {@link Configuration#setDefaultEncoding(String)}.
      *       <br>As the default value is the system default, which can change
@@ -2441,6 +2541,10 @@ public class Configurable {
             } else if (LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE.equals(name)
                     || LOG_TEMPLATE_EXCEPTIONS_KEY_CAMEL_CASE.equals(name)) {
                 setLogTemplateExceptions(StringUtil.getYesNo(value));
+            } else if (LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
+                setLazyAutoImports(value.equals(NULL) ? null : Boolean.valueOf(StringUtil.getYesNo(value)));
+            } else if (LAZY_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
+                setLazyImports(StringUtil.getYesNo(value));
             } else if (AUTO_INCLUDE_KEY_SNAKE_CASE.equals(name)
                     || AUTO_INCLUDE_KEY_CAMEL_CASE.equals(name)) {
                 setAutoIncludes(parseAsList(value));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 8d03ae5..517aba6 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -2525,7 +2525,7 @@ public final class Environment extends Configurable {
      * more intelligent error handling.
      * 
      * <p>
-     * If it will be a lazy or an eager import is decided by the value of {@link Configuration#getLazyImports()}. You
+     * If it will be a lazy or an eager import is decided by the value of {@link #getLazyImports()}. You
      * can also directly control that aspect by using {@link #importLib(String, String, boolean)} instead.
      *
      * @return Not {@code null}. This is possibly a lazily self-initializing namespace, which means that it will only
@@ -2537,7 +2537,7 @@ public final class Environment extends Configurable {
      */
     public Namespace importLib(String templateName, String targetNsVarName)
             throws IOException, TemplateException {
-        return importLib(templateName, targetNsVarName, configuration.getLazyImports());
+        return importLib(templateName, targetNsVarName, getLazyImports());
     }
 
     /**
@@ -2559,7 +2559,7 @@ public final class Environment extends Configurable {
 
     /**
      * Like {@link #importLib(String, String)}, but you can specify if you want a
-     * {@linkplain Configuration#setLazyImports(boolean) lazy import} or not.
+     * {@linkplain #setLazyImports(boolean) lazy import} or not.
      * 
      * @return Not {@code null}. This is possibly a lazily self-initializing namespace, which mean that it will only try
      *         to get and process the imported template when you access its content.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/main/java/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateConfiguration.java b/src/main/java/freemarker/core/TemplateConfiguration.java
index 06f5d7b..fe1062a 100644
--- a/src/main/java/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/freemarker/core/TemplateConfiguration.java
@@ -244,6 +244,12 @@ public final class TemplateConfiguration extends Configurable implements ParserC
         if (tc.isTabSizeSet()) {
             setTabSize(tc.getTabSize());
         }
+        if (tc.isLazyImportsSet()) {
+            setLazyImports(tc.getLazyImports());
+        }
+        if (tc.isLazyAutoImportsSet()) {
+            setLazyAutoImports(tc.getLazyAutoImports());
+        }
         if (tc.isAutoImportsSet()) {
             setAutoImports(mergeMaps(getAutoImports(), tc.getAutoImports(), true));
         }
@@ -348,6 +354,12 @@ public final class TemplateConfiguration extends Configurable implements ParserC
         if (isURLEscapingCharsetSet() && !template.isURLEscapingCharsetSet()) {
             template.setURLEscapingCharset(getURLEscapingCharset());
         }
+        if (isLazyImportsSet() && !template.isLazyImportsSet()) {
+            template.setLazyImports(getLazyImports());
+        }
+        if (isLazyAutoImportsSet() && !template.isLazyAutoImportsSet()) {
+            template.setLazyAutoImports(getLazyAutoImports());
+        }
         if (isAutoImportsSet()) {
             // Regarding the order of the maps in the merge:
             // - Existing template-level imports have precedence over those coming from the TC (just as with the others
@@ -608,6 +620,8 @@ public final class TemplateConfiguration extends Configurable implements ParserC
                 || isCustomNumberFormatsSet()
                 || isDateFormatSet()
                 || isDateTimeFormatSet()
+                || isLazyImportsSet()
+                || isLazyAutoImportsSet()
                 || isLocaleSet()
                 || isLogTemplateExceptionsSet()
                 || isNewBuiltinClassResolverSet()

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 9565258..a888a60 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -245,20 +245,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
     public static final String AUTO_INCLUDE_KEY = AUTO_INCLUDE_KEY_SNAKE_CASE;
 
-    /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
-    public static final String LAZY_IMPORTS_KEY_SNAKE_CASE = "lazy_imports";
-    /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
-    public static final String LAZY_IMPORTS_KEY_CAMEL_CASE = "lazyImports";
-    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-    public static final String LAZY_IMPORTS_KEY = LAZY_IMPORTS_KEY_SNAKE_CASE;
-
-    /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
-    public static final String LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE = "lazy_auto_imports";
-    /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
-    public static final String LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE = "lazyAutoImports";
-    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
-    public static final String LAZY_AUTO_IMPORTS_KEY = LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE;
-    
     /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.23 */
     public static final String TAG_SYNTAX_KEY_SNAKE_CASE = "tag_syntax";
     /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.23 */
@@ -328,8 +314,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         CACHE_STORAGE_KEY_SNAKE_CASE,
         DEFAULT_ENCODING_KEY_SNAKE_CASE,
         INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE,
-        LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE,
-        LAZY_IMPORTS_KEY_SNAKE_CASE,
         LOCALIZED_LOOKUP_KEY_SNAKE_CASE,
         NAMING_CONVENTION_KEY_SNAKE_CASE,
         OUTPUT_FORMAT_KEY_SNAKE_CASE,
@@ -352,8 +336,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         CACHE_STORAGE_KEY_CAMEL_CASE,
         DEFAULT_ENCODING_KEY_CAMEL_CASE,
         INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE,
-        LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE,
-        LAZY_IMPORTS_KEY_CAMEL_CASE,
         LOCALIZED_LOOKUP_KEY_CAMEL_CASE,
         NAMING_CONVENTION_KEY_CAMEL_CASE,
         OUTPUT_FORMAT_KEY_CAMEL_CASE,
@@ -538,9 +520,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     private String defaultEncoding = SecurityUtilities.getSystemProperty("file.encoding", "utf-8");
     private ConcurrentMap localeToCharsetMap = new ConcurrentHashMap();
     
-    private boolean lazyImpots;
-    private Boolean lazyAutoImports;
-
     /**
      * @deprecated Use {@link #Configuration(Version)} instead. Note that the version can be still modified later with
      *     {@link Configuration#setIncompatibleImprovements(Version)} (or
@@ -2955,10 +2934,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
                     valueWithoutUnit = value;
                 }
                 setTemplateUpdateDelayMilliseconds(Integer.parseInt(valueWithoutUnit) * multipier);
-            } else if (LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
-                setLazyAutoImports(value.equals(NULL) ? null : Boolean.valueOf(StringUtil.getYesNo(value)));
-            } else if (LAZY_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
-                setLazyImports(StringUtil.getYesNo(value));
             } else if (TAG_SYNTAX_KEY_SNAKE_CASE.equals(name) || TAG_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
                 if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
                     setTagSyntax(AUTO_DETECT_TAG_SYNTAX);
@@ -3081,7 +3056,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         Map<String, String> envAutoImports = env.getAutoImportsWithoutFallback();
         Map<String, String> tAutoImports = t.getAutoImportsWithoutFallback();
         
-        boolean lazyAutoImports = getLazyAutoImports() != null ? getLazyAutoImports().booleanValue() : getLazyImports();
+        boolean lazyAutoImports = env.getLazyAutoImports() != null ? env.getLazyAutoImports().booleanValue()
+                : env.getLazyImports();
         
         for (Map.Entry<String, String> autoImport : getAutoImportsWithoutFallback().entrySet()) {
             String nsVarName = autoImport.getKey();
@@ -3138,62 +3114,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     /**
-     * The getter pair of {@link #setLazyImports(boolean)}.
-     * 
-     * @since 2.3.25
-     */
-    public boolean getLazyImports() {
-        return lazyImpots;
-    }
-
-    /**
-     * Specifies if {@code <#import ...>} (and {@link Environment#importLib(String, String)}) should delay the loading
-     * and processing of the imported templates until the content of the imported namespace is actually accessed. This
-     * makes the overhead of <em>unused</em> imports negligible. A drawback is that importing a missing or otherwise
-     * broken template will be successful, and the problem will remain hidden until (and if) the namespace content is
-     * actually used. Also, you lose the strict control over when the namespace initializing code in the imported
-     * template will be executed, though it shouldn't mater for well written imported templates anyway. Note that the
-     * namespace initializing code will run with the same {@linkplain Configurable#getLocale() locale} as it was at the
-     * point of the {@code <#import ...>} call (other settings won't be handled specially like that).
-     * 
-     * <p>
-     * The default is {@code false} (and thus imports are eager) for backward compatibility, which can cause
-     * perceivable overhead if you have many imports and only a few of them is used.
-     * 
-     * <p>
-     * This setting also affects {@linkplain #setAutoImports(Map) auto-imports}, unless you have set a non-{@code null}
-     * value just for that via {@link #setLazyAutoImports(Boolean)}.
-     * 
-     * @see #setLazyAutoImports(Boolean)
-     * 
-     * @since 2.3.25
-     */
-    public void setLazyImports(boolean lazyImports) {
-        this.lazyImpots = lazyImports;
-    }
-
-    /**
-     * The getter pair of {@link #setLazyAutoImports(Boolean)}.
-     * 
-     * @since 2.3.25
-     */
-    public Boolean getLazyAutoImports() {
-        return lazyAutoImports;
-    }
-
-    /**
-     * Specifies if {@linkplain #setAutoImports(Map) auto-imports} will be
-     * {@link #setLazyImports(boolean) lazy imports}. This is useful to make the overhead of <em>unused</em>
-     * auto-imports negligible. If this is set to {@code null}, {@link #getLazyImports()} specifies the behavior of
-     * auto-imports too. The default value is {@code null}.
-     * 
-     * @since 2.3.25
-     */
-    public void setLazyAutoImports(Boolean autoImportsLazy) {
-        this.lazyAutoImports = autoImportsLazy;
-    }
-
-    /**
      * Returns FreeMarker version number string. 
      * 
      * @deprecated Use {@link #getVersion()} instead.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index cdf939d..8e1e874 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26593,21 +26593,24 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
-              <para>Lazy imports: With the new boolean
-              <literal>Configuration</literal>-level settings,
+              <para>Lazy imports: With the new boolean settings,
               <literal>lazy_imports</literal> and
-              <literal>lazy_auto_imports</literal>, you can request imports
-              (as in <literal>&lt;#import "lib/utils.ftl" as u&gt;</literal>)
+              <literal>lazy_auto_imports</literal>, you can make imports (as
+              in <literal>&lt;#import "lib/utils.ftl" as u&gt;</literal>)
               and/or auto-imports to be lazy. When the import is lazy, the
               namespace variable (<literal>u</literal> in this example) will
-              be created immediately, just like before, but the template will
-              be imported and processed only when (and if ever) the content of
-              the imported namespace is accessed. The main application of this
-              is with auto-imports, where you don't want the overhead of
-              importing templates that aren't actually used in a template.
-              (Also, a new <literal>Environment.importLib</literal> method
-              overload was added, where you can specify if you want a lazy or
-              an eager import.)</para>
+              be created immediately, just like before, but the imported
+              template will be loaded and processed only when (and if ever)
+              the content of the imported namespace is accessed. The main
+              application of this is with auto-imports, where you don't want
+              the overhead of importing templates that aren't actually used in
+              a template. (Also, a new
+              <literal>Environment.importLib</literal> method overload was
+              added, where you can specify if you want a lazy or an eager
+              import.) These new settings can be set on
+              <literal>Configuration</literal>, <literal>Template</literal>
+              (<literal>TemplateConfiguration</literal>) and
+              <literal>Environment</literal> level.</para>
             </listitem>
 
             <listitem>
@@ -26618,7 +26621,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               auto-imports). This is now possible as these settings were moved
               from the <literal>Configuration</literal> level down to the more
               generic <literal>Configurable</literal> level, and so are
-              inherited by <literal>TemplateConfigurer</literal> and
+              inherited by <literal>TemplateConfiguration</literal> and
               <literal>Environment</literal> too.</para>
             </listitem>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/test/java/freemarker/core/AutoImportAndIncludeTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/AutoImportAndIncludeTest.java b/src/test/java/freemarker/core/AutoImportAndIncludeTest.java
deleted file mode 100644
index c813e69..0000000
--- a/src/test/java/freemarker/core/AutoImportAndIncludeTest.java
+++ /dev/null
@@ -1,261 +0,0 @@
-package freemarker.core;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.StringWriter;
-
-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;
-
-public class AutoImportAndIncludeTest extends TemplateTest {
-
-    @Test
-    public void test3LayerImportNoClashes() throws Exception {
-        Configuration cfg = getConfiguration();
-        cfg.addAutoImport("t1", "t1.ftl");
-
-        TemplateConfiguration tc = new TemplateConfiguration();
-        tc.addAutoImport("t2", "t2.ftl");
-        cfg.setTemplateConfigurations(
-                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoImport("t3", "t3.ftl");
-    
-            env.process();
-            assertEquals("In main: t1;t2;t3;", sw.toString());
-        }
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-    
-            env.process();
-            assertEquals("In main: t1;t2;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main2.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoImport("t3", "t3.ftl");
-    
-            env.process();
-            assertEquals("In main2: t1;t3;", sw.toString());
-        }
-        
-        cfg.removeAutoImport("t1");
-        
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoImport("t3", "t3.ftl");
-    
-            env.process();
-            assertEquals("In main: t2;t3;", sw.toString());
-        }
-    }
-    
-    @Test
-    public void test3LayerImportClashes() throws Exception {
-        Configuration cfg = getConfiguration();
-        cfg.addAutoImport("t1", "t1.ftl");
-        cfg.addAutoImport("t2", "t2.ftl");
-        cfg.addAutoImport("t3", "t3.ftl");
-
-        TemplateConfiguration tc = new TemplateConfiguration();
-        tc.addAutoImport("t2", "t2b.ftl");
-        cfg.setTemplateConfigurations(
-                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoImport("t3", "t3b.ftl");
-    
-            env.process();
-            assertEquals("In main: t1;t2b;t3b;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main2.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoImport("t3", "t3b.ftl");
-    
-            env.process();
-            assertEquals("In main2: t1;t2;t3b;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-    
-            env.process();
-            assertEquals("In main: t1;t3;t2b;", sw.toString());
-        }
-    }
-
-    @Test
-    public void test3LayerIncludesNoClashes() throws Exception {
-        Configuration cfg = getConfiguration();
-        cfg.addAutoInclude("t1.ftl");
-
-        TemplateConfiguration tc = new TemplateConfiguration();
-        tc.addAutoInclude("t2.ftl");
-        cfg.setTemplateConfigurations(
-                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t3.ftl");
-    
-            env.process();
-            assertEquals("T1;T2;T3;In main: t1;t2;t3;", sw.toString());
-        }
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-    
-            env.process();
-            assertEquals("T1;T2;In main: t1;t2;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main2.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t3.ftl");
-    
-            env.process();
-            assertEquals("T1;T3;In main2: t1;t3;", sw.toString());
-        }
-        
-        cfg.removeAutoInclude("t1.ftl");
-        
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t3.ftl");
-    
-            env.process();
-            assertEquals("T2;T3;In main: t2;t3;", sw.toString());
-        }
-    }
-
-    @Test
-    public void test3LayerIncludeClashes() throws Exception {
-        Configuration cfg = getConfiguration();
-        cfg.addAutoInclude("t1.ftl");
-        cfg.addAutoInclude("t2.ftl");
-        cfg.addAutoInclude("t3.ftl");
-
-        TemplateConfiguration tc = new TemplateConfiguration();
-        tc.addAutoInclude("t2.ftl");
-        cfg.setTemplateConfigurations(
-                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t3.ftl");
-    
-            env.process();
-            assertEquals("T1;T2;T3;In main: t1;t2;t3;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main2.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t3.ftl");
-    
-            env.process();
-            assertEquals("T1;T2;T3;In main2: t1;t2;t3;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-    
-            env.process();
-            assertEquals("T1;T3;T2;In main: t1;t3;t2;", sw.toString());
-        }
-        
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t1.ftl");
-    
-            env.process();
-            assertEquals("T3;T2;T1;In main: t3;t2;t1;", sw.toString());
-        }
-    }
-    
-    @Test
-    public void test3LayerIncludesClashes2() throws Exception {
-        Configuration cfg = getConfiguration();
-        cfg.addAutoInclude("t1.ftl");
-        cfg.addAutoInclude("t1.ftl");
-
-        TemplateConfiguration tc = new TemplateConfiguration();
-        tc.addAutoInclude("t2.ftl");
-        tc.addAutoInclude("t2.ftl");
-        cfg.setTemplateConfigurations(
-                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
-
-        {
-            Template t = cfg.getTemplate("main.ftl");
-            StringWriter sw = new StringWriter();
-            Environment env = t.createProcessingEnvironment(null, sw);
-            env.addAutoInclude("t3.ftl");
-            env.addAutoInclude("t3.ftl");
-            env.addAutoInclude("t1.ftl");
-            env.addAutoInclude("t1.ftl");
-    
-            env.process();
-            assertEquals("T2;T3;T1;In main: t2;t3;t1;", sw.toString());
-        }
-    }
-    
-    @Override
-    protected Configuration createConfiguration() throws Exception {
-        Configuration cfg = new Configuration(Configuration.VERSION_2_3_24);
-        cfg.setTemplateLoader(new StringTemplateLoader());
-        return cfg;
-    }
-
-    @Override
-    protected void addCommonTemplates() {
-        addTemplate("main.ftl", "In main: ${loaded}");
-        addTemplate("main2.ftl", "In main2: ${loaded}");
-        addTemplate("t1.ftl", "<#global loaded = (loaded!) + 't1;'>T1;");
-        addTemplate("t2.ftl", "<#global loaded = (loaded!) + 't2;'>T2;");
-        addTemplate("t3.ftl", "<#global loaded = (loaded!) + 't3;'>T3;");
-        addTemplate("t1b.ftl", "<#global loaded = (loaded!) + 't1b;'>T1b;");
-        addTemplate("t2b.ftl", "<#global loaded = (loaded!) + 't2b;'>T2b;");
-        addTemplate("t3b.ftl", "<#global loaded = (loaded!) + 't3b;'>T3b;");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/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
new file mode 100644
index 0000000..e97f8b5
--- /dev/null
+++ b/src/test/java/freemarker/core/IncludeAndImportConfigurableLayersTest.java
@@ -0,0 +1,319 @@
+package freemarker.core;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.StringWriter;
+
+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;
+
+public class IncludeAndImportConfigurableLayersTest extends TemplateTest {
+
+    @Test
+    public void test3LayerImportNoClashes() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoImport("t1", "t1.ftl");
+
+        TemplateConfiguration tc = new TemplateConfiguration();
+        tc.addAutoImport("t2", "t2.ftl");
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoImport("t3", "t3.ftl");
+    
+            env.process();
+            assertEquals("In main: t1;t2;t3;", sw.toString());
+        }
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+    
+            env.process();
+            assertEquals("In main: t1;t2;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main2.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoImport("t3", "t3.ftl");
+    
+            env.process();
+            assertEquals("In main2: t1;t3;", sw.toString());
+        }
+        
+        cfg.removeAutoImport("t1");
+        
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoImport("t3", "t3.ftl");
+    
+            env.process();
+            assertEquals("In main: t2;t3;", sw.toString());
+        }
+    }
+    
+    @Test
+    public void test3LayerImportClashes() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoImport("t1", "t1.ftl");
+        cfg.addAutoImport("t2", "t2.ftl");
+        cfg.addAutoImport("t3", "t3.ftl");
+
+        TemplateConfiguration tc = new TemplateConfiguration();
+        tc.addAutoImport("t2", "t2b.ftl");
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoImport("t3", "t3b.ftl");
+    
+            env.process();
+            assertEquals("In main: t1;t2b;t3b;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main2.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoImport("t3", "t3b.ftl");
+    
+            env.process();
+            assertEquals("In main2: t1;t2;t3b;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+    
+            env.process();
+            assertEquals("In main: t1;t3;t2b;", sw.toString());
+        }
+    }
+
+    @Test
+    public void test3LayerIncludesNoClashes() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoInclude("t1.ftl");
+
+        TemplateConfiguration tc = new TemplateConfiguration();
+        tc.addAutoInclude("t2.ftl");
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t3.ftl");
+    
+            env.process();
+            assertEquals("T1;T2;T3;In main: t1;t2;t3;", sw.toString());
+        }
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+    
+            env.process();
+            assertEquals("T1;T2;In main: t1;t2;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main2.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t3.ftl");
+    
+            env.process();
+            assertEquals("T1;T3;In main2: t1;t3;", sw.toString());
+        }
+        
+        cfg.removeAutoInclude("t1.ftl");
+        
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t3.ftl");
+    
+            env.process();
+            assertEquals("T2;T3;In main: t2;t3;", sw.toString());
+        }
+    }
+
+    @Test
+    public void test3LayerIncludeClashes() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoInclude("t1.ftl");
+        cfg.addAutoInclude("t2.ftl");
+        cfg.addAutoInclude("t3.ftl");
+
+        TemplateConfiguration tc = new TemplateConfiguration();
+        tc.addAutoInclude("t2.ftl");
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t3.ftl");
+    
+            env.process();
+            assertEquals("T1;T2;T3;In main: t1;t2;t3;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main2.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t3.ftl");
+    
+            env.process();
+            assertEquals("T1;T2;T3;In main2: t1;t2;t3;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+    
+            env.process();
+            assertEquals("T1;T3;T2;In main: t1;t3;t2;", sw.toString());
+        }
+        
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t1.ftl");
+    
+            env.process();
+            assertEquals("T3;T2;T1;In main: t3;t2;t1;", sw.toString());
+        }
+    }
+    
+    @Test
+    public void test3LayerIncludesClashes2() throws Exception {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoInclude("t1.ftl");
+        cfg.addAutoInclude("t1.ftl");
+
+        TemplateConfiguration tc = new TemplateConfiguration();
+        tc.addAutoInclude("t2.ftl");
+        tc.addAutoInclude("t2.ftl");
+        cfg.setTemplateConfigurations(
+                new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("main.ftl"), tc));
+
+        {
+            Template t = cfg.getTemplate("main.ftl");
+            StringWriter sw = new StringWriter();
+            Environment env = t.createProcessingEnvironment(null, sw);
+            env.addAutoInclude("t3.ftl");
+            env.addAutoInclude("t3.ftl");
+            env.addAutoInclude("t1.ftl");
+            env.addAutoInclude("t1.ftl");
+    
+            env.process();
+            assertEquals("T2;T3;T1;In main: t2;t3;t1;", sw.toString());
+        }
+    }
+    
+    @Test
+    public void test3LayerLazyness() throws Exception {
+        for (Class<?> layer : new Class<?>[] { Configuration.class, Template.class, Environment.class }) {
+            test3LayerLazyness(layer, null, null, false, "t1;t2;");
+            test3LayerLazyness(layer, null, null, true, "t1;t2;");
+            test3LayerLazyness(layer, null, false, true, "t1;t2;");
+            test3LayerLazyness(layer, null, true, true, "t2;");
+            
+            test3LayerLazyness(layer, false, null, false, "t1;t2;");
+            test3LayerLazyness(layer, false, null, true, "t1;t2;");
+            test3LayerLazyness(layer, false, false, true, "t1;t2;");
+            test3LayerLazyness(layer, false, true, true, "t2;");
+
+            test3LayerLazyness(layer, true, null, false, "");
+            test3LayerLazyness(layer, true, null, true, "");
+            test3LayerLazyness(layer, true, false, true, "t1;");
+            test3LayerLazyness(layer, true, true, true, "");
+        }
+    }
+    
+    private void test3LayerLazyness(
+            Class<?> layer,
+            Boolean lazyImports,
+            Boolean lazyAutoImports, boolean setLazyAutoImports,
+            String expectedOutput)
+            throws Exception {
+        dropConfiguration();
+        Configuration cfg = getConfiguration();
+        cfg.addAutoImport("t1", "t1.ftl");
+        Template t = new Template(null, "<#import 't2.ftl' as t2>${loaded!}", cfg);
+
+        StringWriter sw = new StringWriter();
+        Environment env = t.createProcessingEnvironment(null, sw);
+        
+        if (layer == Configuration.class) {
+            setLazynessOfConfigurable(cfg, lazyImports, lazyAutoImports, setLazyAutoImports);
+        } else if (layer == Template.class) {
+            setLazynessOfConfigurable(t, lazyImports, lazyAutoImports, setLazyAutoImports);
+        } else if (layer == Environment.class) {
+            setLazynessOfConfigurable(env, lazyImports, lazyAutoImports, setLazyAutoImports);
+        } else {
+            throw new IllegalArgumentException();
+        }
+        
+        env.process();
+        assertEquals(expectedOutput, sw.toString());
+    }
+
+    private void setLazynessOfConfigurable(Configurable cfg, Boolean lazyImports, Boolean lazyAutoImports,
+            boolean setLazyAutoImports) {
+        if (lazyImports != null) {
+            cfg.setLazyImports(lazyImports);
+        }
+        if (setLazyAutoImports) {
+            cfg.setLazyAutoImports(lazyAutoImports);
+        }
+    }
+    
+    @Override
+    protected Configuration createConfiguration() throws Exception {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_24);
+        cfg.setTemplateLoader(new StringTemplateLoader());
+        return cfg;
+    }
+
+    @Override
+    protected void addCommonTemplates() {
+        addTemplate("main.ftl", "In main: ${loaded}");
+        addTemplate("main2.ftl", "In main2: ${loaded}");
+        addTemplate("t1.ftl", "<#global loaded = (loaded!) + 't1;'>T1;");
+        addTemplate("t2.ftl", "<#global loaded = (loaded!) + 't2;'>T2;");
+        addTemplate("t3.ftl", "<#global loaded = (loaded!) + 't3;'>T3;");
+        addTemplate("t1b.ftl", "<#global loaded = (loaded!) + 't1b;'>T1b;");
+        addTemplate("t2b.ftl", "<#global loaded = (loaded!) + 't2b;'>T2b;");
+        addTemplate("t3b.ftl", "<#global loaded = (loaded!) + 't3b;'>T3b;");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/src/test/java/freemarker/core/TemplateConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/TemplateConfigurationTest.java b/src/test/java/freemarker/core/TemplateConfigurationTest.java
index ee92492..13a6405 100644
--- a/src/test/java/freemarker/core/TemplateConfigurationTest.java
+++ b/src/test/java/freemarker/core/TemplateConfigurationTest.java
@@ -188,11 +188,13 @@ public class TemplateConfigurationTest {
         SETTING_ASSIGNMENTS.put("outputFormat", HTMLOutputFormat.INSTANCE);
         SETTING_ASSIGNMENTS.put("recognizeStandardFileExtensions", true);
         SETTING_ASSIGNMENTS.put("tabSize", 1);
+        SETTING_ASSIGNMENTS.put("lazyImports", Boolean.TRUE);
+        SETTING_ASSIGNMENTS.put("lazyAutoImports", Boolean.FALSE);
+        SETTING_ASSIGNMENTS.put("autoImports", ImmutableMap.of("a", "/lib/a.ftl"));
+        SETTING_ASSIGNMENTS.put("autoIncludes", ImmutableList.of("/lib/b.ftl"));
         
         // Special settings:
         SETTING_ASSIGNMENTS.put("encoding", NON_DEFAULT_ENCODING);
-        SETTING_ASSIGNMENTS.put("autoImports", ImmutableMap.of("a", "/lib/a.ftl"));
-        SETTING_ASSIGNMENTS.put("autoIncludes", ImmutableList.of("/lib/b.ftl"));
     }
     
     public static String getIsSetMethodName(String readMethodName) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/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 523b072..9f59d80 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -1588,6 +1588,7 @@ public class ConfigurationTest extends TestCase {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
 
         assertFalse(cfg.getLazyImports());
+        assertTrue(cfg.isLazyImportsSet());
         cfg.setSetting("lazy_imports", "true");
         assertTrue(cfg.getLazyImports());
         cfg.setSetting("lazyImports", "false");
@@ -1598,12 +1599,15 @@ public class ConfigurationTest extends TestCase {
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
 
         assertNull(cfg.getLazyAutoImports());
+        assertTrue(cfg.isLazyAutoImportsSet());
         cfg.setSetting("lazy_auto_imports", "true");
         assertEquals(Boolean.TRUE, cfg.getLazyAutoImports());
+        assertTrue(cfg.isLazyAutoImportsSet());
         cfg.setSetting("lazyAutoImports", "false");
         assertEquals(Boolean.FALSE, cfg.getLazyAutoImports());
         cfg.setSetting("lazyAutoImports", "null");
         assertNull(cfg.getLazyAutoImports());
+        assertTrue(cfg.isLazyAutoImportsSet());
     }
     
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa855c73/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 6904b80..c4d4e59 100644
--- a/src/test/java/freemarker/test/TemplateTest.java
+++ b/src/test/java/freemarker/test/TemplateTest.java
@@ -69,6 +69,10 @@ public abstract class TemplateTest {
         this.configuration = configuration;
     }
 
+    protected final void dropConfiguration() {
+        configuration = null;
+    }
+    
     protected void assertOutput(String ftl, String expectedOut) throws IOException, TemplateException {
         assertOutput(createTemplate(ftl), expectedOut, false);
     }