use of freemarker.template.ObjectWrapper in project spring-framework by spring-projects.
the class FreeMarkerView method getObjectWrapper.
/**
* Get the configured FreeMarker {@link ObjectWrapper}, or the
* {@linkplain ObjectWrapper#DEFAULT_WRAPPER default wrapper} if none specified.
* @see freemarker.template.Configuration#getObjectWrapper()
*/
protected ObjectWrapper getObjectWrapper() {
ObjectWrapper ow = obtainConfiguration().getObjectWrapper();
Version version = Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS;
return (ow != null ? ow : new DefaultObjectWrapperBuilder(version).build());
}
use of freemarker.template.ObjectWrapper in project PublicCMS-preview by sanluan.
the class TemplateDirectiveHandler method reduce.
private Map<String, TemplateModel> reduce() throws TemplateModelException {
Map<String, TemplateModel> reduceMap = new LinkedHashMap<>();
ObjectWrapper objectWrapper = environment.getObjectWrapper();
Namespace namespace = environment.getCurrentNamespace();
Iterator<Entry<String, Object>> iterator = map.entrySet().iterator();
for (int i = 0; iterator.hasNext(); i++) {
Entry<String, Object> entry = iterator.next();
if (i < loopVars.length) {
loopVars[i] = objectWrapper.wrap(entry.getValue());
} else {
String key = entry.getKey();
reduceMap.put(key, namespace.get(key));
namespace.put(key, objectWrapper.wrap(entry.getValue()));
}
}
return reduceMap;
}
use of freemarker.template.ObjectWrapper 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);
}
}
use of freemarker.template.ObjectWrapper in project freemarker by apache.
the class Environment method setMacroContextLocalsFromArguments.
/**
* Sets the local variables corresponding to the macro call arguments in the macro context.
*/
private void setMacroContextLocalsFromArguments(final Macro.Context macroCtx, final Macro macro, final Map namedArgs, final List positionalArgs) throws TemplateException, _MiscTemplateException {
String catchAllParamName = macro.getCatchAll();
if (namedArgs != null) {
final SimpleHash catchAllParamValue;
if (catchAllParamName != null) {
catchAllParamValue = new SimpleHash((ObjectWrapper) null);
macroCtx.setLocalVar(catchAllParamName, catchAllParamValue);
} else {
catchAllParamValue = null;
}
for (Iterator it = namedArgs.entrySet().iterator(); it.hasNext(); ) {
final Map.Entry argNameAndValExp = (Map.Entry) it.next();
final String argName = (String) argNameAndValExp.getKey();
final boolean isArgNameDeclared = macro.hasArgNamed(argName);
if (isArgNameDeclared || catchAllParamName != null) {
Expression argValueExp = (Expression) argNameAndValExp.getValue();
TemplateModel argValue = argValueExp.eval(this);
if (isArgNameDeclared) {
macroCtx.setLocalVar(argName, argValue);
} else {
catchAllParamValue.put(argName, argValue);
}
} else {
throw new _MiscTemplateException(this, (macro.isFunction() ? "Function " : "Macro "), new _DelayedJQuote(macro.getName()), " has no parameter with name ", new _DelayedJQuote(argName), ".");
}
}
} else if (positionalArgs != null) {
final SimpleSequence catchAllParamValue;
if (catchAllParamName != null) {
catchAllParamValue = new SimpleSequence((ObjectWrapper) null);
macroCtx.setLocalVar(catchAllParamName, catchAllParamValue);
} else {
catchAllParamValue = null;
}
String[] argNames = macro.getArgumentNamesInternal();
final int argsCnt = positionalArgs.size();
if (argNames.length < argsCnt && catchAllParamName == null) {
throw new _MiscTemplateException(this, (macro.isFunction() ? "Function " : "Macro "), new _DelayedJQuote(macro.getName()), " only accepts ", new _DelayedToString(argNames.length), " parameters, but got ", new _DelayedToString(argsCnt), ".");
}
for (int i = 0; i < argsCnt; i++) {
Expression argValueExp = (Expression) positionalArgs.get(i);
TemplateModel argValue = argValueExp.eval(this);
try {
if (i < argNames.length) {
String argName = argNames[i];
macroCtx.setLocalVar(argName, argValue);
} else {
catchAllParamValue.add(argValue);
}
} catch (RuntimeException re) {
throw new _MiscTemplateException(re, this);
}
}
}
}
use of freemarker.template.ObjectWrapper in project freemarker by apache.
the class DeepUnwrap method unwrap.
private static Object unwrap(TemplateModel model, boolean permissive) throws TemplateModelException {
Environment env = Environment.getCurrentEnvironment();
TemplateModel nullModel = null;
if (env != null) {
ObjectWrapper wrapper = env.getObjectWrapper();
if (wrapper != null) {
nullModel = wrapper.wrap(null);
}
}
return unwrap(model, nullModel, permissive);
}
Aggregations