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><#import "lib/utils.ftl" as u></literal>)
+ <literal>lazy_auto_imports</literal>, you can make imports (as
+ in <literal><#import "lib/utils.ftl" as u></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);
}