Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 44754200C3D for ; Tue, 14 Mar 2017 21:55:15 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 417B5160B7E; Tue, 14 Mar 2017 20:55:15 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 13372160B63 for ; Tue, 14 Mar 2017 21:55:13 +0100 (CET) Received: (qmail 81625 invoked by uid 500); 14 Mar 2017 20:55:11 -0000 Mailing-List: contact notifications-help@freemarker.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@freemarker.incubator.apache.org Delivered-To: mailing list notifications@freemarker.incubator.apache.org Received: (qmail 81616 invoked by uid 99); 14 Mar 2017 20:55:11 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Mar 2017 20:55:11 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id 4128D18063D for ; Tue, 14 Mar 2017 20:55:11 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.569 X-Spam-Level: X-Spam-Status: No, score=-3.569 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_NEUTRAL=0.652] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id hfc8BUql8Ble for ; Tue, 14 Mar 2017 20:55:07 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id B645260D08 for ; Tue, 14 Mar 2017 20:55:06 +0000 (UTC) Received: (qmail 64009 invoked by uid 99); 14 Mar 2017 20:48:26 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Mar 2017 20:48:26 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id A3E12DFDC5; Tue, 14 Mar 2017 20:48:26 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ddekany@apache.org To: notifications@freemarker.incubator.apache.org Date: Tue, 14 Mar 2017 20:48:28 -0000 Message-Id: <5279ea038f9344eb8ac20fe30f3eb4fd@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [3/3] incubator-freemarker git commit: Forward ported from 2.3-gae: archived-at: Tue, 14 Mar 2017 20:55:15 -0000 Forward ported from 2.3-gae: Added Configuration.isXxxExplictlySet and Configuration.unsetXxx methods for the Configuration settings: locale, time_zone, default_encoding. (This can be utilized in frameworks to detect if the application has missed setting these. The backward compatible default values are often unwanted, as they are the default locale, time zone and file encoding of the Java environment.) The locale and default_encoding configuration settings now supports the special "JVM default" value when set from Java .properties file, or via Configuration.setSettings(Properties), or via the #setting directive. Earlier only the time_zone setting has supported this value. Ensure that the configuration settings don't depend on the machine that runs the test. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/755b25a3 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/755b25a3 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/755b25a3 Branch: refs/heads/3 Commit: 755b25a3e1d6e0c0363609d9a73ba80210df2e81 Parents: 98fd94e Author: ddekany Authored: Tue Mar 14 21:47:29 2017 +0100 Committer: ddekany Committed: Tue Mar 14 21:48:17 2017 +0100 ---------------------------------------------------------------------- .../apache/freemarker/core/Configurable.java | 22 ++-- .../apache/freemarker/core/Configuration.java | 118 +++++++++++++++++-- .../freemarker/core/ConfigurationTest.java | 65 +++++++++- .../apache/freemarker/core/SQLTimeZoneTest.java | 2 + .../apache/freemarker/test/TemplateTest.java | 18 +++ 5 files changed, 204 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/755b25a3/src/main/java/org/apache/freemarker/core/Configurable.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/Configurable.java b/src/main/java/org/apache/freemarker/core/Configurable.java index 122a3c0..c2aeb85 100644 --- a/src/main/java/org/apache/freemarker/core/Configurable.java +++ b/src/main/java/org/apache/freemarker/core/Configurable.java @@ -91,9 +91,9 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; 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 JVM_DEFAULT = "JVM default"; + static final String NULL = "null"; + static final String DEFAULT = "default"; + static final String JVM_DEFAULT = "JVM default"; /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.23 */ public static final String LOCALE_KEY_SNAKE_CASE = "locale"; @@ -361,8 +361,8 @@ public class Configurable { protected Configurable(Version incompatibleImprovements) { _CoreAPI.checkVersionNotNullAndSupported(incompatibleImprovements); parent = null; - locale = Locale.getDefault(); - timeZone = TimeZone.getDefault(); + locale = Configuration.getDefaultLocale(); + timeZone = Configuration.getDefaultTimeZone(); sqlDataAndTimeTimeZone = null; numberFormat = "number"; timeFormat = ""; @@ -1769,7 +1769,8 @@ public class Configurable { *
    *
  • {@code "locale"}: * See {@link #setLocale(Locale)}. - *
    String value: local codes with the usual format in Java, such as {@code "en_US"}. + *
    String value: local codes with the usual format in Java, such as {@code "en_US"}, or + * "JVM default" (ignoring case) to use the default locale of the Java environment. * *

  • {@code "custom_number_formats"}: See {@link #setCustomNumberFormats(Map)}. *
    String value: Interpreted as an object builder expression. @@ -1943,7 +1944,8 @@ public class Configurable { * {@code "disable"} for {@link Configuration#DISABLE_AUTO_ESCAPING_POLICY}. * *

  • {@code "default_encoding"}: - * See {@link Configuration#setDefaultEncoding(String)}. + * See {@link Configuration#setDefaultEncoding(String)}; since 2.3.26 also accepts value "JVM default" + * (not case sensitive) to set the Java environment default value. *
    As the default value is the system default, which can change * from one server to another, you should always set this! * @@ -2136,7 +2138,11 @@ public class Configurable { boolean unknown = false; try { if (LOCALE_KEY.equals(name)) { - setLocale(_StringUtil.deduceLocale(value)); + if (JVM_DEFAULT.equalsIgnoreCase(value)) { + setLocale(Locale.getDefault()); + } else { + setLocale(_StringUtil.deduceLocale(value)); + } } else if (NUMBER_FORMAT_KEY_SNAKE_CASE.equals(name) || NUMBER_FORMAT_KEY_CAMEL_CASE.equals(name)) { setNumberFormat(value); } else if (CUSTOM_NUMBER_FORMATS_KEY_SNAKE_CASE.equals(name) http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/755b25a3/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 4bf2eae..73e85f1 100644 --- a/src/main/java/org/apache/freemarker/core/Configuration.java +++ b/src/main/java/org/apache/freemarker/core/Configuration.java @@ -354,9 +354,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf /** The default of {@link #getIncompatibleImprovements()}, currently {@link #VERSION_3_0_0}. */ public static final Version DEFAULT_INCOMPATIBLE_IMPROVEMENTS = Configuration.VERSION_3_0_0; - private static final String NULL = "null"; - private static final String DEFAULT = "default"; - private static final Version VERSION; static { try { @@ -418,7 +415,10 @@ public class Configuration extends Configurable implements Cloneable, ParserConf private boolean objectWrapperExplicitlySet; private boolean templateExceptionHandlerExplicitlySet; private boolean logTemplateExceptionsExplicitlySet; - + private boolean localeExplicitlySet; + private boolean defaultEncodingExplicitlySet; + private boolean timeZoneExplicitlySet; + private HashMap/**/ sharedVariables = new HashMap(); /** @@ -428,7 +428,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf */ private HashMap rewrappableSharedVariables = null; - private String defaultEncoding = _SecurityUtil.getSystemProperty("file.encoding", "utf-8"); + private String defaultEncoding = getDefaultDefaultEncoding(); private ConcurrentMap localeToCharsetMap = new ConcurrentHashMap(); /** @@ -491,11 +491,6 @@ public class Configuration extends Configurable implements Cloneable, ParserConf loadBuiltInSharedVariables(); } - @Override - public void setTimeZone(TimeZone timeZone) { - super.setTimeZone(timeZone); - } - private void createTemplateResolver() { templateResolver = new DefaultTemplateResolver( null, @@ -1123,7 +1118,71 @@ public class Configuration extends Configurable implements Cloneable, ParserConf public boolean isObjectWrapperExplicitlySet() { return objectWrapperExplicitlySet; } - + + @Override + public void setLocale(Locale locale) { + super.setLocale(locale); + localeExplicitlySet = true; + } + + /** + * Resets the setting to its default, as if it was never set. + * + * @since 2.3.26 + */ + public void unsetLocale() { + if (localeExplicitlySet) { + setLocale(getDefaultLocale()); + localeExplicitlySet = false; + } + } + + /** + * Tells if {@link #setLocale(Locale)} (or equivalent) was already called on this instance, or it just holds the + * default value. + * + * @since 2.3.26 + */ + public boolean isLocaleExplicitlySet() { + return localeExplicitlySet; + } + + static Locale getDefaultLocale() { + return Locale.getDefault(); + } + + @Override + public void setTimeZone(TimeZone timeZone) { + super.setTimeZone(timeZone); + timeZoneExplicitlySet = true; + } + + /** + * Resets the setting to its default, as if it was never set. + * + * @since 2.3.26 + */ + public void unsetTimeZone() { + if (timeZoneExplicitlySet) { + setTimeZone(getDefaultTimeZone()); + timeZoneExplicitlySet = false; + } + } + + /** + * Tells if {@link #setTimeZone(TimeZone)} (or equivalent) was already called on this instance, or it just holds the + * default value. + * + * @since 2.3.26 + */ + public boolean isTimeZoneExplicitlySet() { + return timeZoneExplicitlySet; + } + + static TimeZone getDefaultTimeZone() { + return TimeZone.getDefault(); + } + @Override public void setTemplateExceptionHandler(TemplateExceptionHandler templateExceptionHandler) { super.setTemplateExceptionHandler(templateExceptionHandler); @@ -2056,6 +2115,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf */ public void setDefaultEncoding(String encoding) { defaultEncoding = encoding; + defaultEncodingExplicitlySet = true; } /** @@ -2068,6 +2128,36 @@ public class Configuration extends Configurable implements Cloneable, ParserConf } /** + * Resets the setting to its default, as if it was never set. + * + * @since 2.3.26 + */ + public void unsetDefaultEncoding() { + if (defaultEncodingExplicitlySet) { + setDefaultEncoding(getDefaultDefaultEncoding()); + defaultEncodingExplicitlySet = false; + } + } + + /** + * Tells if {@link #setDefaultEncoding(String)} (or equivalent) was already called on this instance, or it just holds the + * default value. + * + * @since 2.3.26 + */ + public boolean isDefaultEncodingExplicitlySet() { + return defaultEncodingExplicitlySet; + } + + static private String getDefaultDefaultEncoding() { + return getJVMDefaultEncoding(); + } + + static private String getJVMDefaultEncoding() { + return _SecurityUtil.getSystemProperty("file.encoding", "utf-8"); + } + + /** * Gets the preferred character encoding for the given locale, or the * default encoding if no encoding is set explicitly for the specified * locale. You can associate encodings with locales using @@ -2366,7 +2456,11 @@ public class Configuration extends Configurable implements Cloneable, ParserConf } if (DEFAULT_ENCODING_KEY_SNAKE_CASE.equals(name) || DEFAULT_ENCODING_KEY_CAMEL_CASE.equals(name)) { - setDefaultEncoding(value); + if (JVM_DEFAULT.equalsIgnoreCase(value)) { + setDefaultEncoding(getJVMDefaultEncoding()); + } else { + setDefaultEncoding(value); + } } else if (LOCALIZED_LOOKUP_KEY_SNAKE_CASE.equals(name) || LOCALIZED_LOOKUP_KEY_CAMEL_CASE.equals(name)) { setLocalizedLookup(_StringUtil.getYesNo(value)); } else if (WHITESPACE_STRIPPING_KEY_SNAKE_CASE.equals(name) http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/755b25a3/src/test/java/org/apache/freemarker/core/ConfigurationTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java index c1650ec..0ad4773 100644 --- a/src/test/java/org/apache/freemarker/core/ConfigurationTest.java +++ b/src/test/java/org/apache/freemarker/core/ConfigurationTest.java @@ -1460,7 +1460,70 @@ public class ConfigurationTest extends TestCase { assertNull(cfg.getLazyAutoImports()); assertTrue(cfg.isLazyAutoImportsSet()); } - + + public void testLocaleSetting() throws TemplateException, ConfigurationException { + Configuration cfg = new Configuration(Configuration.VERSION_3_0_0); + + assertEquals(Locale.getDefault(), cfg.getLocale()); + assertFalse(cfg.isLocaleExplicitlySet()); + + Locale nonDefault = Locale.getDefault().equals(Locale.GERMANY) ? Locale.FRANCE : Locale.GERMANY; + cfg.setLocale(nonDefault); + assertTrue(cfg.isLocaleExplicitlySet()); + assertEquals(nonDefault, cfg.getLocale()); + + cfg.unsetLocale(); + assertEquals(Locale.getDefault(), cfg.getLocale()); + assertFalse(cfg.isLocaleExplicitlySet()); + + cfg.setSetting(Configuration.LOCALE_KEY, "JVM default"); + assertEquals(Locale.getDefault(), cfg.getLocale()); + assertTrue(cfg.isLocaleExplicitlySet()); + } + + public void testDefaultEncodingSetting() throws TemplateException, ConfigurationException { + Configuration cfg = new Configuration(Configuration.VERSION_3_0_0); + + String defaultFileEncoding = System.getProperty("file.encoding"); + assertNotNull(defaultFileEncoding); + + assertEquals(defaultFileEncoding, cfg.getDefaultEncoding()); + assertFalse(cfg.isDefaultEncodingExplicitlySet()); + + String nonDefault = defaultFileEncoding.equalsIgnoreCase("UTF-8") ? "ISO-8859-1" : "UTF-8"; + cfg.setDefaultEncoding(nonDefault); + assertTrue(cfg.isDefaultEncodingExplicitlySet()); + assertEquals(nonDefault, cfg.getDefaultEncoding()); + + cfg.unsetDefaultEncoding(); + assertEquals(defaultFileEncoding, cfg.getDefaultEncoding()); + assertFalse(cfg.isDefaultEncodingExplicitlySet()); + + cfg.setSetting(Configuration.DEFAULT_ENCODING_KEY, "JVM default"); + assertEquals(defaultFileEncoding, cfg.getDefaultEncoding()); + assertTrue(cfg.isDefaultEncodingExplicitlySet()); + } + + public void testTimeZoneSetting() throws TemplateException, ConfigurationException { + Configuration cfg = new Configuration(Configuration.VERSION_3_0_0); + + assertEquals(TimeZone.getDefault(), cfg.getTimeZone()); + assertFalse(cfg.isTimeZoneExplicitlySet()); + + TimeZone nonDefault = TimeZone.getDefault().equals(_DateUtil.UTC) ? TimeZone.getTimeZone("PST") : _DateUtil.UTC; + cfg.setTimeZone(nonDefault); + assertTrue(cfg.isTimeZoneExplicitlySet()); + assertEquals(nonDefault, cfg.getTimeZone()); + + cfg.unsetTimeZone(); + assertEquals(TimeZone.getDefault(), cfg.getTimeZone()); + assertFalse(cfg.isTimeZoneExplicitlySet()); + + cfg.setSetting(Configuration.TIME_ZONE_KEY, "JVM default"); + assertEquals(TimeZone.getDefault(), cfg.getTimeZone()); + assertTrue(cfg.isTimeZoneExplicitlySet()); + } + @Test public void testGetSettingNamesAreSorted() throws Exception { Configuration cfg = new Configuration(Configuration.VERSION_3_0_0); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/755b25a3/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java b/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java index 9ade361..aae82f6 100644 --- a/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java +++ b/src/test/java/org/apache/freemarker/core/SQLTimeZoneTest.java @@ -133,6 +133,7 @@ public class SQLTimeZoneTest extends TemplateTest { TimeZone.setDefault(GMT_P02); try { Configuration cfg = getConfiguration(); + cfg.unsetTimeZone(); assertNull(cfg.getSQLDateAndTimeTimeZone()); assertEquals(TimeZone.getDefault(), cfg.getTimeZone()); @@ -148,6 +149,7 @@ public class SQLTimeZoneTest extends TemplateTest { TimeZone.setDefault(GMT_P02); try { Configuration cfg = getConfiguration(); + cfg.unsetTimeZone(); cfg.setSQLDateAndTimeTimeZone(GMT_P02); assertOutput(FTL, OUTPUT_BEFORE_SETTING_GMT_CFG_GMT2 + OUTPUT_AFTER_SETTING_GMT_CFG_SQL_DIFFERENT); http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/755b25a3/src/test/java/org/apache/freemarker/test/TemplateTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/test/TemplateTest.java b/src/test/java/org/apache/freemarker/test/TemplateTest.java index 769ea16..d2eeb72 100644 --- a/src/test/java/org/apache/freemarker/test/TemplateTest.java +++ b/src/test/java/org/apache/freemarker/test/TemplateTest.java @@ -28,7 +28,9 @@ import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; +import java.util.Locale; import java.util.Map; +import java.util.TimeZone; import org.apache.commons.io.IOUtils; import org.apache.freemarker.core.Configuration; @@ -60,6 +62,7 @@ public abstract class TemplateTest { try { configuration = createConfiguration(); addCommonTemplates(); + applyEnvironmentIndependentDefaults(); } catch (Exception e) { throw new RuntimeException("Failed to set up configuration for the test", e); } @@ -67,6 +70,21 @@ public abstract class TemplateTest { return configuration; } + /** + * Ensure that the configuration settings don't depend on the machine that runs the test. + */ + private void applyEnvironmentIndependentDefaults() { + if (!configuration.isLocaleExplicitlySet()) { + configuration.setLocale(Locale.US); + } + if (!configuration.isDefaultEncodingExplicitlySet()) { + configuration.setDefaultEncoding(StandardCharsets.UTF_8.name()); + } + if (!configuration.isTimeZoneExplicitlySet()) { + configuration.setTimeZone(TimeZone.getTimeZone("GMT+1")); + } + } + protected final void setConfiguration(Configuration configuration) { this.configuration = configuration; }