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 2015/11/29 12:59:26 UTC

[22/25] incubator-freemarker git commit: FreemarkerServlet ResponseCharacterEncoding init-param doesn't use the "force" prefix anymore, you just specify the charset name as its value.

FreemarkerServlet ResponseCharacterEncoding init-param doesn't use the "force" prefix anymore, you just specify the charset name as its 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/7540a51c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/7540a51c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/7540a51c

Branch: refs/heads/2.3
Commit: 7540a51c13e9b666bea6e8e5065cb1ee1712aee8
Parents: 947428a
Author: ddekany <dd...@apache.org>
Authored: Thu Nov 26 22:36:42 2015 +0100
Committer: ddekany <dd...@apache.org>
Committed: Thu Nov 26 23:44:19 2015 +0100

----------------------------------------------------------------------
 .../ext/servlet/FreemarkerServlet.java          | 81 +++++++++++++-------
 src/manual/book.xml                             | 32 ++++++--
 .../ext/servlet/FreemarkerServletTest.java      | 12 +--
 3 files changed, 85 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7540a51c/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java b/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
index d745010..092dc8e 100644
--- a/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
+++ b/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
@@ -21,6 +21,8 @@ package freemarker.ext.servlet;
 
 import java.io.IOException;
 import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -45,6 +47,7 @@ import freemarker.cache.FileTemplateLoader;
 import freemarker.cache.MultiTemplateLoader;
 import freemarker.cache.TemplateLoader;
 import freemarker.cache.WebappTemplateLoader;
+import freemarker.core.BugException;
 import freemarker.core.Configurable;
 import freemarker.core.Environment;
 import freemarker.core.OutputFormat;
@@ -162,8 +165,7 @@ import freemarker.template.utility.StringUtil;
  * the default of it), the content type may include the charset (as in <tt>"text/html; charset=utf-8"</tt>), in which
  * case that specifies the actual charset of the output. If the the {@value #INIT_PARAM_RESPONSE_CHARACTER_ENCODING}
  * init-param is not set to {@value #INIT_PARAM_VALUE_LEGACY}, then specifying the charset in the
- * {@value #INIT_PARAM_CONTENT_TYPE} init-param is not allowed, and will cause servlet initialization error.
- * </li>
+ * {@value #INIT_PARAM_CONTENT_TYPE} init-param is not allowed, and will cause servlet initialization error.</li>
  *
  * <li><strong>{@value #INIT_PARAM_OVERRIDE_RESPONSE_CONTENT_TYPE}</strong> (since 2.3.24): Specifies when we should
  * override the {@code contentType} that might be already set (i.e., non-{@code null}) in the
@@ -185,7 +187,7 @@ import freemarker.template.utility.StringUtil;
  * 
  * <li><strong>{@value #INIT_PARAM_RESPONSE_CHARACTER_ENCODING}</strong> (since 2.3.24): Specifies how the
  * {@link HttpServletResponse} "character encoding" (as in {@link HttpServletResponse#setCharacterEncoding(String)})
- * will deduced. The possible modes are:
+ * will be deduced. The possible modes are:
  * <ul>
  * <li>{@value #INIT_PARAM_VALUE_LEGACY}: This is the default for backward compatibility; in new applications, use
  * {@value #INIT_PARAM_VALUE_FROM_TEMPLATE} (or some of the other options) instead. {@value #INIT_PARAM_VALUE_LEGACY}
@@ -195,8 +197,8 @@ import freemarker.template.utility.StringUtil;
  * or writes it (though very few applications utilize that setting anyway). Also, it sets the charset of the servlet
  * response by adding it to the response content type via calling {@link HttpServletResponse#setContentType(String)} (as
  * that was the only way before Servlet 2.4), not via the more modern
- * {@link HttpServletResponse#setCharacterEncoding(String)} method. Note that the charset of a template usually
- * comes from {@link Configuration#getDefaultEncoding()} (i.e., from the {@code default_encoding} FreeMarker setting),
+ * {@link HttpServletResponse#setCharacterEncoding(String)} method. Note that the charset of a template usually comes
+ * from {@link Configuration#getDefaultEncoding()} (i.e., from the {@code default_encoding} FreeMarker setting),
  * occasionally from {@link Configuration#getEncoding(Locale)} (when FreeMarker was configured to use different charsets
  * depending on the locale) or even more rarely from {@link Configuration#getTemplateConfigurers()} (when FreeMarker was
  * configured to use a specific charset for certain templates).
@@ -205,16 +207,16 @@ import freemarker.template.utility.StringUtil;
  * template usually just inherits that from the {@link Configuration}), and if that's not set, then reads the source
  * charset of the template, just like {@value #INIT_PARAM_VALUE_LEGACY}. Then it passes the charset acquired this way to
  * {@link HttpServletResponse#setCharacterEncoding(String)} and {@link Environment#setOutputEncoding(String)}. (It
- * doesn't call the legacy {@link HttpServletResponse#setContentType(String)} API to set the charset.) (Note that if
- * the template has a {@code content_type} template attribute (which is deprecated) that specifies a charset, it will be
- * considered as the output charset of that template.)
+ * doesn't call the legacy {@link HttpServletResponse#setContentType(String)} API to set the charset.) (Note that if the
+ * template has a {@code content_type} template attribute (which is deprecated) that specifies a charset, it will be
+ * used as the output charset of that template.)
  * <li>{@value #INIT_PARAM_VALUE_DO_NOT_SET}: {@link FreemarkerServlet} will not set the {@link HttpServletResponse}
  * "character encoding". It will still call {@link Environment#setOutputEncoding(String)}, so that the running template
  * will be aware of the charset used for the output.
- * <li>{@value #INIT_PARAM_VALUE_FORCE_PREFIX} + charset name, for example {@code force UTF-8}: The output charset will
- * be the one specified after "force" + space, regardless of everything. The charset specified this way is passed to
- * {@link HttpServletResponse#setCharacterEncoding(String)} and {@link Environment#setOutputEncoding(String)}. If the
- * charset name is not recognized by Java, the servlet initialization will fail.
+ * <li>A charset name, for example {@code UTF-8}: The output charset will the specified charset, regardless of
+ * everything. The charset specified this way is passed to {@link HttpServletResponse#setCharacterEncoding(String)} and
+ * {@link Environment#setOutputEncoding(String)}. If the charset name is not recognized by Java, the servlet
+ * initialization will fail.
  * </ul>
  *
  * <li><strong>{@value #INIT_PARAM_BUFFER_SIZE}</strong>: Sets the size of the output buffer in bytes, or if "KB" or
@@ -417,7 +419,6 @@ public class FreemarkerServlet extends HttpServlet {
     public static final String INIT_PARAM_VALUE_FROM_TEMPLATE = "fromTemplate";
     public static final String INIT_PARAM_VALUE_LEGACY = "legacy";
     public static final String INIT_PARAM_VALUE_DO_NOT_SET = "doNotSet";
-    public static final String INIT_PARAM_VALUE_FORCE_PREFIX = "force ";
 
     /**
      * When set, the items defined in it will be added after those coming from the
@@ -668,9 +669,20 @@ public class FreemarkerServlet extends HttpServlet {
                     overrideResponseContentType = initParamValueToEnum(value, OverrideResponseContentType.values());
                 } else if (name.equals(INIT_PARAM_RESPONSE_CHARACTER_ENCODING)) {
                     responseCharacterEncoding = initParamValueToEnum(value, ResponseCharacterEncoding.values());
-                    if (responseCharacterEncoding == ResponseCharacterEncoding.FORCE_CHARSET) {
-                        String charsetName = value.substring(INIT_PARAM_VALUE_FORCE_PREFIX.length()).trim();
-                        forcedResponseCharacterEncoding = Charset.forName(charsetName);
+                    if (responseCharacterEncoding == ResponseCharacterEncoding.SPECIFIC_CHARSET) {
+                        try {
+                            forcedResponseCharacterEncoding = Charset.forName(value);
+                        } catch (IllegalArgumentException e) {
+                            if (!(e instanceof UnsupportedCharsetException
+                                    || e instanceof IllegalCharsetNameException)) {
+                                throw e;
+                            }
+                            StringBuilder sb = new StringBuilder();
+                            sb.append(StringUtil.jQuote(value));
+                            sb.append(" isn't a valid charset name, nor it is any of the predefined values: ");
+                            appendEnumInitParamValues(sb, ResponseCharacterEncoding.values());
+                            throw new IllegalArgumentException(sb.toString());
+                        }
                     }
                 } else if (name.equals(INIT_PARAM_OVERRIDE_RESPONSE_LOCALE)) {
                     overrideResponseLocale = initParamValueToEnum(value, OverrideResponseLocale.values());
@@ -846,7 +858,7 @@ public class FreemarkerServlet extends HttpServlet {
         if (responseCharacterEncoding != ResponseCharacterEncoding.LEGACY
                 && responseCharacterEncoding != ResponseCharacterEncoding.DO_NOT_SET) {
             // Using the Servlet 2.4 way of setting character encoding.
-            if (responseCharacterEncoding != ResponseCharacterEncoding.FORCE_CHARSET) {
+            if (responseCharacterEncoding != ResponseCharacterEncoding.SPECIFIC_CHARSET) {
                 if (!tempSpecContentTypeContainsCharset) {
                     response.setCharacterEncoding(getTemplateSpecificOutputEncoding(template));
                 }
@@ -1589,28 +1601,42 @@ public class FreemarkerServlet extends HttpServlet {
     }
     
     private <T extends InitParamValueEnum> T initParamValueToEnum(String initParamValue, T[] enumValues) {
+        T wildcardEnumValue = null;
         for (T enumValue : enumValues) {
             String enumInitParamValue = enumValue.getInitParamValue();
-            if (initParamValue.equals(enumInitParamValue)
-                    || enumInitParamValue.endsWith("}") && initParamValue.startsWith(
-                            enumInitParamValue.substring(0, enumInitParamValue.indexOf("${")))) {
+            if (enumInitParamValue == null) {
+                if (wildcardEnumValue != null) {
+                    throw new BugException();
+                }
+                wildcardEnumValue = enumValue;
+            } else if (initParamValue.equals(enumInitParamValue)) {
                 return enumValue;
             }
         }
+        if (wildcardEnumValue != null) {
+            return wildcardEnumValue;
+        }
         
         StringBuilder sb = new StringBuilder();
         sb.append(StringUtil.jQuote(initParamValue));
         sb.append(" is not a one of the enumeration values: ");
+        appendEnumInitParamValues(sb, enumValues);
+        throw new IllegalArgumentException(sb.toString());
+    }
+
+    protected <T extends InitParamValueEnum> void appendEnumInitParamValues(StringBuilder sb, T[] enumValues) {
         boolean first = true;
         for (T value : enumValues) {
-            if (!first) {
-                sb.append(", ");
-            } else {
-                first = false;
+            String initParamValue = value.getInitParamValue();
+            if (initParamValue != null) {  // Not a wildcard enum
+                if (!first) {
+                    sb.append(", ");
+                } else {
+                    first = false;
+                }
+                sb.append(StringUtil.jQuote(initParamValue));
             }
-            sb.append(StringUtil.jQuote(value.getInitParamValue()));
         }
-        throw new IllegalArgumentException(sb.toString());
     }
 
     /**
@@ -1643,7 +1669,7 @@ public class FreemarkerServlet extends HttpServlet {
         LEGACY(INIT_PARAM_VALUE_LEGACY),
         FROM_TEMPLATE(INIT_PARAM_VALUE_FROM_TEMPLATE),
         DO_NOT_SET(INIT_PARAM_VALUE_DO_NOT_SET),
-        FORCE_CHARSET(INIT_PARAM_VALUE_FORCE_PREFIX + "${charsetName}");
+        SPECIFIC_CHARSET(null);
 
         private final String initParamValue;
         
@@ -1655,7 +1681,6 @@ public class FreemarkerServlet extends HttpServlet {
         public String getInitParamValue() {
             return initParamValue;
         }
-        
     }
 
     private enum OverrideResponseLocale implements InitParamValueEnum {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7540a51c/src/manual/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/book.xml b/src/manual/book.xml
index c6f8033..1654417 100644
--- a/src/manual/book.xml
+++ b/src/manual/book.xml
@@ -10427,7 +10427,11 @@ TemplateHashModel roundingModeEnums =
   &lt;/init-param&gt;
   &lt;init-param&gt;
     &lt;param-name&gt;ContentType&lt;/param-name&gt;
-    &lt;param-value&gt;text/html; charset=UTF-8&lt;/param-value&gt; &lt;!-- Forces UTF-8 output encoding! --&gt;
+    &lt;param-value&gt;text/html&lt;/param-value&gt;
+  &lt;/init-param&gt;
+  &lt;init-param&gt;
+    &lt;param-name&gt;ResponseCharacterEncoding&lt;/param-name&gt;
+    &lt;param-value&gt;UTF-8&lt;/param-value&gt;
   &lt;/init-param&gt;
     
   &lt;!-- FreeMarker settings: --&gt;
@@ -26080,9 +26084,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   the <literal>outputEncoding</literal> setting),
                   <literal>doNotSet</literal> (keeps what the caller has
                   already set in the <literal>ServletRespone</literal>) and
-                  <literal>force
-                  <replaceable>charsetName</replaceable></literal> (forces a
-                  specific charset).</para>
+                  any valid charset name (forces a specific output
+                  charset).</para>
                 </listitem>
               </itemizedlist>
             </listitem>
@@ -26420,7 +26423,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
               <itemizedlist>
                 <listitem>
-                  <para><literal>OverrideResponseContentType</literal>.
+                  <para><literal>OverrideResponseContentType</literal>:
                   Specifies when should we override the
                   <literal>contentType</literal> that's already set (i.e.,
                   non-<literal>null</literal>) in the
@@ -26433,13 +26436,30 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 </listitem>
 
                 <listitem>
-                  <para><literal>OverrideResponseLocale</literal>. Specifies
+                  <para><literal>OverrideResponseLocale</literal>: Specifies
                   if should we override the <literal>contentType</literal>
                   that's already set (i.e., non-<literal>null</literal>) in
                   the <literal>HttpServletResponse</literal>. Earlier, we have
                   always set it, but now this behavior can be changed so that
                   we only set it if it wasn't already set.</para>
                 </listitem>
+
+                <listitem>
+                  <para><literal>ResponseCharacterEncoding</literal>:
+                  Deprecates the old (and quirky) logic of specifying the
+                  output charset, which was putting it into the
+                  <literal>ContentType</literal> init-param after the MIME
+                  type, otherwise falling back to using the template file
+                  charset. The possible values are <literal>legacy</literal>
+                  (the default for backward compatibility),
+                  <literal>fromTemplate</literal> (which is
+                  <literal>legacy</literal> without quirks, and is aware of
+                  the <literal>outputEncoding</literal> setting),
+                  <literal>doNotSet</literal> (keeps what the caller has
+                  already set in the <literal>ServletRespone</literal>) and
+                  any valid charset name (forces a specific output
+                  charset).</para>
+                </listitem>
               </itemizedlist>
             </listitem>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/7540a51c/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
index f008280..6e5ce09 100644
--- a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
+++ b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java
@@ -310,23 +310,23 @@ public class FreemarkerServletTest {
         assertOutputEncodingEquals(
                 "UTF-16LE", // <- expected response.characterEncoding
                 "UTF-16LE", // <- expected env.outputEncoding
-                FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
+                "UTF-16LE", // <- init-param
                 FOO_FTL);
         assertOutputEncodingEquals(
                 "UTF-16LE", // <- expected response.characterEncoding
                 "UTF-16LE", // <- expected env.outputEncoding
-                FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
+                "UTF-16LE", // <- init-param
                 FOO_SRC_UTF8_FTL);
         assertOutputEncodingEquals(
                 "UTF-16LE", // <- expected response.characterEncoding
                 "UTF-16LE", // <- expected env.outputEncoding
-                FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
+                "UTF-16LE", // <- init-param
                 FOO_OUT_UTF8_FTL);
         try {
             assertOutputEncodingEquals(
                     null, // <- expected response.characterEncoding
                     null, // <- expected env.outputEncoding
-                    FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "noSuchCharset", // <- init-param
+                    "noSuchCharset", // <- init-param
                     FOO_FTL);
             fail();
         } catch (ServletException e) {
@@ -337,7 +337,7 @@ public class FreemarkerServletTest {
             assertOutputEncodingEquals(
                     "UTF-16LE", // <- expected response.characterEncoding
                     "UTF-16LE", // <- expected env.outputEncoding
-                    FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
+                    "UTF-16LE", // <- init-param
                     "text/html; charset=ISO-8859-2", // ContentType init-param
                     FOO_FTL);
             fail();
@@ -348,7 +348,7 @@ public class FreemarkerServletTest {
         assertOutputEncodingEquals(
                 "UTF-16LE", // <- expected response.characterEncoding
                 "UTF-16LE", // <- expected env.outputEncoding
-                FreemarkerServlet.INIT_PARAM_VALUE_FORCE_PREFIX + "UTF-16LE", // <- init-param
+                "UTF-16LE", // <- init-param
                 CONTENT_TYPE_ATTR_WITH_CHARSET_FTL);
     }