freemarker-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ddek...@apache.org
Subject [03/10] incubator-freemarker git commit: 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 mi
Date Wed, 15 Mar 2017 12:31:45 GMT
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.


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

Branch: refs/heads/2.3
Commit: 0fa4299657306fba0e18d732b122e1ca09d7b54e
Parents: 738cef8
Author: ddekany <ddekany@apache.org>
Authored: Tue Mar 14 20:13:25 2017 +0100
Committer: ddekany <ddekany@apache.org>
Committed: Tue Mar 14 20:13:25 2017 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/Configurable.java |  16 ++-
 .../java/freemarker/template/Configuration.java | 109 ++++++++++++++++++-
 .../java/freemarker/template/_TemplateAPI.java  |  10 ++
 src/manual/en_US/book.xml                       |  29 ++++-
 .../freemarker/template/ConfigurationTest.java  |  63 +++++++++++
 5 files changed, 218 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0fa42996/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index 76a3922..1563a4e 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -388,10 +388,10 @@ public class Configurable {
         parent = null;
         properties = new Properties();
         
-        locale = Locale.getDefault();
+        locale = _TemplateAPI.getDefaultLocale();
         properties.setProperty(LOCALE_KEY, locale.toString());
         
-        timeZone = TimeZone.getDefault();
+        timeZone = _TemplateAPI.getDefaultTimeZone();
         properties.setProperty(TIME_ZONE_KEY, timeZone.getID());
         
         sqlDataAndTimeTimeZone = null;
@@ -1992,7 +1992,8 @@ public class Configurable {
      * <ul>
      *   <li><p>{@code "locale"}:
      *       See {@link #setLocale(Locale)}.
-     *       <br>String value: local codes with the usual format in Java, such as {@code
"en_US"}.
+     *       <br>String value: local codes with the usual format in Java, such as {@code
"en_US"}, or since 2.3.26,
+     *       "JVM default" (ignoring case) to use the default locale of the Java environment.
      *       
      *   <li><p>{@code "classic_compatible"}:
      *       See {@link #setClassicCompatible(boolean)} and {@link Configurable#setClassicCompatibleAsInt(int)}.
@@ -2179,7 +2180,8 @@ public class Configurable {
      *       {@code "disable"} for {@link Configuration#DISABLE_AUTO_ESCAPING_POLICY}.
      *       
      *   <li><p>{@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.
      *       <br>As the default value is the system default, which can change
      *       from one server to another, <b>you should always set this!</b>
      *       
@@ -2385,7 +2387,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/0fa42996/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index a34c605..ca5ee72 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -38,6 +38,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
+import java.util.TimeZone;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -424,6 +425,7 @@ public class Configuration extends Configurable implements Cloneable,
ParserConf
     
     private static final String NULL = "null";
     private static final String DEFAULT = "default";
+    private static final String JVM_DEFAULT = "JVM default";
     
     private static final Version VERSION;
     static {
@@ -509,6 +511,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/*<String, TemplateModel>*/ sharedVariables = new HashMap();
 
@@ -519,7 +525,7 @@ public class Configuration extends Configurable implements Cloneable,
ParserConf
      */
     private HashMap/*<String, Object>*/ rewrappableSharedVariables = null;
     
-    private String defaultEncoding = SecurityUtilities.getSystemProperty("file.encoding",
"utf-8");
+    private String defaultEncoding = getDefaultDefaultEncoding();
     private ConcurrentMap localeToCharsetMap = new ConcurrentHashMap();
     
     /**
@@ -1606,6 +1612,70 @@ public class Configuration extends Configurable implements Cloneable,
ParserConf
     }
     
     @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);
         templateExceptionHandlerExplicitlySet = true;
@@ -2534,6 +2604,7 @@ public class Configuration extends Configurable implements Cloneable,
ParserConf
      */
     public void setDefaultEncoding(String encoding) {
         defaultEncoding = encoding;
+        defaultEncodingExplicitlySet = true;
     }
 
     /**
@@ -2544,7 +2615,37 @@ public class Configuration extends Configurable implements Cloneable,
ParserConf
     public String getDefaultEncoding() {
         return defaultEncoding;
     }
+    
+    /**
+     * 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 SecurityUtilities.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
@@ -2845,7 +2946,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 (STRICT_SYNTAX_KEY_SNAKE_CASE.equals(name) || STRICT_SYNTAX_KEY_CAMEL_CASE.equals(name))
{

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0fa42996/src/main/java/freemarker/template/_TemplateAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/_TemplateAPI.java b/src/main/java/freemarker/template/_TemplateAPI.java
index 15d5e23..737c528 100644
--- a/src/main/java/freemarker/template/_TemplateAPI.java
+++ b/src/main/java/freemarker/template/_TemplateAPI.java
@@ -19,7 +19,9 @@
 
 package freemarker.template;
 
+import java.util.Locale;
 import java.util.Set;
+import java.util.TimeZone;
 
 import freemarker.cache.CacheStorage;
 import freemarker.cache.TemplateLoader;
@@ -150,4 +152,12 @@ public class _TemplateAPI {
         return e.getBlamedExpression();
     }
     
+    public static Locale getDefaultLocale() {
+        return Configuration.getDefaultLocale();
+    }
+    
+    public static TimeZone getDefaultTimeZone() {
+        return Configuration.getDefaultTimeZone();
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0fa42996/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 7ba4089..5673870 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26862,8 +26862,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <literal>Configuration</literal> on its default, it's enough to
               increase the <literal>incompatibleImprovements</literal> setting
               of the <literal>Configuration</literal> to 2.3.26, as that's
-              inherited by the default <literal>object_wrapper</literal>.
-              </para>
+              inherited by the default
+              <literal>object_wrapper</literal>.</para>
             </listitem>
 
             <listitem>
@@ -26895,6 +26895,31 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Added
+              <literal>Configuration.is<replaceable>Xxx</replaceable>ExplictlySet</literal>
+              and
+              <literal>Configuration.unset<replaceable>Xxx</replaceable></literal>
+              methods for the Configuration settings:
+              <literal>locale</literal>, <literal>time_zone</literal>,
+              <literal>default_encoding</literal>. (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.)</para>
+            </listitem>
+
+            <listitem>
+              <para>The <literal>locale</literal> and
+              <literal>default_encoding</literal> configuration settings now
+              supports the special <literal>"JVM default"</literal> value when
+              set from Java <literal>.properties</literal> file, or via
+              <literal>Configuration.setSettings(Properties)</literal>, or via
+              the <literal>#setting</literal> directive. Earlier only the
+              <literal>time_zone</literal> setting has supported this
+              value.</para>
+            </listitem>
+
+            <listitem>
               <para>Bug fixed: If <link
               linkend="pgui_config_incompatible_improvements_how_to_set">the
               <literal>incompatible_improvements</literal> setting</link>
is

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0fa42996/src/test/java/freemarker/template/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index a4dbfcc..15ba915 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -1615,6 +1615,69 @@ public class ConfigurationTest extends TestCase {
         assertTrue(cfg.isLazyAutoImportsSet());
     }
     
+    public void testLocaleSetting() throws TemplateException {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_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 {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_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 {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_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_2_3_22);


Mime
View raw message