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 2017/04/05 19:55:50 UTC
[4/4] incubator-freemarker git commit: Made TemplateConfiguration
immutable, added a TemplateConfiguration.Builder. (This is not the final
version of TemplateConfiguration;
it will be become cleaner as Template also becomes immutable.)
Made TemplateConfiguration immutable, added a TemplateConfiguration.Builder. (This is not the final version of TemplateConfiguration; it will be become cleaner as Template also becomes immutable.)
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/88baea20
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/88baea20
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/88baea20
Branch: refs/heads/3
Commit: 88baea20cade54dad8a932124d5ecc691ea088d9
Parents: 23f66eb
Author: ddekany <dd...@apache.org>
Authored: Wed Apr 5 21:55:34 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Apr 5 21:55:34 2017 +0200
----------------------------------------------------------------------
.../core/BuiltInsForMultipleTypes.java | 4 +-
.../freemarker/core/BuiltInsForStringsMisc.java | 8 +-
.../apache/freemarker/core/Configuration.java | 243 ++--
.../org/apache/freemarker/core/Environment.java | 274 +++++
.../MutableProcessingAndParseConfiguration.java | 48 +-
.../core/MutableProcessingConfiguration.java | 346 +++---
.../core/ParserAndProcessingConfiguration.java | 29 +
.../freemarker/core/ParserConfiguration.java | 5 +-
.../core/ProcessingConfiguration.java | 14 +-
.../org/apache/freemarker/core/Template.java | 148 +++
.../freemarker/core/TemplateBooleanFormat.java | 91 ++
.../freemarker/core/TemplateConfiguration.java | 1163 ++++++++++--------
..._ParserConfigurationWithInheritedFormat.java | 13 +-
.../core/model/impl/ClassIntrospector.java | 4 +-
.../core/model/impl/DefaultObjectWrapper.java | 4 +-
.../DefaultObjectWrapperTCCLSingletonUtil.java | 4 +-
.../MergingTemplateConfigurationFactory.java | 40 +-
.../templateresolver/TemplateLoadingResult.java | 5 +-
.../impl/DefaultTemplateResolver.java | 14 +-
.../freemarker/core/util/BuilderBase.java | 34 -
.../freemarker/core/util/CommonBuilder.java | 29 +
.../freemarker/core/util/FluentBuilder.java | 36 +
.../core/util/ProductWrappingBuilder.java | 2 +-
src/manual/en_US/FM3-CHANGE-LOG.txt | 1 +
.../freemarker/core/ConfigurationTest.java | 6 +-
.../apache/freemarker/core/DateFormatTest.java | 7 +-
.../IncludeAndImportConfigurableLayersTest.java | 37 +-
.../freemarker/core/OutputFormatTest.java | 24 +-
.../core/TemplateConfigurationTest.java | 330 ++---
...igurationWithDefaltTemplateResolverTest.java | 264 ----
...gurationWithDefaultTemplateResolverTest.java | 264 ++++
.../core/TemplateGetEncodingTest.java | 7 +-
.../TemplateConfigurationFactoryTest.java | 27 +-
.../core/valueformat/NumberFormatTest.java | 7 +-
.../ConfigureOutputFormatExamples.java | 16 +-
.../TemplateConfigurationExamples.java | 50 +-
.../servlet/FreemarkerServletTest.java | 12 +-
37 files changed, 2217 insertions(+), 1393 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
index e75ea9e..ab3df64 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForMultipleTypes.java
@@ -229,11 +229,11 @@ class BuiltInsForMultipleTypes {
static class apiBI extends ASTExpBuiltIn {
@Override
TemplateModel _eval(Environment env) throws TemplateException {
- if (!env.isAPIBuiltinEnabled()) {
+ if (!env.getAPIBuiltinEnabled()) {
throw new _MiscTemplateException(this,
"Can't use ?api, because the \"", MutableProcessingConfiguration.API_BUILTIN_ENABLED_KEY,
"\" configuration setting is false. Think twice before you set it to true though. Especially, "
- + "it shouldn't abussed for modifying Map-s and Collection-s.");
+ + "it shouldn't abused for modifying Map-s and Collection-s.");
}
final TemplateModel tm = target.eval(env);
if (!(tm instanceof TemplateModelWithAPISupport)) {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
index d0deade..f83cbbb 100644
--- a/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
+++ b/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
@@ -46,13 +46,13 @@ class BuiltInsForStringsMisc {
@Override
TemplateModel calculateResult(String s, Environment env) throws TemplateException {
final boolean b;
- if (s.equals("true")) {
+ if (s.equals(MiscUtil.C_TRUE)) {
b = true;
- } else if (s.equals("false")) {
+ } else if (s.equals(MiscUtil.C_FALSE)) {
b = false;
- } else if (s.equals(env.getTrueStringValue())) {
+ } else if (s.equals(env.getTemplateBooleanFormat().getTrueStringValue())) {
b = true;
- } else if (s.equals(env.getFalseStringValue())) {
+ } else if (s.equals(env.getTemplateBooleanFormat().getFalseStringValue())) {
b = false;
} else {
throw new _MiscTemplateException(this, env,
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Configuration.java b/src/main/java/org/apache/freemarker/core/Configuration.java
index 52bfd19..c8e700a 100644
--- a/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -43,6 +43,7 @@ import java.util.TimeZone;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
import org.apache.freemarker.core.model.ObjectWrapper;
import org.apache.freemarker.core.model.ObjectWrapperAndUnwrapper;
import org.apache.freemarker.core.model.TemplateHashModelEx;
@@ -93,6 +94,8 @@ import org.apache.freemarker.core.util._NullArgumentException;
import org.apache.freemarker.core.util._SortedArraySet;
import org.apache.freemarker.core.util._StringUtil;
import org.apache.freemarker.core.util._UnmodifiableCompositeSet;
+import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
+import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
/**
* <b>The main entry point into the FreeMarker API</b>; encapsulates the configuration settings of FreeMarker,
@@ -142,7 +145,7 @@ import org.apache.freemarker.core.util._UnmodifiableCompositeSet;
* The methods that aren't for modifying settings, like {@link #getTemplate(String)}, are thread-safe.
*/
public final class Configuration extends MutableProcessingConfiguration<Configuration>
- implements Cloneable, ParserConfiguration, ProcessingConfiguration, CustomStateScope {
+ implements Cloneable, ParserAndProcessingConfiguration, CustomStateScope {
private static final String VERSION_PROPERTIES_PATH = "org/apache/freemarker/core/version.properties";
@@ -522,6 +525,16 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
return super.getTemplateExceptionHandler();
}
+ @Override
+ protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected ArithmeticEngine getInheritedArithmeticEngine() {
+ throw new BugException("Missing property value");
+ }
+
private void recreateTemplateResolverWith(
TemplateLoader loader, CacheStorage storage,
TemplateLookupStrategy templateLookupStrategy, TemplateNameFormat templateNameFormat,
@@ -767,8 +780,8 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
/**
* Sets a {@link TemplateConfigurationFactory} that will configure individual templates where their settings differ
* from those coming from the common {@link Configuration} object. A typical use case for that is specifying the
- * {@link TemplateConfiguration#setOutputFormat(OutputFormat) outputFormat} for templates based on their file
- * extension or parent directory.
+ * {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat) outputFormat} for templates based on their
+ * file extension or parent directory.
*
* <p>
* Note that the settings suggested by standard file extensions are stronger than that you set here. See
@@ -1003,7 +1016,42 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
}
}
}
-
+
+ @Override
+ protected ObjectWrapper getInheritedObjectWrapper() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected Charset getInheritedOutputEncoding() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected Charset getInheritedURLEscapingCharset() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected TemplateClassResolver getInheritedNewBuiltinClassResolver() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected boolean getInheritedAutoFlush() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected boolean getInheritedShowErrorTips() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected boolean getInheritedAPIBuiltinEnabled() {
+ throw new BugException("Missing property value");
+ }
+
/**
* Resets the setting to its default, as if it was never set. This means that when you change the
* {@code incompatibe_improvements} setting later, the default will also change as appropriate. Also
@@ -1033,6 +1081,11 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
localeExplicitlySet = true;
}
+ @Override
+ protected Locale getInheritedLocale() {
+ throw new BugException("Missing property value");
+ }
+
/**
* Resets the setting to its default, as if it was never set.
*
@@ -1065,6 +1118,66 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
timeZoneExplicitlySet = true;
}
+ @Override
+ protected TimeZone getInheritedTimeZone() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected TimeZone getInheritedSQLDateAndTimeTimeZone() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected String getInheritedNumberFormat() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) {
+ return null;
+ }
+
+ @Override
+ protected boolean getInheritedHasCustomFormats() {
+ return false;
+ }
+
+ @Override
+ protected String getInheritedBooleanFormat() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected String getInheritedTimeFormat() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected String getInheritedDateFormat() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected String getInheritedDateTimeFormat() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) {
+ return null;
+ }
+
/**
* Resets the setting to its default, as if it was never set.
*
@@ -1130,6 +1243,31 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
logTemplateExceptionsExplicitlySet = true;
}
+ @Override
+ protected boolean getInheritedLogTemplateExceptions() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected boolean getInheritedLazyImports() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected Boolean getInheritedLazyAutoImports() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected Map<String, String> getInheritedAutoImports() {
+ throw new BugException("Missing property value");
+ }
+
+ @Override
+ protected List<String> getInheritedAutoIncludes() {
+ throw new BugException("Missing property value");
+ }
+
/**
* Resets the setting to its default, as if it was never set. This means that when you change the
* {@code incompatibe_improvements} setting later, the default will also change as appropriate. Also
@@ -1260,8 +1398,8 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
* Auto-escaping has significance when a value is printed with <code>${...}</code> (or <code>#{...}</code>). If
* auto-escaping is on, FreeMarker will assume that the value is plain text (as opposed to markup or some kind of
* rich text), so it will escape it according the current output format (see {@link #setOutputFormat(OutputFormat)}
- * and {@link TemplateConfiguration#setOutputFormat(OutputFormat)}). If auto-escaping is off, FreeMarker will assume
- * that the string value is already in the output format, so it prints it as is to the output.
+ * and {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat)}). If auto-escaping is off, FreeMarker
+ * will assume that the string value is already in the output format, so it prints it as is to the output.
*
* <p>Further notes on auto-escaping:
* <ul>
@@ -1286,9 +1424,9 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
* One of the {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY},
* {@link #ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY}, and {@link #DISABLE_AUTO_ESCAPING_POLICY} constants.
*
- * @see TemplateConfiguration#setAutoEscapingPolicy(int)
+ * @see TemplateConfiguration.Builder#setAutoEscapingPolicy(int)
* @see Configuration#setOutputFormat(OutputFormat)
- * @see TemplateConfiguration#setOutputFormat(OutputFormat)
+ * @see TemplateConfiguration.Builder#setOutputFormat(OutputFormat)
*
* @since 2.3.24
*/
@@ -1573,15 +1711,15 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
* 2.3.24, it defaults to {@code true}, so the following standard file extensions take their effect:
*
* <ul>
- * <li>{@code ftlh}: Sets {@link TemplateConfiguration#setOutputFormat(OutputFormat) outputFormat} to
+ * <li>{@code ftlh}: Sets {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat) outputFormat} to
* {@code "HTML"} (i.e., {@link HTMLOutputFormat#INSTANCE}, unless the {@code "HTML"} name is overridden by
* {@link #setRegisteredCustomOutputFormats(Collection)}) and
- * {@link TemplateConfiguration#setAutoEscapingPolicy(int) autoEscapingPolicy} to
+ * {@link TemplateConfiguration.Builder#setAutoEscapingPolicy(int) autoEscapingPolicy} to
* {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}.
- * <li>{@code ftlx}: Sets {@link TemplateConfiguration#setOutputFormat(OutputFormat) outputFormat} to
+ * <li>{@code ftlx}: Sets {@link TemplateConfiguration.Builder#setOutputFormat(OutputFormat) outputFormat} to
* {@code "XML"} (i.e., {@link XMLOutputFormat#INSTANCE}, unless the {@code "XML"} name is overridden by
* {@link #setRegisteredCustomOutputFormats(Collection)}) and
- * {@link TemplateConfiguration#setAutoEscapingPolicy(int) autoEscapingPolicy} to
+ * {@link TemplateConfiguration.Builder#setAutoEscapingPolicy(int) autoEscapingPolicy} to
* {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}.
* </ul>
*
@@ -1647,6 +1785,11 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
return templateLanguage;
}
+ @Override
+ public boolean isTemplateLanguageSet() {
+ return true;
+ }
+
/**
* Sets the template language used; this is often overridden for certain file extension with
* {@link #setTemplateConfigurations(TemplateConfigurationFactory)}.
@@ -2041,7 +2184,7 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
* another, so <b>you should always set this setting</b>. If you don't know what charset your should chose,
* {@code "UTF-8"} is usually a good choice.
*
- * @param sourceEncoding The charset, for example {@link StandardCharsets#UTF_8}.
+ * @param sourceEncoding The charset, for example such as {@link StandardCharsets#UTF_8}.
*/
public void setSourceEncoding(Charset sourceEncoding) {
this.sourceEncoding = sourceEncoding;
@@ -2052,10 +2195,13 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
return sourceEncoding;
}
+ @Override
+ public boolean isSourceEncodingSet() {
+ return true;
+ }
+
/**
* Resets the setting to its default, as if it was never set.
- *
- * @since 2.3.26
*/
public void unsetSourceEncoding() {
if (sourceEncodingExplicitlySet) {
@@ -2547,73 +2693,12 @@ public final class Configuration extends MutableProcessingConfiguration<Configur
return super.getCorrectedNameForUnknownSetting(name);
}
-
- @Override
- protected void doAutoImportsAndIncludes(Environment env) throws TemplateException, IOException {
- Template t = env.getMainTemplate();
- doAutoImports(env, t);
- doAutoIncludes(env, t);
- }
- private void doAutoImports(Environment env, Template t) throws IOException, TemplateException {
- Map<String, String> envAutoImports = env.isAutoImportsSet() ? env.getAutoImports() : null;
- Map<String, String> tAutoImports = t.isAutoImportsSet() ? t.getAutoImports() : null;
-
- boolean lazyAutoImports = env.getLazyAutoImports() != null ? env.getLazyAutoImports() : env.getLazyImports();
-
- for (Map.Entry<String, String> autoImport : getAutoImports().entrySet()) {
- String nsVarName = autoImport.getKey();
- if ((tAutoImports == null || !tAutoImports.containsKey(nsVarName))
- && (envAutoImports == null || !envAutoImports.containsKey(nsVarName))) {
- env.importLib(autoImport.getValue(), nsVarName, lazyAutoImports);
- }
- }
- if (tAutoImports != null) {
- for (Map.Entry<String, String> autoImport : tAutoImports.entrySet()) {
- String nsVarName = autoImport.getKey();
- if (envAutoImports == null || !envAutoImports.containsKey(nsVarName)) {
- env.importLib(autoImport.getValue(), nsVarName, lazyAutoImports);
- }
- }
- }
- if (envAutoImports != null) {
- for (Map.Entry<String, String> autoImport : envAutoImports.entrySet()) {
- String nsVarName = autoImport.getKey();
- env.importLib(autoImport.getValue(), nsVarName, lazyAutoImports);
- }
- }
+ @Override
+ protected Object getInheritedCustomAttribute(Object name) {
+ return null;
}
-
- private void doAutoIncludes(Environment env, Template t) throws TemplateException, IOException {
- // We can't store autoIncludes in LinkedHashSet-s because setAutoIncludes(List) allows duplicates,
- // unfortunately. Yet we have to prevent duplicates among Configuration levels, with the lowest levels having
- // priority. So we build some Set-s to do that, but we avoid the most common cases where they aren't needed.
- List<String> tAutoIncludes = t.isAutoIncludesSet() ? t.getAutoIncludes() : null;
- List<String> envAutoIncludes = env.isAutoIncludesSet() ? env.getAutoIncludes() : null;
-
- for (String templateName : getAutoIncludes()) {
- if ((tAutoIncludes == null || !tAutoIncludes.contains(templateName))
- && (envAutoIncludes == null || !envAutoIncludes.contains(templateName))) {
- env.include(getTemplate(templateName, env.getLocale()));
- }
- }
-
- if (tAutoIncludes != null) {
- for (String templateName : tAutoIncludes) {
- if (envAutoIncludes == null || !envAutoIncludes.contains(templateName)) {
- env.include(getTemplate(templateName, env.getLocale()));
- }
- }
- }
-
- if (envAutoIncludes != null) {
- for (String templateName : envAutoIncludes) {
- env.include(getTemplate(templateName, env.getLocale()));
- }
- }
- }
-
/**
* Returns the FreeMarker version information, most importantly the major.minor.micro version numbers.
*
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Environment.java b/src/main/java/org/apache/freemarker/core/Environment.java
index 6733045..5382404 100644
--- a/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/src/main/java/org/apache/freemarker/core/Environment.java
@@ -42,6 +42,7 @@ import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
import org.apache.freemarker.core.model.ObjectWrapper;
import org.apache.freemarker.core.model.TemplateCollectionModel;
import org.apache.freemarker.core.model.TemplateDateModel;
@@ -128,6 +129,8 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
private Map<String, TemplateNumberFormat> cachedTemplateNumberFormats;
private Map<CustomStateKey, Object> customStateMap;
+ private TemplateBooleanFormat cachedTemplateBooleanFormat;
+
/**
* Stores the date/time/date-time formatters that are used when no format is explicitly given at the place of
* formatting. That is, in situations like ${lastModified} or even ${lastModified?date}, but not in situations like
@@ -321,6 +324,75 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
/**
+ * Executes the auto-imports and auto-includes for the main template of this environment.
+ * This is not meant to be called or overridden by code outside of FreeMarker.
+ */
+ private void doAutoImportsAndIncludes(Environment env) throws TemplateException, IOException {
+ Template t = getMainTemplate();
+ doAutoImports(t);
+ doAutoIncludes(t);
+ }
+
+ private void doAutoImports(Template t) throws IOException, TemplateException {
+ Map<String, String> envAutoImports = isAutoImportsSet() ? getAutoImports() : null;
+ Map<String, String> tAutoImports = t.isAutoImportsSet() ? t.getAutoImports() : null;
+
+ boolean lazyAutoImports = getLazyAutoImports() != null ? getLazyAutoImports() : getLazyImports();
+
+ for (Map.Entry<String, String> autoImport : configuration.getAutoImports().entrySet()) {
+ String nsVarName = autoImport.getKey();
+ if ((tAutoImports == null || !tAutoImports.containsKey(nsVarName))
+ && (envAutoImports == null || !envAutoImports.containsKey(nsVarName))) {
+ importLib(autoImport.getValue(), nsVarName, lazyAutoImports);
+ }
+ }
+ if (tAutoImports != null) {
+ for (Map.Entry<String, String> autoImport : tAutoImports.entrySet()) {
+ String nsVarName = autoImport.getKey();
+ if (envAutoImports == null || !envAutoImports.containsKey(nsVarName)) {
+ importLib(autoImport.getValue(), nsVarName, lazyAutoImports);
+ }
+ }
+ }
+ if (envAutoImports != null) {
+ for (Map.Entry<String, String> autoImport : envAutoImports.entrySet()) {
+ String nsVarName = autoImport.getKey();
+ importLib(autoImport.getValue(), nsVarName, lazyAutoImports);
+ }
+ }
+ }
+
+ private void doAutoIncludes(Template t) throws TemplateException, IOException {
+ // We can't store autoIncludes in LinkedHashSet-s because setAutoIncludes(List) allows duplicates,
+ // unfortunately. Yet we have to prevent duplicates among Configuration levels, with the lowest levels having
+ // priority. So we build some Set-s to do that, but we avoid the most common cases where they aren't needed.
+
+ List<String> tAutoIncludes = t.isAutoIncludesSet() ? t.getAutoIncludes() : null;
+ List<String> envAutoIncludes = isAutoIncludesSet() ? getAutoIncludes() : null;
+
+ for (String templateName : configuration.getAutoIncludes()) {
+ if ((tAutoIncludes == null || !tAutoIncludes.contains(templateName))
+ && (envAutoIncludes == null || !envAutoIncludes.contains(templateName))) {
+ include(configuration.getTemplate(templateName, getLocale()));
+ }
+ }
+
+ if (tAutoIncludes != null) {
+ for (String templateName : tAutoIncludes) {
+ if (envAutoIncludes == null || !envAutoIncludes.contains(templateName)) {
+ include(configuration.getTemplate(templateName, getLocale()));
+ }
+ }
+ }
+
+ if (envAutoIncludes != null) {
+ for (String templateName : envAutoIncludes) {
+ include(configuration.getTemplate(templateName, getLocale()));
+ }
+ }
+ }
+
+ /**
* "Visit" the template element.
*/
void visit(ASTElement element) throws IOException, TemplateException {
@@ -849,6 +921,21 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
@Override
+ protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() {
+ return getParent().getTemplateExceptionHandler();
+ }
+
+ @Override
+ protected ArithmeticEngine getInheritedArithmeticEngine() {
+ return getParent().getArithmeticEngine();
+ }
+
+ @Override
+ protected ObjectWrapper getInheritedObjectWrapper() {
+ return getParent().getObjectWrapper();
+ }
+
+ @Override
public void setLocale(Locale locale) {
Locale prevLocale = getLocale();
super.setLocale(locale);
@@ -874,6 +961,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
@Override
+ protected Locale getInheritedLocale() {
+ return getParent().getLocale();
+ }
+
+ @Override
public void setTimeZone(TimeZone timeZone) {
TimeZone prevTimeZone = getTimeZone();
super.setTimeZone(timeZone);
@@ -898,6 +990,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
@Override
+ protected TimeZone getInheritedTimeZone() {
+ return getParent().getTimeZone();
+ }
+
+ @Override
public void setSQLDateAndTimeTimeZone(TimeZone timeZone) {
TimeZone prevTimeZone = getSQLDateAndTimeTimeZone();
super.setSQLDateAndTimeTimeZone(timeZone);
@@ -921,6 +1018,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
}
+ @Override
+ protected TimeZone getInheritedSQLDateAndTimeTimeZone() {
+ return getParent().getSQLDateAndTimeTimeZone();
+ }
+
// Replace with Objects.equals in Java 7
private static boolean nullSafeEquals(Object o1, Object o2) {
if (o1 == o2) return true;
@@ -947,6 +1049,61 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
super.setURLEscapingCharset(urlEscapingCharset);
}
+ @Override
+ protected Charset getInheritedURLEscapingCharset() {
+ return getParent().getURLEscapingCharset();
+ }
+
+ @Override
+ protected TemplateClassResolver getInheritedNewBuiltinClassResolver() {
+ return getParent().getNewBuiltinClassResolver();
+ }
+
+ @Override
+ protected boolean getInheritedAutoFlush() {
+ return getParent().getAutoFlush();
+ }
+
+ @Override
+ protected boolean getInheritedShowErrorTips() {
+ return getParent().getShowErrorTips();
+ }
+
+ @Override
+ protected boolean getInheritedAPIBuiltinEnabled() {
+ return getParent().getAPIBuiltinEnabled();
+ }
+
+ @Override
+ protected boolean getInheritedLogTemplateExceptions() {
+ return getParent().getLogTemplateExceptions();
+ }
+
+ @Override
+ protected boolean getInheritedLazyImports() {
+ return getParent().getLazyImports();
+ }
+
+ @Override
+ protected Boolean getInheritedLazyAutoImports() {
+ return getParent().getLazyAutoImports();
+ }
+
+ @Override
+ protected Map<String, String> getInheritedAutoImports() {
+ return getParent().getAutoImports();
+ }
+
+ @Override
+ protected List<String> getInheritedAutoIncludes() {
+ return getParent().getAutoIncludes();
+ }
+
+ @Override
+ protected Object getInheritedCustomAttribute(Object name) {
+ return getParent().getCustomAttribute(name);
+ }
+
/*
* Note that altough it's not allowed to set this setting with the <tt>setting</tt> directive, it still must be
* allowed to set it from Java code while the template executes, since some frameworks allow templates to actually
@@ -958,6 +1115,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
super.setOutputEncoding(outputEncoding);
}
+ @Override
+ protected Charset getInheritedOutputEncoding() {
+ return getParent().getOutputEncoding();
+ }
+
/**
* Returns the name of the charset that should be used for URL encoding. This will be <code>null</code> if the
* information is not available. The function caches the return value, so it's quick to call it repeatedly.
@@ -1056,6 +1218,93 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
cachedTemplateNumberFormat = null;
}
+ @Override
+ protected String getInheritedNumberFormat() {
+ return getParent().getNumberFormat();
+ }
+
+ @Override
+ protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() {
+ return getParent().getCustomNumberFormats();
+ }
+
+ @Override
+ protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) {
+ return getParent().getCustomNumberFormat(name);
+ }
+
+ @Override
+ protected boolean getInheritedHasCustomFormats() {
+ return getParent().hasCustomFormats();
+ }
+
+ @Override
+ protected String getInheritedBooleanFormat() {
+ return getParent().getBooleanFormat();
+ }
+
+ String formatBoolean(boolean value, boolean fallbackToTrueFalse) throws TemplateException {
+ TemplateBooleanFormat templateBooleanFormat = getTemplateBooleanFormat();
+ if (value) {
+ String s = templateBooleanFormat.getTrueStringValue();
+ if (s == null) {
+ if (fallbackToTrueFalse) {
+ return MiscUtil.C_TRUE;
+ } else {
+ throw new _MiscTemplateException(getNullBooleanFormatErrorDescription());
+ }
+ } else {
+ return s;
+ }
+ } else {
+ String s = templateBooleanFormat.getFalseStringValue();
+ if (s == null) {
+ if (fallbackToTrueFalse) {
+ return MiscUtil.C_FALSE;
+ } else {
+ throw new _MiscTemplateException(getNullBooleanFormatErrorDescription());
+ }
+ } else {
+ return s;
+ }
+ }
+ }
+
+ TemplateBooleanFormat getTemplateBooleanFormat() {
+ TemplateBooleanFormat format = cachedTemplateBooleanFormat;
+ if (format == null) {
+ format = TemplateBooleanFormat.getInstance(getBooleanFormat());
+ cachedTemplateBooleanFormat = format;
+ }
+ return format;
+ }
+
+ @Override
+ public void setBooleanFormat(String booleanFormat) {
+ String previousFormat = getBooleanFormat();
+ super.setBooleanFormat(booleanFormat);
+ if (!booleanFormat.equals(previousFormat)) {
+ cachedTemplateBooleanFormat = null;
+ }
+ }
+
+ private _ErrorDescriptionBuilder getNullBooleanFormatErrorDescription() {
+ return new _ErrorDescriptionBuilder(
+ "Can't convert boolean to string automatically, because the \"", BOOLEAN_FORMAT_KEY ,"\" setting was ",
+ new _DelayedJQuote(getBooleanFormat()),
+ (getBooleanFormat().equals(TemplateBooleanFormat.C_TRUE_FALSE)
+ ? ", which is the legacy default computer-language format, and hence isn't accepted."
+ : ".")
+ ).tips(
+ "If you just want \"true\"/\"false\" result as you are generting computer-language output, "
+ + "use \"?c\", like ${myBool?c}.",
+ "You can write myBool?string('yes', 'no') and like to specify boolean formatting in place.",
+ new Object[] {
+ "If you need the same two values on most places, the programmers should set the \"",
+ BOOLEAN_FORMAT_KEY ,"\" setting to something like \"yes,no\"." }
+ );
+ }
+
/**
* Format number with the default number format.
*
@@ -1285,6 +1534,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
@Override
+ protected String getInheritedTimeFormat() {
+ return getParent().getTimeFormat();
+ }
+
+ @Override
public void setDateFormat(String dateFormat) {
String prevDateFormat = getDateFormat();
super.setDateFormat(dateFormat);
@@ -1298,6 +1552,11 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
@Override
+ protected String getInheritedDateFormat() {
+ return getParent().getDateFormat();
+ }
+
+ @Override
public void setDateTimeFormat(String dateTimeFormat) {
String prevDateTimeFormat = getDateTimeFormat();
super.setDateTimeFormat(dateTimeFormat);
@@ -1310,6 +1569,21 @@ public final class Environment extends MutableProcessingConfiguration<Environmen
}
}
+ @Override
+ protected String getInheritedDateTimeFormat() {
+ return getParent().getDateTimeFormat();
+ }
+
+ @Override
+ protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() {
+ return getParent().getCustomDateFormats();
+ }
+
+ @Override
+ protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) {
+ return getParent().getCustomDateFormat(name);
+ }
+
public Configuration getConfiguration() {
return configuration;
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
index 03cfb95..aaac98d 100644
--- a/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/MutableProcessingAndParseConfiguration.java
@@ -30,7 +30,7 @@ import org.apache.freemarker.core.util._NullArgumentException;
public abstract class MutableProcessingAndParseConfiguration<
SelfT extends MutableProcessingAndParseConfiguration<SelfT>>
extends MutableProcessingConfiguration<SelfT>
- implements ParserConfiguration {
+ implements ParserAndProcessingConfiguration {
private TemplateLanguage templateLanguage;
private Integer tagSyntax;
@@ -63,10 +63,10 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public int getTagSyntax() {
- return tagSyntax != null ? tagSyntax : getDefaultTagSyntax();
+ return tagSyntax != null ? tagSyntax : getInheritedTagSyntax();
}
- protected abstract int getDefaultTagSyntax();
+ protected abstract int getInheritedTagSyntax();
@Override
public boolean isTagSyntaxSet() {
@@ -78,10 +78,10 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public TemplateLanguage getTemplateLanguage() {
- return templateLanguage != null ? templateLanguage : getDefaultTemplateLanguage();
+ return isTemplateLanguageSet() ? templateLanguage : getInheritedTemplateLanguage();
}
- protected abstract TemplateLanguage getDefaultTemplateLanguage();
+ protected abstract TemplateLanguage getInheritedTemplateLanguage();
/**
* See {@link Configuration#setTemplateLanguage(TemplateLanguage)}
@@ -108,11 +108,11 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public int getNamingConvention() {
- return namingConvention != null ? namingConvention
- : getDefaultNamingConvention();
+ return isNamingConventionSet() ? namingConvention
+ : getInheritedNamingConvention();
}
- protected abstract int getDefaultNamingConvention();
+ protected abstract int getInheritedNamingConvention();
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
@@ -134,11 +134,11 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public boolean getWhitespaceStripping() {
- return whitespaceStripping != null ? whitespaceStripping.booleanValue()
- : getDefaultWhitespaceStripping();
+ return isWhitespaceStrippingSet() ? whitespaceStripping.booleanValue()
+ : getInheritedWhitespaceStripping();
}
- protected abstract boolean getDefaultWhitespaceStripping();
+ protected abstract boolean getInheritedWhitespaceStripping();
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
@@ -162,11 +162,11 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public int getAutoEscapingPolicy() {
- return autoEscapingPolicy != null ? autoEscapingPolicy.intValue()
- : getDefaultAutoEscapingPolicy();
+ return isAutoEscapingPolicySet() ? autoEscapingPolicy.intValue()
+ : getInheritedAutoEscapingPolicy();
}
- protected abstract int getDefaultAutoEscapingPolicy();
+ protected abstract int getInheritedAutoEscapingPolicy();
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
@@ -189,10 +189,10 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public OutputFormat getOutputFormat() {
- return outputFormat != null ? outputFormat : getDefaultOutputFormat();
+ return isOutputFormatSet() ? outputFormat : getInheritedOutputFormat();
}
- protected abstract OutputFormat getDefaultOutputFormat();
+ protected abstract OutputFormat getInheritedOutputFormat();
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
@@ -214,11 +214,11 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public boolean getRecognizeStandardFileExtensions() {
- return recognizeStandardFileExtensions != null ? recognizeStandardFileExtensions.booleanValue()
- : getDefaultRecognizeStandardFileExtensions();
+ return isRecognizeStandardFileExtensionsSet() ? recognizeStandardFileExtensions.booleanValue()
+ : getInheritedRecognizeStandardFileExtensions();
}
- protected abstract boolean getDefaultRecognizeStandardFileExtensions();
+ protected abstract boolean getInheritedRecognizeStandardFileExtensions();
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
@@ -228,11 +228,12 @@ public abstract class MutableProcessingAndParseConfiguration<
return recognizeStandardFileExtensions != null;
}
+ @Override
public Charset getSourceEncoding() {
- return sourceEncoding != null ? sourceEncoding : getDefaultSourceEncoding();
+ return isSourceEncodingSet() ? sourceEncoding : getInheritedSourceEncoding();
}
- protected abstract Charset getDefaultSourceEncoding();
+ protected abstract Charset getInheritedSourceEncoding();
/**
* The charset to be used when reading the template "file" that the {@link TemplateLoader} returns as binary
@@ -263,11 +264,10 @@ public abstract class MutableProcessingAndParseConfiguration<
*/
@Override
public int getTabSize() {
- return tabSize != null ? tabSize.intValue()
- : getDefaultTabSize();
+ return isTabSizeSet() ? tabSize.intValue() : getInheritedTabSize();
}
- protected abstract int getDefaultTabSize();
+ protected abstract int getInheritedTabSize();
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
index a1e756a..305194d 100644
--- a/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/MutableProcessingConfiguration.java
@@ -19,7 +19,6 @@
package org.apache.freemarker.core;
-import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
@@ -35,7 +34,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TimeZone;
@@ -91,8 +89,6 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
*/
public abstract class MutableProcessingConfiguration<SelfT extends MutableProcessingConfiguration<SelfT>>
implements ProcessingConfiguration {
- static final String C_TRUE_FALSE = "true,false";
-
public static final String NULL_VALUE = "null";
public static final String DEFAULT_VALUE = "default";
public static final String JVM_DEFAULT_VALUE = "JVM default";
@@ -321,20 +317,17 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
URL_ESCAPING_CHARSET_KEY_CAMEL_CASE
};
- private MutableProcessingConfiguration parent;
- private Map<Object, Object> customAttributes;
-
+ private ProcessingConfiguration parent;
+
private Locale locale;
private String numberFormat;
private String timeFormat;
private String dateFormat;
private String dateTimeFormat;
private TimeZone timeZone;
- private TimeZone sqlDataAndTimeTimeZone;
- private boolean sqlDataAndTimeTimeZoneSet;
+ private TimeZone sqlDateAndTimeTimeZone;
+ private boolean sqlDateAndTimeTimeZoneSet;
private String booleanFormat;
- private String trueStringValue; // deduced from booleanFormat
- private String falseStringValue; // deduced from booleanFormat
private TemplateExceptionHandler templateExceptionHandler;
private ArithmeticEngine arithmeticEngine;
private ObjectWrapper objectWrapper;
@@ -347,24 +340,27 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
private Boolean showErrorTips;
private Boolean apiBuiltinEnabled;
private Boolean logTemplateExceptions;
- private Map<String, ? extends TemplateDateFormatFactory> customDateFormats;
- private Map<String, ? extends TemplateNumberFormatFactory> customNumberFormats;
+ private Map<String, TemplateDateFormatFactory> customDateFormats;
+ private Map<String, TemplateNumberFormatFactory> customNumberFormats;
private LinkedHashMap<String, String> autoImports;
private ArrayList<String> autoIncludes;
private Boolean lazyImports;
private Boolean lazyAutoImports;
private boolean lazyAutoImportsSet;
-
+ private Map<Object, Object> customAttributes;
+
/**
* Called by the {@link Configuration} constructor, initializes the fields to their {@link Configuration}-level
* default without marking them as set.
*/
+ // TODO Move to Configuration(Builder) constructor
MutableProcessingConfiguration(Version incompatibleImprovements) {
_CoreAPI.checkVersionNotNullAndSupported(incompatibleImprovements);
parent = null;
locale = Configuration.getDefaultLocale();
timeZone = Configuration.getDefaultTimeZone();
- sqlDataAndTimeTimeZone = null;
+ sqlDateAndTimeTimeZone = null;
+ sqlDateAndTimeTimeZoneSet = true;
numberFormat = "number";
timeFormat = "";
dateFormat = "";
@@ -379,14 +375,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
logTemplateExceptions = Boolean.FALSE;
// outputEncoding and urlEscapingCharset defaults to null,
// which means "not specified"
- setBooleanFormat(C_TRUE_FALSE);
-
+ setBooleanFormat(TemplateBooleanFormat.C_TRUE_FALSE);
customDateFormats = Collections.emptyMap();
customNumberFormats = Collections.emptyMap();
-
+ outputEncodingSet = true;
+ urlEscapingCharsetSet = true;
+
lazyImports = false;
lazyAutoImportsSet = true;
-
initAutoImportsMap();
initAutoIncludesList();
}
@@ -420,7 +416,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* @return The parent {@link MutableProcessingConfiguration} object, or {@code null} if this is the root {@link MutableProcessingConfiguration} object
* (i.e, if it's the {@link Configuration} object).
*/
- public final MutableProcessingConfiguration getParent() {
+ public final ProcessingConfiguration getParent() {
return parent;
}
@@ -429,7 +425,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* template - the included template becomes the parent configurable during
* its evaluation.
*/
- void setParent(MutableProcessingConfiguration parent) {
+ void setParent(ProcessingConfiguration parent) {
this.parent = parent;
}
@@ -454,9 +450,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
@Override
public Locale getLocale() {
- return locale != null ? locale : parent.getLocale();
+ return isLocaleSet() ? locale : getInheritedLocale();
}
+ protected abstract Locale getInheritedLocale();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -496,9 +494,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public TimeZone getTimeZone() {
- return timeZone != null ? timeZone : parent.getTimeZone();
+ return isTimeZoneSet() ? timeZone : getInheritedTimeZone();
}
-
+
+ protected abstract TimeZone getInheritedTimeZone();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -571,8 +571,8 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* @since 2.3.21
*/
public void setSQLDateAndTimeTimeZone(TimeZone tz) {
- sqlDataAndTimeTimeZone = tz;
- sqlDataAndTimeTimeZoneSet = true;
+ sqlDateAndTimeTimeZone = tz;
+ sqlDateAndTimeTimeZoneSet = true;
}
/**
@@ -595,11 +595,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public TimeZone getSQLDateAndTimeTimeZone() {
- return sqlDataAndTimeTimeZoneSet
- ? sqlDataAndTimeTimeZone
- : (parent != null ? parent.getSQLDateAndTimeTimeZone() : null);
+ return sqlDateAndTimeTimeZoneSet
+ ? sqlDateAndTimeTimeZone
+ : getInheritedSQLDateAndTimeTimeZone();
}
-
+
+ protected abstract TimeZone getInheritedSQLDateAndTimeTimeZone();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -607,7 +609,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public boolean isSQLDateAndTimeTimeZoneSet() {
- return sqlDataAndTimeTimeZoneSet;
+ return sqlDateAndTimeTimeZoneSet;
}
/**
@@ -653,9 +655,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public String getNumberFormat() {
- return numberFormat != null ? numberFormat : parent.getNumberFormat();
+ return isNumberFormatSet() ? numberFormat : getInheritedNumberFormat();
}
+ protected abstract String getInheritedNumberFormat();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -682,10 +686,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* @since 2.3.24
*/
@Override
- public Map<String, ? extends TemplateNumberFormatFactory> getCustomNumberFormats() {
- return customNumberFormats == null ? parent.getCustomNumberFormats() : customNumberFormats;
+ public Map<String, TemplateNumberFormatFactory> getCustomNumberFormats() {
+ return isCustomNumberFormatsSet() ? customNumberFormats : getInheritedCustomNumberFormats();
}
+ protected abstract Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats();
+
/**
* Associates names with formatter factories, which then can be referred by the {@link #setNumberFormat(String)
* number_format} setting with values starting with <code>@<i>name</i></code>. Beware, if you specify any custom
@@ -700,7 +706,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*
* @since 2.3.24
*/
- public void setCustomNumberFormats(Map<String, ? extends TemplateNumberFormatFactory> customNumberFormats) {
+ public void setCustomNumberFormats(Map<String, TemplateNumberFormatFactory> customNumberFormats) {
_NullArgumentException.check("customNumberFormats", customNumberFormats);
validateFormatNames(customNumberFormats.keySet());
this.customNumberFormats = customNumberFormats;
@@ -709,7 +715,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
/**
* Fluent API equivalent of {@link #setCustomNumberFormats(Map)}
*/
- public SelfT customNumberFormats(Map<String, ? extends TemplateNumberFormatFactory> value) {
+ public SelfT customNumberFormats(Map<String, TemplateNumberFormatFactory> value) {
setCustomNumberFormats(value);
return self();
}
@@ -752,6 +758,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*
* @since 2.3.24
*/
+ @Override
public TemplateNumberFormatFactory getCustomNumberFormat(String name) {
TemplateNumberFormatFactory r;
if (customNumberFormats != null) {
@@ -760,20 +767,24 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
return r;
}
}
- return parent != null ? parent.getCustomNumberFormat(name) : null;
+ return getInheritedCustomNumberFormat(name);
}
-
+
+ protected abstract TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name);
+
/**
* Tells if this configurable object or its parent defines any custom formats.
*
* @since 2.3.24
*/
public boolean hasCustomFormats() {
- return customNumberFormats != null && !customNumberFormats.isEmpty()
- || customDateFormats != null && !customDateFormats.isEmpty()
- || getParent() != null && getParent().hasCustomFormats();
+ return isCustomNumberFormatsSet() && !customNumberFormats.isEmpty()
+ || isCustomDateFormatsSet() && !customDateFormats.isEmpty()
+ || getInheritedHasCustomFormats();
}
-
+
+ protected abstract boolean getInheritedHasCustomFormats();
+
/**
* The string value for the boolean {@code true} and {@code false} values, intended for human audience (not for a
* computer language), separated with comma. For example, {@code "yes,no"}. Note that white-space is significant,
@@ -797,16 +808,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
}
this.booleanFormat = booleanFormat;
-
- if (booleanFormat.equals(C_TRUE_FALSE)) {
- // C_TRUE_FALSE is the default for BC, but it's not a good default for human audience formatting, so we
- // pretend that it wasn't set.
- trueStringValue = null;
- falseStringValue = null;
- } else {
- trueStringValue = booleanFormat.substring(0, commaIdx);
- falseStringValue = booleanFormat.substring(commaIdx + 1);
- }
}
/**
@@ -822,9 +823,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public String getBooleanFormat() {
- return booleanFormat != null ? booleanFormat : parent.getBooleanFormat();
+ return isBooleanFormatSet() ? booleanFormat : getInheritedBooleanFormat();
}
-
+
+ protected abstract String getInheritedBooleanFormat();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -834,75 +837,6 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
public boolean isBooleanFormatSet() {
return booleanFormat != null;
}
-
- String formatBoolean(boolean value, boolean fallbackToTrueFalse) throws TemplateException {
- if (value) {
- String s = getTrueStringValue();
- if (s == null) {
- if (fallbackToTrueFalse) {
- return MiscUtil.C_TRUE;
- } else {
- throw new _MiscTemplateException(getNullBooleanFormatErrorDescription());
- }
- } else {
- return s;
- }
- } else {
- String s = getFalseStringValue();
- if (s == null) {
- if (fallbackToTrueFalse) {
- return MiscUtil.C_FALSE;
- } else {
- throw new _MiscTemplateException(getNullBooleanFormatErrorDescription());
- }
- } else {
- return s;
- }
- }
- }
-
- private _ErrorDescriptionBuilder getNullBooleanFormatErrorDescription() {
- return new _ErrorDescriptionBuilder(
- "Can't convert boolean to string automatically, because the \"", BOOLEAN_FORMAT_KEY ,"\" setting was ",
- new _DelayedJQuote(getBooleanFormat()),
- (getBooleanFormat().equals(C_TRUE_FALSE)
- ? ", which is the legacy default computer-language format, and hence isn't accepted."
- : ".")
- ).tips(
- "If you just want \"true\"/\"false\" result as you are generting computer-language output, "
- + "use \"?c\", like ${myBool?c}.",
- "You can write myBool?string('yes', 'no') and like to specify boolean formatting in place.",
- new Object[] {
- "If you need the same two values on most places, the programmers should set the \"",
- BOOLEAN_FORMAT_KEY ,"\" setting to something like \"yes,no\"." }
- );
- }
-
- /**
- * Returns the string to which {@code true} is converted to for human audience, or {@code null} if automatic
- * coercion to string is not allowed. The default value is {@code null}.
- *
- * <p>This value is deduced from the {@code "boolean_format"} setting.
- * Confusingly, for backward compatibility (at least until 2.4) that defaults to {@code "true,false"}, yet this
- * defaults to {@code null}. That's so because {@code "true,false"} is treated exceptionally, as that default is a
- * historical mistake in FreeMarker, since it targets computer language output, not human writing. Thus it's
- * ignored.
- *
- * @since 2.3.20
- */
- String getTrueStringValue() {
- // The first step deliberately tests booleanFormat instead of trueStringValue!
- return booleanFormat != null ? trueStringValue : (parent != null ? parent.getTrueStringValue() : null);
- }
-
- /**
- * Same as {@link #getTrueStringValue()} but with {@code false}.
- * @since 2.3.20
- */
- String getFalseStringValue() {
- // The first step deliberately tests booleanFormat instead of falseStringValue!
- return booleanFormat != null ? falseStringValue : (parent != null ? parent.getFalseStringValue() : null);
- }
/**
* Sets the format used to convert {@link java.util.Date}-s to string-s that are time (no date part) values,
@@ -930,9 +864,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public String getTimeFormat() {
- return timeFormat != null ? timeFormat : parent.getTimeFormat();
+ return isTimeFormatSet() ? timeFormat : getInheritedTimeFormat();
}
+ protected abstract String getInheritedTimeFormat();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -969,9 +905,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public String getDateFormat() {
- return dateFormat != null ? dateFormat : parent.getDateFormat();
+ return isDateFormatSet() ? dateFormat : getInheritedDateFormat();
}
+ protected abstract String getInheritedDateFormat();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1086,9 +1024,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public String getDateTimeFormat() {
- return dateTimeFormat != null ? dateTimeFormat : parent.getDateTimeFormat();
+ return isDateTimeFormatSet() ? dateTimeFormat : getInheritedDateTimeFormat();
}
-
+
+ protected abstract String getInheritedDateTimeFormat();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1115,10 +1055,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* @since 2.3.24
*/
@Override
- public Map<String, ? extends TemplateDateFormatFactory> getCustomDateFormats() {
- return customDateFormats == null ? parent.getCustomDateFormats() : customDateFormats;
+ public Map<String, TemplateDateFormatFactory> getCustomDateFormats() {
+ return isCustomDateFormatsSet() ? customDateFormats : getInheritedCustomDateFormats();
}
+ protected abstract Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats();
+
/**
* Associates names with formatter factories, which then can be referred by the {@link #setDateTimeFormat(String)
* date_format}, {@link #setDateTimeFormat(String) time_format}, and {@link #setDateTimeFormat(String)
@@ -1134,7 +1076,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*
* @since 2.3.24
*/
- public void setCustomDateFormats(Map<String, ? extends TemplateDateFormatFactory> customDateFormats) {
+ public void setCustomDateFormats(Map<String, TemplateDateFormatFactory> customDateFormats) {
_NullArgumentException.check("customDateFormats", customDateFormats);
validateFormatNames(customDateFormats.keySet());
this.customDateFormats = customDateFormats;
@@ -1143,7 +1085,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
/**
* Fluent API equivalent of {@link #setCustomDateFormats(Map)}
*/
- public SelfT customDateFormats(Map<String, ? extends TemplateDateFormatFactory> value) {
+ public SelfT customDateFormats(Map<String, TemplateDateFormatFactory> value) {
setCustomDateFormats(value);
return self();
}
@@ -1163,6 +1105,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*
* @since 2.3.24
*/
+ @Override
public TemplateDateFormatFactory getCustomDateFormat(String name) {
TemplateDateFormatFactory r;
if (customDateFormats != null) {
@@ -1171,9 +1114,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
return r;
}
}
- return parent != null ? parent.getCustomDateFormat(name) : null;
+ return getInheritedCustomDateFormat(name);
}
-
+
+ protected abstract TemplateDateFormatFactory getInheritedCustomDateFormat(String name);
+
/**
* Sets the exception handler used to handle exceptions occurring inside templates.
* The default is {@link TemplateExceptionHandler#DEBUG_HANDLER}. The recommended values are:
@@ -1212,10 +1157,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public TemplateExceptionHandler getTemplateExceptionHandler() {
- return templateExceptionHandler != null
- ? templateExceptionHandler : parent.getTemplateExceptionHandler();
+ return isTemplateExceptionHandlerSet()
+ ? templateExceptionHandler : getInheritedTemplateExceptionHandler();
}
+ protected abstract TemplateExceptionHandler getInheritedTemplateExceptionHandler();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1248,10 +1195,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public ArithmeticEngine getArithmeticEngine() {
- return arithmeticEngine != null
- ? arithmeticEngine : parent.getArithmeticEngine();
+ return isArithmeticEngineSet()
+ ? arithmeticEngine : getInheritedArithmeticEngine();
}
+ protected abstract ArithmeticEngine getInheritedArithmeticEngine();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1284,10 +1233,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public ObjectWrapper getObjectWrapper() {
- return objectWrapper != null
- ? objectWrapper : parent.getObjectWrapper();
+ return isObjectWrapperSet()
+ ? objectWrapper : getInheritedObjectWrapper();
}
+ protected abstract ObjectWrapper getInheritedObjectWrapper();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1321,11 +1272,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
@Override
public Charset getOutputEncoding() {
- return outputEncodingSet
+ return isOutputEncodingSet()
? outputEncoding
- : (parent != null ? parent.getOutputEncoding() : null);
+ : getInheritedOutputEncoding();
}
+ protected abstract Charset getInheritedOutputEncoding();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1357,11 +1310,13 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
@Override
public Charset getURLEscapingCharset() {
- return urlEscapingCharsetSet
+ return isURLEscapingCharsetSet()
? urlEscapingCharset
- : (parent != null ? parent.getURLEscapingCharset() : null);
+ : getInheritedURLEscapingCharset();
}
+ protected abstract Charset getInheritedURLEscapingCharset();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1407,10 +1362,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public TemplateClassResolver getNewBuiltinClassResolver() {
- return newBuiltinClassResolver != null
- ? newBuiltinClassResolver : parent.getNewBuiltinClassResolver();
+ return isNewBuiltinClassResolverSet()
+ ? newBuiltinClassResolver : getInheritedNewBuiltinClassResolver();
}
+ protected abstract TemplateClassResolver getInheritedNewBuiltinClassResolver();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1456,11 +1413,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public boolean getAutoFlush() {
- return autoFlush != null
- ? autoFlush.booleanValue()
- : (parent != null ? parent.getAutoFlush() : true);
+ return isAutoFlushSet() ? autoFlush.booleanValue() : getInheritedAutoFlush();
}
+ protected abstract boolean getInheritedAutoFlush();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1496,11 +1453,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public boolean getShowErrorTips() {
- return showErrorTips != null
- ? showErrorTips.booleanValue()
- : (parent != null ? parent.getShowErrorTips() : true);
+ return isShowErrorTipsSet() ? showErrorTips : getInheritedShowErrorTips();
}
+ protected abstract boolean getInheritedShowErrorTips();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1534,17 +1491,19 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*
* @since 2.3.22
*/
- public boolean isAPIBuiltinEnabled() {
- return apiBuiltinEnabled != null
- ? apiBuiltinEnabled.booleanValue()
- : (parent != null ? parent.isAPIBuiltinEnabled() : false);
+ @Override
+ public boolean getAPIBuiltinEnabled() {
+ return isAPIBuiltinEnabledSet() ? apiBuiltinEnabled : getInheritedAPIBuiltinEnabled();
}
+ protected abstract boolean getInheritedAPIBuiltinEnabled();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
* @since 2.3.24
*/
+ @Override
public boolean isAPIBuiltinEnabledSet() {
return apiBuiltinEnabled != null;
}
@@ -1561,7 +1520,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* @since 2.3.22
*/
public void setLogTemplateExceptions(boolean value) {
- logTemplateExceptions = Boolean.valueOf(value);
+ logTemplateExceptions = value;
}
/**
@@ -1571,11 +1530,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public boolean getLogTemplateExceptions() {
- return logTemplateExceptions != null
- ? logTemplateExceptions.booleanValue()
- : (parent != null ? parent.getLogTemplateExceptions() : true);
+ return isLogTemplateExceptionsSet() ? logTemplateExceptions : getInheritedLogTemplateExceptions();
}
+ protected abstract boolean getInheritedLogTemplateExceptions();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1593,9 +1552,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public boolean getLazyImports() {
- return lazyImports != null ? lazyImports.booleanValue() : parent.getLazyImports();
+ return isLazyImportsSet() ? lazyImports : getInheritedLazyImports();
}
-
+
+ protected abstract boolean getInheritedLazyImports();
+
/**
* 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
@@ -1619,7 +1580,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
* @since 2.3.25
*/
public void setLazyImports(boolean lazyImports) {
- this.lazyImports = Boolean.valueOf(lazyImports);
+ this.lazyImports = lazyImports;
}
/**
@@ -1639,9 +1600,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public Boolean getLazyAutoImports() {
- return lazyAutoImportsSet ? lazyAutoImports : parent.getLazyAutoImports();
+ return isLazyAutoImportsSet() ? lazyAutoImports : getInheritedLazyAutoImports();
}
+ protected abstract Boolean getInheritedLazyAutoImports();
+
/**
* 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>
@@ -1776,9 +1739,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public Map<String, String> getAutoImports() {
- return autoImports != null ? autoImports : parent.getAutoImports();
+ return isAutoImportsSet() ? autoImports : getInheritedAutoImports();
}
-
+
+ protected abstract Map<String,String> getInheritedAutoImports();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -1870,9 +1835,11 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
@Override
public List<String> getAutoIncludes() {
- return autoIncludes != null ? autoIncludes : parent.getAutoIncludes();
+ return isAutoIncludesSet() ? autoIncludes : getInheritedAutoIncludes();
}
-
+
+ protected abstract List<String> getInheritedAutoIncludes();
+
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*
@@ -2491,14 +2458,14 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
*/
protected final UnknownConfigurationSettingException unknownSettingException(String name) {
Version removalVersion = getRemovalVersionForUnknownSetting(name);
- return removalVersion != null
+ return removalVersion != null
? new UnknownConfigurationSettingException(name, removalVersion)
: new UnknownConfigurationSettingException(name, getCorrectedNameForUnknownSetting(name));
}
/**
- * If a setting name is unknown because it was removed over time, then returns the version where it was removed,
- * otherwise returns {@code null}.
+ * If a setting name is unknown because it was removed over time (not just renamed), then returns the version where
+ * it was removed, otherwise returns {@code null}.
*/
protected Version getRemovalVersionForUnknownSetting(String name) {
if (name.equals("classic_compatible") || name.equals("classicCompatible")) {
@@ -2565,31 +2532,7 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
}
boolean isCustomAttributeSet(Object key) {
- return customAttributes != null && customAttributes.containsKey(key);
- }
-
- /**
- * For internal usage only, copies the custom attributes set directly on this objects into another
- * {@link MutableProcessingConfiguration}. The target {@link MutableProcessingConfiguration} is assumed to be not seen be other thread than the current
- * one yet. (That is, the operation is not synchronized on the target {@link MutableProcessingConfiguration}, only on the source
- * {@link MutableProcessingConfiguration})
- *
- * @since 2.3.24
- */
- void copyDirectCustomAttributes(MutableProcessingConfiguration target, boolean overwriteExisting) {
- if (customAttributes == null) {
- return;
- }
- for (Entry<?, ?> custAttrEnt : customAttributes.entrySet()) {
- Object custAttrKey = custAttrEnt.getKey();
- if (overwriteExisting || !target.isCustomAttributeSet(custAttrKey)) {
- if (custAttrKey instanceof String) {
- target.setCustomAttribute((String) custAttrKey, custAttrEnt.getValue());
- } else {
- target.setCustomAttribute(custAttrKey, custAttrEnt.getValue());
- }
- }
- }
+ return isCustomAttributesSet() && customAttributes.containsKey(key);
}
/**
@@ -2673,19 +2616,12 @@ public abstract class MutableProcessingConfiguration<SelfT extends MutableProces
r = null;
}
if (r == null && parent != null) {
- return parent.getCustomAttribute(name);
+ return getInheritedCustomAttribute(name);
}
return r;
}
-
- /**
- * Executes the auto-imports and auto-includes for the main template of this environment.
- * This is not meant to be called or overridden by code outside of FreeMarker.
- */
- protected void doAutoImportsAndIncludes(Environment env)
- throws TemplateException, IOException {
- if (parent != null) parent.doAutoImportsAndIncludes(env);
- }
+
+ protected abstract Object getInheritedCustomAttribute(Object name);
protected final List<String> parseAsList(String text) throws GenericParseException {
return new SettingStringParser(text).parseAsList();
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java
new file mode 100644
index 0000000..9398242
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/ParserAndProcessingConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+/**
+ * <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is the union of
+ * {@link ProcessingConfiguration} and {@link ParserConfiguration}, which is useful for declaring types for values
+ * that must implement both interfaces.
+ */
+public interface ParserAndProcessingConfiguration extends ParserConfiguration, ProcessingConfiguration {
+ // No additional method
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
index e515826..599adbb 100644
--- a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
@@ -31,12 +31,13 @@ import org.apache.freemarker.core.outputformat.OutputFormat;
* implementation.
*
* @see ProcessingConfiguration
- * @since 2.3.24
*/
public interface ParserConfiguration {
TemplateLanguage getTemplateLanguage();
+ boolean isTemplateLanguageSet();
+
/**
* See {@link Configuration#getTagSyntax()}.
*/
@@ -147,4 +148,6 @@ public interface ParserConfiguration {
*/
Charset getSourceEncoding();
+ boolean isSourceEncodingSet();
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
index 33b028e..b224a01 100644
--- a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
@@ -97,7 +97,9 @@ public interface ProcessingConfiguration {
/**
* Getter pair of {@link MutableProcessingConfiguration#setCustomNumberFormats(Map)}.
*/
- Map<String, ? extends TemplateNumberFormatFactory> getCustomNumberFormats();
+ Map<String, TemplateNumberFormatFactory> getCustomNumberFormats();
+
+ TemplateNumberFormatFactory getCustomNumberFormat(String name);
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
@@ -106,6 +108,8 @@ public interface ProcessingConfiguration {
*/
boolean isCustomNumberFormatsSet();
+ boolean hasCustomFormats();
+
/**
* Getter pair of {@link MutableProcessingConfiguration#setBooleanFormat(String)}.
*/
@@ -157,7 +161,9 @@ public interface ProcessingConfiguration {
/**
* Getter pair of {@link MutableProcessingConfiguration#setCustomDateFormats(Map)}.
*/
- Map<String, ? extends TemplateDateFormatFactory> getCustomDateFormats();
+ Map<String, TemplateDateFormatFactory> getCustomDateFormats();
+
+ TemplateDateFormatFactory getCustomDateFormat(String name);
/**
* Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
@@ -238,6 +244,10 @@ public interface ProcessingConfiguration {
*/
boolean isNewBuiltinClassResolverSet();
+ boolean getAPIBuiltinEnabled();
+
+ boolean isAPIBuiltinEnabledSet();
+
/**
* Getter pair of {@link MutableProcessingConfiguration#setAutoFlush(boolean)}.
*/
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/88baea20/src/main/java/org/apache/freemarker/core/Template.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Template.java b/src/main/java/org/apache/freemarker/core/Template.java
index a82c131..dcde5d9 100644
--- a/src/main/java/org/apache/freemarker/core/Template.java
+++ b/src/main/java/org/apache/freemarker/core/Template.java
@@ -38,9 +38,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.TimeZone;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
import org.apache.freemarker.core.debug._DebuggerService;
import org.apache.freemarker.core.model.ObjectWrapper;
import org.apache.freemarker.core.model.TemplateHashModel;
@@ -53,6 +55,8 @@ import org.apache.freemarker.core.templateresolver.TemplateLookupStrategy;
import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver;
import org.apache.freemarker.core.util.BugException;
import org.apache.freemarker.core.util._NullArgumentException;
+import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
+import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
/**
* <p>
@@ -111,6 +115,10 @@ public class Template extends MutableProcessingConfiguration<Template> implement
this.name = name;
this.sourceName = sourceName;
templateLanguageVersion = normalizeTemplateLanguageVersion(cfg.getIncompatibleImprovements());
+ if (customParserConfiguration instanceof TemplateConfiguration.Builder) {
+ throw new IllegalArgumentException("Using TemplateConfiguration.Builder as Template constructor "
+ + "argument is not allowed; the TemplateConfiguration that it has built is needed instead.");
+ }
parserConfiguration = customParserConfiguration != null ? customParserConfiguration : getConfiguration();
}
@@ -732,6 +740,146 @@ public class Template extends MutableProcessingConfiguration<Template> implement
return buf.toString();
}
+ @Override
+ protected Locale getInheritedLocale() {
+ return getParent().getLocale();
+ }
+
+ @Override
+ protected TimeZone getInheritedTimeZone() {
+ return getParent().getTimeZone();
+ }
+
+ @Override
+ protected TimeZone getInheritedSQLDateAndTimeTimeZone() {
+ return getParent().getSQLDateAndTimeTimeZone();
+ }
+
+ @Override
+ protected String getInheritedNumberFormat() {
+ return getParent().getNumberFormat();
+ }
+
+ @Override
+ protected Map<String, TemplateNumberFormatFactory> getInheritedCustomNumberFormats() {
+ return getParent().getCustomNumberFormats();
+ }
+
+ @Override
+ protected TemplateNumberFormatFactory getInheritedCustomNumberFormat(String name) {
+ return getParent().getCustomNumberFormat(name);
+ }
+
+ @Override
+ protected boolean getInheritedHasCustomFormats() {
+ return getParent().hasCustomFormats();
+ }
+
+ @Override
+ protected String getInheritedBooleanFormat() {
+ return getParent().getBooleanFormat();
+ }
+
+ @Override
+ protected String getInheritedTimeFormat() {
+ return getParent().getTimeFormat();
+ }
+
+ @Override
+ protected String getInheritedDateFormat() {
+ return getParent().getDateFormat();
+ }
+
+ @Override
+ protected String getInheritedDateTimeFormat() {
+ return getParent().getDateTimeFormat();
+ }
+
+ @Override
+ protected Map<String, TemplateDateFormatFactory> getInheritedCustomDateFormats() {
+ return getParent().getCustomDateFormats();
+ }
+
+ @Override
+ protected TemplateDateFormatFactory getInheritedCustomDateFormat(String name) {
+ return getParent().getCustomDateFormat(name);
+ }
+
+ @Override
+ protected TemplateExceptionHandler getInheritedTemplateExceptionHandler() {
+ return getParent().getTemplateExceptionHandler();
+ }
+
+ @Override
+ protected ArithmeticEngine getInheritedArithmeticEngine() {
+ return getParent().getArithmeticEngine();
+ }
+
+ @Override
+ protected ObjectWrapper getInheritedObjectWrapper() {
+ return getParent().getObjectWrapper();
+ }
+
+ @Override
+ protected Charset getInheritedOutputEncoding() {
+ return getParent().getOutputEncoding();
+ }
+
+ @Override
+ protected Charset getInheritedURLEscapingCharset() {
+ return getParent().getURLEscapingCharset();
+ }
+
+ @Override
+ protected TemplateClassResolver getInheritedNewBuiltinClassResolver() {
+ return getParent().getNewBuiltinClassResolver();
+ }
+
+ @Override
+ protected boolean getInheritedAutoFlush() {
+ return getParent().getAutoFlush();
+ }
+
+ @Override
+ protected boolean getInheritedShowErrorTips() {
+ return getParent().getShowErrorTips();
+ }
+
+ @Override
+ protected boolean getInheritedAPIBuiltinEnabled() {
+ return getParent().getAPIBuiltinEnabled();
+ }
+
+ @Override
+ protected boolean getInheritedLogTemplateExceptions() {
+ return getParent().getLogTemplateExceptions();
+ }
+
+ @Override
+ protected boolean getInheritedLazyImports() {
+ return getParent().getLazyImports();
+ }
+
+ @Override
+ protected Boolean getInheritedLazyAutoImports() {
+ return getParent().getLazyAutoImports();
+ }
+
+ @Override
+ protected Map<String, String> getInheritedAutoImports() {
+ return getParent().getAutoImports();
+ }
+
+ @Override
+ protected List<String> getInheritedAutoIncludes() {
+ return getParent().getAutoIncludes();
+ }
+
+ @Override
+ protected Object getInheritedCustomAttribute(Object name) {
+ return getParent().getCustomAttribute(name);
+ }
+
/**
* Reader that builds up the line table info for us, and also helps in working around JavaCC's exception
* suppression.