Search in sources :

Example 1 with SimpleObjectWrapper

use of freemarker.template.SimpleObjectWrapper in project freemarker by apache.

the class Configurable method setSetting.

/**
 * Sets a FreeMarker setting by a name and string value. If you can configure FreeMarker directly with Java (or
 * other programming language), you should use the dedicated setter methods instead (like
 * {@link #setObjectWrapper(ObjectWrapper)}. This meant to be used only when you get settings from somewhere
 * as {@link String}-{@link String} name-value pairs (typically, as a {@link Properties} object). Below you find an
 * overview of the settings available.
 *
 * <p>Note: As of FreeMarker 2.3.23, setting names can be written in camel case too. For example, instead of
 * {@code date_format} you can also use {@code dateFormat}. It's likely that camel case will become to the
 * recommended convention in the future.
 *
 * <p>The list of settings commonly supported in all {@link Configurable} subclasses:
 * <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"}, 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)}.
 *       <br>String value: {@code "true"}, {@code "false"}, also since 2.3.20 {@code 0} or {@code 1} or {@code 2}.
 *       (Also accepts {@code "yes"}, {@code "no"}, {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}.)
 *       Case insensitive.
 *
 *   <li><p>{@code "custom_number_formats"}: See {@link #setCustomNumberFormats(Map)}.
 *   <br>String value: Interpreted as an <a href="#fm_obe">object builder expression</a>.
 *   <br>Example: <code>{ "hex": com.example.HexTemplateNumberFormatFactory,
 *   "gps": com.example.GPSTemplateNumberFormatFactory }</code>
 *
 *   <li><p>{@code "custom_date_formats"}: See {@link #setCustomDateFormats(Map)}.
 *   <br>String value: Interpreted as an <a href="#fm_obe">object builder expression</a>.
 *   <br>Example: <code>{ "trade": com.example.TradeTemplateDateFormatFactory,
 *   "log": com.example.LogTemplateDateFormatFactory }</code>
 *
 *   <li><p>{@code "template_exception_handler"}:
 *       See {@link #setTemplateExceptionHandler(TemplateExceptionHandler)}.
 *       <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder
 *       expression</a>.
 *       If the value does not contain dot, then it must be one of these predefined values (case insensitive):
 *       {@code "rethrow"} (means {@link TemplateExceptionHandler#RETHROW_HANDLER}),
 *       {@code "debug"} (means {@link TemplateExceptionHandler#DEBUG_HANDLER}),
 *       {@code "html_debug"} (means {@link TemplateExceptionHandler#HTML_DEBUG_HANDLER}),
 *       {@code "ignore"} (means {@link TemplateExceptionHandler#IGNORE_HANDLER}), or
 *       {@code "default"} (only allowed for {@link Configuration} instances) for the default value.
 *
 *   <li><p>{@code "attempt_exception_reporter"}:
 *       See {@link #setAttemptExceptionReporter(AttemptExceptionReporter)}.
 *       <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder
 *       expression</a>.
 *       If the value does not contain dot, then it must be one of these predefined values (case insensitive):
 *       {@code "log_error"} (means {@link AttemptExceptionReporter#LOG_ERROR_REPORTER}),
 *       {@code "log_warn"} (means {@link AttemptExceptionReporter#LOG_WARN_REPORTER}), or
 *       {@code "default"} (only allowed for {@link Configuration} instances) for the default value.
 *
 *   <li><p>{@code "arithmetic_engine"}:
 *       See {@link #setArithmeticEngine(ArithmeticEngine)}.
 *       <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder
 *       expression</a>.
 *       If the value does not contain dot,
 *       then it must be one of these special values (case insensitive):
 *       {@code "bigdecimal"}, {@code "conservative"}.
 *
 *   <li><p>{@code "object_wrapper"}:
 *       See {@link #setObjectWrapper(ObjectWrapper)}.
 *       <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder
 *       expression</a>, with the addition that {@link BeansWrapper}, {@link DefaultObjectWrapper} and
 *       {@link SimpleObjectWrapper} can be referred without package name. For example, these strings are valid
 *       values: {@code "DefaultObjectWrapper(2.3.21, forceLegacyNonListCollections=false, iterableSupport=true)"},
 *       {@code "BeansWrapper(2.3.21, simpleMapWrapper=true)"}.
 *       <br>If the value does not contain dot, then it must be one of these special values (case insensitive):
 *       {@code "default"} means the default of {@link Configuration} (the default depends on the
 *       {@code Configuration#Configuration(Version) incompatible_improvements}, but a bug existed in 2.3.21 where
 *       that was ignored),
 *       {@code "default_2_3_0"} (means the deprecated {@link ObjectWrapper#DEFAULT_WRAPPER})
 *       {@code "simple"} (means the deprecated {@link ObjectWrapper#SIMPLE_WRAPPER}),
 *       {@code "beans"} (means the deprecated {@link BeansWrapper#BEANS_WRAPPER}
 *       or {@link BeansWrapperBuilder#build()}),
 *       {@code "jython"} (means {@link freemarker.ext.jython.JythonWrapper#DEFAULT_WRAPPER})
 *
 *   <li><p>{@code "number_format"}: See {@link #setNumberFormat(String)}.
 *
 *   <li><p>{@code "boolean_format"}: See {@link #setBooleanFormat(String)} .
 *
 *   <li><p>{@code "date_format", "time_format", "datetime_format"}:
 *       See {@link #setDateFormat(String)}, {@link #setTimeFormat(String)}, {@link #setDateTimeFormat(String)}.
 *
 *   <li><p>{@code "time_zone"}:
 *       See {@link #setTimeZone(TimeZone)}.
 *       <br>String value: With the format as {@link TimeZone#getTimeZone} defines it. Also, since 2.3.21
 *       {@code "JVM default"} can be used that will be replaced with the actual JVM default time zone when
 *       {@link #setSetting(String, String)} is called.
 *       For example {@code "GMT-8:00"} or {@code "America/Los_Angeles"}
 *       <br>If you set this setting, consider setting {@code sql_date_and_time_time_zone}
 *       too (see below)!
 *
 *   <li><p>{@code sql_date_and_time_time_zone}:
 *       See {@link #setSQLDateAndTimeTimeZone(TimeZone)}.
 *       Since 2.3.21.
 *       <br>String value: With the format as {@link TimeZone#getTimeZone} defines it. Also, {@code "JVM default"}
 *       can be used that will be replaced with the actual JVM default time zone when
 *       {@link #setSetting(String, String)} is called. Also {@code "null"} can be used, which has the same effect
 *       as {@link #setSQLDateAndTimeTimeZone(TimeZone) setSQLDateAndTimeTimeZone(null)}.
 *
 *   <li><p>{@code "output_encoding"}:
 *       See {@link #setOutputEncoding(String)}.
 *
 *   <li><p>{@code "url_escaping_charset"}:
 *       See {@link #setURLEscapingCharset(String)}.
 *
 *   <li><p>{@code "auto_flush"}:
 *       See {@link #setAutoFlush(boolean)}.
 *       Since 2.3.17.
 *       <br>String value: {@code "true"}, {@code "false"}, {@code "y"},  etc.
 *
 *   <li><p>{@code "auto_import"}:
 *       See {@link Configuration#setAutoImports(Map)}
 *       <br>String value is something like:
 *       <br>{@code /lib/form.ftl as f, /lib/widget as w, "/lib/odd name.ftl" as odd}
 *
 *   <li><p>{@code "auto_include"}: Sets the list of auto-includes.
 *       See {@link Configuration#setAutoIncludes(List)}
 *       <br>String value is something like:
 *       <br>{@code /include/common.ftl, "/include/evil name.ftl"}
 *
 *   <li><p>{@code "lazy_auto_imports"}:
 *       See {@link Configuration#setLazyAutoImports(Boolean)}.
 *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
 *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive. Also can be {@code "null"}.
 *
 *   <li><p>{@code "lazy_imports"}:
 *       See {@link Configuration#setLazyImports(boolean)}.
 *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
 *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive.
 *
 *   <li><p>{@code "new_builtin_class_resolver"}:
 *       See {@link #setNewBuiltinClassResolver(TemplateClassResolver)}.
 *       Since 2.3.17.
 *       The value must be one of these (ignore the quotation marks):
 *       <ol>
 *         <li><p>{@code "unrestricted"}:
 *             Use {@link TemplateClassResolver#UNRESTRICTED_RESOLVER}
 *         <li><p>{@code "safer"}:
 *             Use {@link TemplateClassResolver#SAFER_RESOLVER}
 *         <li><p>{@code "allows_nothing"} (or {@code "allowsNothing"}):
 *             Use {@link TemplateClassResolver#ALLOWS_NOTHING_RESOLVER}
 *         <li><p>Something that contains colon will use
 *             {@link OptInTemplateClassResolver} and is expected to
 *             store comma separated values (possibly quoted) segmented
 *             with {@code "allowed_classes:"} (or {@code "allowedClasses:"}) and/or
 *             {@code "trusted_templates:"} (or {@code "trustedTemplates:"}). Examples of valid values:
 *
 *             <table style="width: auto; border-collapse: collapse" border="1"
 *                  summary="trusted_template value examples">
 *               <tr>
 *                 <th>Setting value
 *                 <th>Meaning
 *               <tr>
 *                 <td>
 *                   {@code allowed_classes: com.example.C1, com.example.C2,
 *                   trusted_templates: lib/*, safe.ftl}
 *                 <td>
 *                   Only allow instantiating the {@code com.example.C1} and
 *                   {@code com.example.C2} classes. But, allow templates
 *                   within the {@code lib/} directory (like
 *                   {@code lib/foo/bar.ftl}) and template {@code safe.ftl}
 *                   (that does not match {@code foo/safe.ftl}, only
 *                   exactly {@code safe.ftl}) to instantiate anything
 *                   that {@link TemplateClassResolver#SAFER_RESOLVER} allows.
 *               <tr>
 *                 <td>
 *                   {@code allowed_classes: com.example.C1, com.example.C2}
 *                 <td>Only allow instantiating the {@code com.example.C1} and
 *                   {@code com.example.C2} classes. There are no
 *                   trusted templates.
 *               <tr>
 *                 <td>
 *                         {@code trusted_templates: lib/*, safe.ftl}
 *                 <td>
 *                   Do not allow instantiating any classes, except in
 *                   templates inside {@code lib/} or in template
 *                   {@code safe.ftl}.
 *             </table>
 *
 *             <p>For more details see {@link OptInTemplateClassResolver}.
 *
 *         <li><p>Otherwise if the value contains dot, it's interpreted as an <a href="#fm_obe">object builder
 *             expression</a>.
 *       </ol>
 *
 *   <li><p>{@code "show_error_tips"}:
 *       See {@link #setShowErrorTips(boolean)}.
 *       Since 2.3.21.
 *       <br>String value: {@code "true"}, {@code "false"}, {@code "y"},  etc.
 *
 *   <li><p>{@code api_builtin_enabled}:
 *       See {@link #setAPIBuiltinEnabled(boolean)}.
 *       Since 2.3.22.
 *       <br>String value: {@code "true"}, {@code "false"}, {@code "y"},  etc.
 *
 * </ul>
 *
 * <p>{@link Configuration} (a subclass of {@link Configurable}) also understands these:</p>
 * <ul>
 *   <li><p>{@code "auto_escaping"}:
 *       See {@link Configuration#setAutoEscapingPolicy(int)}
 *       <br>String value: {@code "enable_if_default"} or {@code "enableIfDefault"} for
 *       {@link Configuration#ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY},
 *       {@code "enable_if_supported"} or {@code "enableIfSupported"} for
 *       {@link Configuration#ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY}
 *       {@code "disable"} for {@link Configuration#DISABLE_AUTO_ESCAPING_POLICY}.
 *
 *   <li><p>{@code "default_encoding"}:
 *       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>
 *
 *   <li><p>{@code "localized_lookup"}:
 *       See {@link Configuration#setLocalizedLookup}.
 *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
 *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}).
 *       Case insensitive.
 *
 *   <li><p>{@code "output_format"}:
 *       See {@link Configuration#setOutputFormat(OutputFormat)}.
 *       <br>String value: {@code "default"} (case insensitive) for the default, or an
 *       <a href="#fm_obe">object builder expression</a> that gives an {@link OutputFormat}, for example
 *       {@code HTMLOutputFormat} or {@code XMLOutputFormat}.
 *
 *   <li><p>{@code "registered_custom_output_formats"}:
 *       See {@link Configuration#setRegisteredCustomOutputFormats(Collection)}.
 *       <br>String value: an <a href="#fm_obe">object builder expression</a> that gives a {@link List} of
 *       {@link OutputFormat}-s.
 *       Example: {@code [com.example.MyOutputFormat(), com.example.MyOtherOutputFormat()]}
 *
 *   <li><p>{@code "strict_syntax"}:
 *       See {@link Configuration#setStrictSyntaxMode}. Deprecated.
 *       <br>String value: {@code "true"}, {@code "false"}, {@code yes}, etc.
 *
 *   <li><p>{@code "whitespace_stripping"}:
 *       See {@link Configuration#setWhitespaceStripping}.
 *       <br>String value: {@code "true"}, {@code "false"}, {@code yes}, etc.
 *
 *   <li><p>{@code "cache_storage"}:
 *       See {@link Configuration#setCacheStorage}.
 *       <br>String value: If the value contains dot, then it's interpreted as an <a href="#fm_obe">object builder
 *       expression</a>.
 *       If the value does not contain dot,
 *       then a {@link freemarker.cache.MruCacheStorage} will be used with the
 *       maximum strong and soft sizes specified with the setting value. Examples
 *       of valid setting values:
 *
 *       <table style="width: auto; border-collapse: collapse" border="1" summary="cache_storage value examples">
 *         <tr><th>Setting value<th>max. strong size<th>max. soft size
 *         <tr><td>{@code "strong:50, soft:500"}<td>50<td>500
 *         <tr><td>{@code "strong:100, soft"}<td>100<td>{@code Integer.MAX_VALUE}
 *         <tr><td>{@code "strong:100"}<td>100<td>0
 *         <tr><td>{@code "soft:100"}<td>0<td>100
 *         <tr><td>{@code "strong"}<td>{@code Integer.MAX_VALUE}<td>0
 *         <tr><td>{@code "soft"}<td>0<td>{@code Integer.MAX_VALUE}
 *       </table>
 *
 *       <p>The value is not case sensitive. The order of <tt>soft</tt> and <tt>strong</tt>
 *       entries is not significant.
 *
 *   <li><p>{@code "template_update_delay"}:
 *       Template update delay in <b>seconds</b> (not in milliseconds) if no unit is specified; see
 *       {@link Configuration#setTemplateUpdateDelayMilliseconds(long)} for more.
 *       <br>String value: Valid positive integer, optionally followed by a time unit (recommended). The default
 *       unit is seconds. It's strongly recommended to specify the unit for clarity, like in "500 ms" or "30 s".
 *       Supported units are: "s" (seconds), "ms" (milliseconds), "m" (minutes), "h" (hours). The whitespace between
 *       the unit and the number is optional. Units are only supported since 2.3.23.
 *
 *   <li><p>{@code "tag_syntax"}:
 *       See {@link Configuration#setTagSyntax(int)}.
 *       <br>String value: Must be one of
 *       {@code "auto_detect"}, {@code "angle_bracket"}, and {@code "square_bracket"} (like {@code [#if x]}).
 *       <br>Note that setting the {@code "tagSyntax"} to {@code "square_bracket"} does <em>not</em> change
 *       <code>${x}</code> to {@code [=...]}; that's <em>interpolation</em> syntax, so use the
 *       {@code "interpolation_syntax"} setting for that, not this setting.
 *
 *   <li><p>{@code "interpolation_syntax"} (since 2.3.28):
 *       See {@link Configuration#setInterpolationSyntax(int)}.
 *       <br>String value: Must be one of
 *       {@code "legacy"}, {@code "dollar"}, and {@code "square_bracket"} (like {@code [=x]}).
 *       <br>Note that setting the {@code "interpolation_syntax"} to {@code "square_bracket"} does <em>not</em>
 *       change {@code <#if x>} to {@code [#if x]}; that's <em>tag</em> syntax, so use the
 *       {@code "tag_syntax"} setting for that, not this setting.
 *
 *   <li><p>{@code "naming_convention"}:
 *       See {@link Configuration#setNamingConvention(int)}.
 *       <br>String value: Must be one of
 *       {@code "auto_detect"}, {@code "legacy"}, and {@code "camel_case"}.
 *
 *   <li><p>{@code "incompatible_improvements"}:
 *       See {@link Configuration#setIncompatibleImprovements(Version)}.
 *       <br>String value: version number like {@code 2.3.20}.
 *
 *   <li><p>{@code "incompatible_enhancements"}:
 *       See: {@link Configuration#setIncompatibleEnhancements(String)}.
 *       This setting name is deprecated, use {@code "incompatible_improvements"} instead.
 *
 *   <li><p>{@code "recognize_standard_file_extensions"}:
 *       See {@link Configuration#setRecognizeStandardFileExtensions(boolean)}.
 *       <br>String value: {@code "default"} (case insensitive) for the default, or {@code "true"}, {@code "false"},
 *       {@code yes}, etc.
 *
 *   <li><p>{@code "template_configurations"}:
 *       See: {@link Configuration#setTemplateConfigurations(freemarker.cache.TemplateConfigurationFactory)}.
 *       <br>String value: Interpreted as an <a href="#fm_obe">object builder expression</a>,
 *       can be {@code null}.
 *
 *   <li><p>{@code "template_loader"}:
 *       See: {@link Configuration#setTemplateLoader(TemplateLoader)}.
 *       <br>String value: {@code "default"} (case insensitive) for the default, or else interpreted as an
 *       <a href="#fm_obe">object builder expression</a>. {@code "null"} is also allowed since 2.3.26.
 *
 *   <li><p>{@code "template_lookup_strategy"}:
 *       See: {@link Configuration#setTemplateLookupStrategy(freemarker.cache.TemplateLookupStrategy)}.
 *       <br>String value: {@code "default"} (case insensitive) for the default, or else interpreted as an
 *       <a href="#fm_obe">object builder expression</a>.
 *
 *   <li><p>{@code "template_name_format"}:
 *       See: {@link Configuration#setTemplateNameFormat(freemarker.cache.TemplateNameFormat)}.
 *       <br>String value: {@code "default"} (case insensitive) for the default, {@code "default_2_3_0"}
 *       for {@link freemarker.cache.TemplateNameFormat#DEFAULT_2_3_0}, {@code "default_2_4_0"} for
 *       {@link freemarker.cache.TemplateNameFormat#DEFAULT_2_4_0}.
 * </ul>
 *
 * <p><a name="fm_obe"></a>Regarding <em>object builder expressions</em> (used by the setting values where it was
 * indicated):
 * <ul>
 *   <li><p>Before FreeMarker 2.3.21 it had to be a fully qualified class name, and nothing else.</li>
 *   <li><p>Since 2.3.21, the generic syntax is:
 *       <tt><i>className</i>(<i>constrArg1</i>, <i>constrArg2</i>, ... <i>constrArgN</i>,
 *       <i>propName1</i>=<i>propValue1</i>, <i>propName2</i>=<i>propValue2</i>, ...
 *       <i>propNameN</i>=<i>propValueN</i>)</tt>,
 *       where
 *       <tt><i>className</i></tt> is the fully qualified class name of the instance to create (except if we have
 *       builder class or <tt>INSTANCE</tt> field around, but see that later),
 *       <tt><i>constrArg</i></tt>-s are the values of constructor arguments,
 *       and <tt><i>propName</i>=<i>propValue</i></tt>-s set JavaBean properties (like <tt>x=1</tt> means
 *       <tt>setX(1)</tt>) on the created instance. You can have any number of constructor arguments and property
 *       setters, including 0. Constructor arguments must precede any property setters.
 *   </li>
 *   <li>
 *     Example: <tt>com.example.MyObjectWrapper(1, 2, exposeFields=true, cacheSize=5000)</tt> is nearly
 *     equivalent with this Java code:
 *     <tt>obj = new com.example.MyObjectWrapper(1, 2); obj.setExposeFields(true); obj.setCacheSize(5000);</tt>
 *   </li>
 *   <li>
 *      <p>If you have no constructor arguments and property setters, and the <tt><i>className</i></tt> class has
 *      a public static {@code INSTANCE} field, the value of that filed will be the value of the expression, and
 *      the constructor won't be called. Note that if you use the backward compatible
 *      syntax, where these's no parenthesis after the class name, then it will not look for {@code INSTANCE}.
 *   </li>
 *   <li>
 *      <p>If there exists a class named <tt><i>className</i>Builder</tt>, then that class will be instantiated
 *      instead with the given constructor arguments, and the JavaBean properties of that builder instance will be
 *      set. After that, the public <tt>build()</tt> method of the instance will be called, whose return value
 *      will be the value of the whole expression. (The builder class and the <tt>build()</tt> method is simply
 *      found by name, there's no special interface to implement.) Note that if you use the backward compatible
 *      syntax, where these's no parenthesis after the class name, then it will not look for builder class. Note
 *      that if you have a builder class, you don't actually need a <tt><i>className</i></tt> class (since 2.3.24);
 *      after all, <tt><i>className</i>Builder.build()</tt> can return any kind of object.
 *   </li>
 *   <li>
 *      <p>Currently, the values of arguments and properties can only be one of these:
 *      <ul>
 *        <li>A numerical literal, like {@code 123} or {@code -1.5}. The value will be automatically converted to
 *        the type of the target (just like in FTL). However, a target type is only available if the number will
 *        be a parameter to a method or constructor, not when it's a value (or key) in a {@code List} or
 *        {@code Map} literal. Thus in the last case the type of number will be like in Java language, like
 *        {@code 1} is an {@code int}, and {@code 1.0} is a {@code double}, and {@code 1.0f} is a {@code float},
 *        etc. In all cases, the standard Java type postfixes can be used ("f", "d", "l"), plus "bd" for
 *        {@code BigDecimal} and "bi" for {@code BigInteger}.</li>
 *        <li>A boolean literal: {@code true} or {@code false}
 *        <li>The null literal: {@code null}
 *        <li>A string literal with FTL syntax, except that  it can't contain <tt>${...}</tt>-s and
 *            <tt>#{...}</tt>-s. Examples: {@code "Line 1\nLine 2"} or {@code r"C:\temp"}.
 *        <li>A list literal (since 2.3.24) with FTL-like syntax, for example {@code [ 'foo', 2, true ]}.
 *            If the parameter is expected to be array, the list will be automatically converted to array.
 *            The list items can be any kind of expression, like even object builder expressions.
 *        <li>A map literal (since 2.3.24) with FTL-like syntax, for example <code>{ 'foo': 2, 'bar': true }</code>.
 *            The keys and values can be any kind of expression, like even object builder expressions.
 *            The resulting Java object will be a {@link Map} that keeps the item order ({@link LinkedHashMap} as
 *            of this writing).
 *        <li>A reference to a public static filed, like {@code Configuration.AUTO_DETECT_TAG_SYNTAX} or
 *            {@code com.example.MyClass.MY_CONSTANT}.
 *        <li>An object builder expression. That is, object builder expressions can be nested into each other.
 *      </ul>
 *   </li>
 *   <li>
 *     The same kind of expression as for parameters can also be used as top-level expressions (though it's
 *     rarely useful, apart from using {@code null}).
 *   </li>
 *   <li>
 *     <p>The top-level object builder expressions may omit {@code ()}. In that case, for backward compatibility,
 *     the {@code INSTANCE} field and the builder class is not searched, so the instance will be always
 *     created with its parameterless constructor. (This behavior will possibly change in 2.4.) The {@code ()}
 *     can't be omitted for nested expressions.
 *   </li>
 *   <li>
 *     <p>The following classes can be referred to with simple (unqualified) name instead of fully qualified name:
 *     {@link DefaultObjectWrapper}, {@link BeansWrapper}, {@link SimpleObjectWrapper}, {@link Locale},
 *     {@link TemplateConfiguration}, {@link PathGlobMatcher}, {@link FileNameGlobMatcher}, {@link PathRegexMatcher},
 *     {@link AndMatcher}, {@link OrMatcher}, {@link NotMatcher}, {@link ConditionalTemplateConfigurationFactory},
 *     {@link MergingTemplateConfigurationFactory}, {@link FirstMatchTemplateConfigurationFactory},
 *     {@link HTMLOutputFormat}, {@link XMLOutputFormat}, {@link RTFOutputFormat}, {@link PlainTextOutputFormat},
 *     {@link UndefinedOutputFormat}, {@link Configuration}.
 *   </li>
 *   <li>
 *     <p>{@link TimeZone} objects can be created like {@code TimeZone("UTC")}, despite that there's no a such
 *     constructor (since 2.3.24).
 *   </li>
 *   <li>
 *     <p>The classes and methods that the expression meant to access must be all public.
 *   </li>
 * </ul>
 *
 * @param name the name of the setting.
 * @param value the string that describes the new value of the setting.
 *
 * @throws UnknownSettingException if the name is wrong.
 * @throws TemplateException if the new value of the setting can't be set for any other reasons.
 */
public void setSetting(String name, String value) throws TemplateException {
    boolean unknown = false;
    try {
        if (LOCALE_KEY.equals(name)) {
            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) || CUSTOM_NUMBER_FORMATS_KEY_CAMEL_CASE.equals(name)) {
            Map map = (Map) _ObjectBuilderSettingEvaluator.eval(value, Map.class, false, _SettingEvaluationEnvironment.getCurrent());
            _CoreAPI.checkSettingValueItemsType("Map keys", String.class, map.keySet());
            _CoreAPI.checkSettingValueItemsType("Map values", TemplateNumberFormatFactory.class, map.values());
            setCustomNumberFormats(map);
        } else if (TIME_FORMAT_KEY_SNAKE_CASE.equals(name) || TIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
            setTimeFormat(value);
        } else if (DATE_FORMAT_KEY_SNAKE_CASE.equals(name) || DATE_FORMAT_KEY_CAMEL_CASE.equals(name)) {
            setDateFormat(value);
        } else if (DATETIME_FORMAT_KEY_SNAKE_CASE.equals(name) || DATETIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
            setDateTimeFormat(value);
        } else if (CUSTOM_DATE_FORMATS_KEY_SNAKE_CASE.equals(name) || CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE.equals(name)) {
            Map map = (Map) _ObjectBuilderSettingEvaluator.eval(value, Map.class, false, _SettingEvaluationEnvironment.getCurrent());
            _CoreAPI.checkSettingValueItemsType("Map keys", String.class, map.keySet());
            _CoreAPI.checkSettingValueItemsType("Map values", TemplateDateFormatFactory.class, map.values());
            setCustomDateFormats(map);
        } else if (TIME_ZONE_KEY_SNAKE_CASE.equals(name) || TIME_ZONE_KEY_CAMEL_CASE.equals(name)) {
            setTimeZone(parseTimeZoneSettingValue(value));
        } else if (SQL_DATE_AND_TIME_TIME_ZONE_KEY_SNAKE_CASE.equals(name) || SQL_DATE_AND_TIME_TIME_ZONE_KEY_CAMEL_CASE.equals(name)) {
            setSQLDateAndTimeTimeZone(value.equals("null") ? null : parseTimeZoneSettingValue(value));
        } else if (CLASSIC_COMPATIBLE_KEY_SNAKE_CASE.equals(name) || CLASSIC_COMPATIBLE_KEY_CAMEL_CASE.equals(name)) {
            char firstChar;
            if (value != null && value.length() > 0) {
                firstChar = value.charAt(0);
            } else {
                firstChar = 0;
            }
            if (Character.isDigit(firstChar) || firstChar == '+' || firstChar == '-') {
                setClassicCompatibleAsInt(Integer.parseInt(value));
            } else {
                setClassicCompatible(value != null ? StringUtil.getYesNo(value) : false);
            }
        } else if (TEMPLATE_EXCEPTION_HANDLER_KEY_SNAKE_CASE.equals(name) || TEMPLATE_EXCEPTION_HANDLER_KEY_CAMEL_CASE.equals(name)) {
            if (value.indexOf('.') == -1) {
                if ("debug".equalsIgnoreCase(value)) {
                    setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER);
                } else if ("html_debug".equalsIgnoreCase(value) || "htmlDebug".equals(value)) {
                    setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER);
                } else if ("ignore".equalsIgnoreCase(value)) {
                    setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
                } else if ("rethrow".equalsIgnoreCase(value)) {
                    setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
                } else if (DEFAULT.equalsIgnoreCase(value) && this instanceof Configuration) {
                    ((Configuration) this).unsetTemplateExceptionHandler();
                } else {
                    throw invalidSettingValueException(name, value);
                }
            } else {
                setTemplateExceptionHandler((TemplateExceptionHandler) _ObjectBuilderSettingEvaluator.eval(value, TemplateExceptionHandler.class, false, _SettingEvaluationEnvironment.getCurrent()));
            }
        } else if (ATTEMPT_EXCEPTION_REPORTER_KEY_SNAKE_CASE.equals(name) || ATTEMPT_EXCEPTION_REPORTER_KEY_CAMEL_CASE.equals(name)) {
            if (value.indexOf('.') == -1) {
                if ("log_error".equalsIgnoreCase(value) || "logError".equals(value)) {
                    setAttemptExceptionReporter(AttemptExceptionReporter.LOG_ERROR_REPORTER);
                } else if ("log_warn".equalsIgnoreCase(value) || "logWarn".equals(value)) {
                    setAttemptExceptionReporter(AttemptExceptionReporter.LOG_WARN_REPORTER);
                } else if (DEFAULT.equalsIgnoreCase(value) && this instanceof Configuration) {
                    ((Configuration) this).unsetAttemptExceptionReporter();
                } else {
                    throw invalidSettingValueException(name, value);
                }
            } else {
                setAttemptExceptionReporter((AttemptExceptionReporter) _ObjectBuilderSettingEvaluator.eval(value, AttemptExceptionReporter.class, false, _SettingEvaluationEnvironment.getCurrent()));
            }
        } else if (ARITHMETIC_ENGINE_KEY_SNAKE_CASE.equals(name) || ARITHMETIC_ENGINE_KEY_CAMEL_CASE.equals(name)) {
            if (value.indexOf('.') == -1) {
                if ("bigdecimal".equalsIgnoreCase(value)) {
                    setArithmeticEngine(ArithmeticEngine.BIGDECIMAL_ENGINE);
                } else if ("conservative".equalsIgnoreCase(value)) {
                    setArithmeticEngine(ArithmeticEngine.CONSERVATIVE_ENGINE);
                } else {
                    throw invalidSettingValueException(name, value);
                }
            } else {
                setArithmeticEngine((ArithmeticEngine) _ObjectBuilderSettingEvaluator.eval(value, ArithmeticEngine.class, false, _SettingEvaluationEnvironment.getCurrent()));
            }
        } else if (OBJECT_WRAPPER_KEY_SNAKE_CASE.equals(name) || OBJECT_WRAPPER_KEY_CAMEL_CASE.equals(name)) {
            if (DEFAULT.equalsIgnoreCase(value)) {
                if (this instanceof Configuration) {
                    ((Configuration) this).unsetObjectWrapper();
                } else {
                    setObjectWrapper(Configuration.getDefaultObjectWrapper(Configuration.VERSION_2_3_0));
                }
            } else if (DEFAULT_2_3_0.equalsIgnoreCase(value)) {
                setObjectWrapper(Configuration.getDefaultObjectWrapper(Configuration.VERSION_2_3_0));
            } else if ("simple".equalsIgnoreCase(value)) {
                setObjectWrapper(ObjectWrapper.SIMPLE_WRAPPER);
            } else if ("beans".equalsIgnoreCase(value)) {
                setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
            } else if ("jython".equalsIgnoreCase(value)) {
                Class clazz = Class.forName("freemarker.ext.jython.JythonWrapper");
                setObjectWrapper((ObjectWrapper) clazz.getField("INSTANCE").get(null));
            } else {
                setObjectWrapper((ObjectWrapper) _ObjectBuilderSettingEvaluator.eval(value, ObjectWrapper.class, false, _SettingEvaluationEnvironment.getCurrent()));
            }
        } else if (BOOLEAN_FORMAT_KEY_SNAKE_CASE.equals(name) || BOOLEAN_FORMAT_KEY_CAMEL_CASE.equals(name)) {
            setBooleanFormat(value);
        } else if (OUTPUT_ENCODING_KEY_SNAKE_CASE.equals(name) || OUTPUT_ENCODING_KEY_CAMEL_CASE.equals(name)) {
            setOutputEncoding(value);
        } else if (URL_ESCAPING_CHARSET_KEY_SNAKE_CASE.equals(name) || URL_ESCAPING_CHARSET_KEY_CAMEL_CASE.equals(name)) {
            setURLEscapingCharset(value);
        } else if (STRICT_BEAN_MODELS_KEY_SNAKE_CASE.equals(name) || STRICT_BEAN_MODELS_KEY_CAMEL_CASE.equals(name)) {
            setStrictBeanModels(StringUtil.getYesNo(value));
        } else if (AUTO_FLUSH_KEY_SNAKE_CASE.equals(name) || AUTO_FLUSH_KEY_CAMEL_CASE.equals(name)) {
            setAutoFlush(StringUtil.getYesNo(value));
        } else if (SHOW_ERROR_TIPS_KEY_SNAKE_CASE.equals(name) || SHOW_ERROR_TIPS_KEY_CAMEL_CASE.equals(name)) {
            setShowErrorTips(StringUtil.getYesNo(value));
        } else if (API_BUILTIN_ENABLED_KEY_SNAKE_CASE.equals(name) || API_BUILTIN_ENABLED_KEY_CAMEL_CASE.equals(name)) {
            setAPIBuiltinEnabled(StringUtil.getYesNo(value));
        } else if (NEW_BUILTIN_CLASS_RESOLVER_KEY_SNAKE_CASE.equals(name) || NEW_BUILTIN_CLASS_RESOLVER_KEY_CAMEL_CASE.equals(name)) {
            if ("unrestricted".equals(value)) {
                setNewBuiltinClassResolver(TemplateClassResolver.UNRESTRICTED_RESOLVER);
            } else if ("safer".equals(value)) {
                setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
            } else if ("allows_nothing".equals(value) || "allowsNothing".equals(value)) {
                setNewBuiltinClassResolver(TemplateClassResolver.ALLOWS_NOTHING_RESOLVER);
            } else if (value.indexOf(":") != -1) {
                List segments = parseAsSegmentedList(value);
                Set allowedClasses = null;
                List trustedTemplates = null;
                for (int i = 0; i < segments.size(); i++) {
                    KeyValuePair kv = (KeyValuePair) segments.get(i);
                    String segmentKey = (String) kv.getKey();
                    List segmentValue = (List) kv.getValue();
                    if (segmentKey.equals(ALLOWED_CLASSES_SNAKE_CASE) || segmentKey.equals(ALLOWED_CLASSES_CAMEL_CASE)) {
                        allowedClasses = new HashSet(segmentValue);
                    } else if (segmentKey.equals(TRUSTED_TEMPLATES_SNAKE_CASE) || segmentKey.equals(TRUSTED_TEMPLATES_CAMEL_CASE)) {
                        trustedTemplates = segmentValue;
                    } else {
                        throw new ParseException("Unrecognized list segment key: " + StringUtil.jQuote(segmentKey) + ". Supported keys are: " + "\"" + ALLOWED_CLASSES_SNAKE_CASE + "\", " + "\"" + ALLOWED_CLASSES_CAMEL_CASE + "\", " + "\"" + TRUSTED_TEMPLATES_SNAKE_CASE + "\", " + "\"" + TRUSTED_TEMPLATES_CAMEL_CASE + "\". ", 0, 0);
                    }
                }
                setNewBuiltinClassResolver(new OptInTemplateClassResolver(allowedClasses, trustedTemplates));
            } else if ("allow_nothing".equals(value)) {
                throw new IllegalArgumentException("The correct value would be: allows_nothing");
            } else if ("allowNothing".equals(value)) {
                throw new IllegalArgumentException("The correct value would be: allowsNothing");
            } else if (value.indexOf('.') != -1) {
                setNewBuiltinClassResolver((TemplateClassResolver) _ObjectBuilderSettingEvaluator.eval(value, TemplateClassResolver.class, false, _SettingEvaluationEnvironment.getCurrent()));
            } else {
                throw invalidSettingValueException(name, value);
            }
        } else if (LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE.equals(name) || LOG_TEMPLATE_EXCEPTIONS_KEY_CAMEL_CASE.equals(name)) {
            setLogTemplateExceptions(StringUtil.getYesNo(value));
        } else if (WRAP_UNCHECKED_EXCEPTIONS_KEY_SNAKE_CASE.equals(name) || WRAP_UNCHECKED_EXCEPTIONS_KEY_CAMEL_CASE.equals(name)) {
            setWrapUncheckedExceptions(StringUtil.getYesNo(value));
        } else if (LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
            setLazyAutoImports(value.equals(NULL) ? null : Boolean.valueOf(StringUtil.getYesNo(value)));
        } else if (LAZY_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
            setLazyImports(StringUtil.getYesNo(value));
        } else if (AUTO_INCLUDE_KEY_SNAKE_CASE.equals(name) || AUTO_INCLUDE_KEY_CAMEL_CASE.equals(name)) {
            setAutoIncludes(parseAsList(value));
        } else if (AUTO_IMPORT_KEY_SNAKE_CASE.equals(name) || AUTO_IMPORT_KEY_CAMEL_CASE.equals(name)) {
            setAutoImports(parseAsImportList(value));
        } else {
            unknown = true;
        }
    } catch (Exception e) {
        throw settingValueAssignmentException(name, value, e);
    }
    if (unknown) {
        throw unknownSettingException(name);
    }
}
Also used : HashSet(java.util.HashSet) Set(java.util.Set) Configuration(freemarker.template.Configuration) AttemptExceptionReporter(freemarker.template.AttemptExceptionReporter) TemplateException(freemarker.template.TemplateException) NullArgumentException(freemarker.template.utility.NullArgumentException) IOException(java.io.IOException) DefaultObjectWrapper(freemarker.template.DefaultObjectWrapper) SimpleObjectWrapper(freemarker.template.SimpleObjectWrapper) ObjectWrapper(freemarker.template.ObjectWrapper) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) List(java.util.List) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) HashSet(java.util.HashSet)

Aggregations

AttemptExceptionReporter (freemarker.template.AttemptExceptionReporter)1 Configuration (freemarker.template.Configuration)1 DefaultObjectWrapper (freemarker.template.DefaultObjectWrapper)1 ObjectWrapper (freemarker.template.ObjectWrapper)1 SimpleObjectWrapper (freemarker.template.SimpleObjectWrapper)1 TemplateException (freemarker.template.TemplateException)1 NullArgumentException (freemarker.template.utility.NullArgumentException)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedHashMap (java.util.LinkedHashMap)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1