public class Configuration extends Configurable implements Cloneable
This class is meant to be used in a singleton pattern. That is, you create an instance of this at the beginning of
the application life-cycle, set its configuration settings
there (either with the
setter methods like setTemplateLoader(TemplateLoader)
or by loading a .properties
file), and then
use that single instance everywhere in your application. Frequently re-creating Configuration
is a typical
and grave mistake from performance standpoint, as the Configuration
holds the template cache, and often also
the class introspection cache, which then will be lost. (Note that, naturally, having multiple long-lived instances,
like one per component that internally uses FreeMarker is fine.)
The basic usage pattern is like:
// Where the application is initialized; in general you do this ONLY ONCE in the application life-cycle! Configuration cfg = new Configuration(VERSION_X_Y_Z)); // Where X, Y, Z enables the not-100%-backward-compatible fixes introduced in // FreeMarker version X.Y.Z and earlier (seeConfiguration(Version)
). cfg.setSomeSetting(...); cfg.setOtherSetting(...); ... // Later, whenever the application needs a template (so you may do this a lot, and from multiple threads):Template
myTemplate = cfg.getTemplate
("myTemplate.html"); myTemplate.process
(dataModel, out);
A couple of settings that you should not leave on its default value are:
template_loader
: The default value is deprecated and in fact quite
useless. (For the most common cases you can use the convenience methods,
setDirectoryForTemplateLoading(File)
and setClassForTemplateLoading(Class, String)
and
setClassLoaderForTemplateLoading(ClassLoader, String)
too.)
default_encoding
: The default value is system dependent, which makes it
fragile on servers, so it should be set explicitly, like to "UTF-8" nowadays.
template_exception_handler
: For developing
HTML pages, the most convenient value is TemplateExceptionHandler.HTML_DEBUG_HANDLER
. For production,
TemplateExceptionHandler.RETHROW_HANDLER
is safer to use.
A Configuration
object is thread-safe only after you have stopped modifying the configuration settings,
and you have safely published it (see JSR 133 and related literature) to other threads. Generally, you set
everything directly after you have instantiated the Configuration
object, then you don't change the settings
anymore, so then it's safe to make it accessible (again, via a "safe publication" technique) from multiple threads.
The methods that aren't for modifying settings, like getTemplate(String)
, are thread-safe.
Configurable.SettingValueAssignmentException, Configurable.UnknownSettingException
API_BUILTIN_ENABLED_KEY, ARITHMETIC_ENGINE_KEY, AUTO_FLUSH_KEY, BOOLEAN_FORMAT_KEY, CLASSIC_COMPATIBLE_KEY, DATE_FORMAT_KEY, DATETIME_FORMAT_KEY, LOCALE_KEY, LOG_TEMPLATE_EXCEPTIONS_KEY, NEW_BUILTIN_CLASS_RESOLVER_KEY, NUMBER_FORMAT_KEY, OBJECT_WRAPPER_KEY, OUTPUT_ENCODING_KEY, SHOW_ERROR_TIPS_KEY, SQL_DATE_AND_TIME_TIME_ZONE_KEY, STRICT_BEAN_MODELS, STRICT_BEAN_MODELS_KEY, TEMPLATE_EXCEPTION_HANDLER_KEY, TIME_FORMAT_KEY, TIME_ZONE_KEY, URL_ESCAPING_CHARSET_KEY
Constructor and Description |
---|
Configuration()
Deprecated.
Use
Configuration(Version) instead. Note that the version can be still modified later with
setIncompatibleImprovements(Version) (or
Configurable.setSettings(Properties) ). |
Configuration(Version incompatibleImprovements)
Creates a new instance and sets which of the non-backward-compatible bugfixes/improvements should be enabled.
|
Modifier and Type | Method and Description |
---|---|
void |
addAutoImport(String namespaceVarName,
String templateName)
Adds an invisible
#import templateName as namespaceVarName at the beginning of all
templates. |
void |
addAutoInclude(String templateName)
Adds an invisible
#include templateName as namespaceVarName at the beginning of all
templates. |
void |
clearEncodingMap()
Clears language-to-encoding map.
|
void |
clearSharedVariables()
Removes all shared sharedVariables, except the predefined ones (compress, html_escape, etc.).
|
void |
clearTemplateCache()
Removes all entries from the template cache, thus forcing reloading of templates
on subsequent
getTemplate calls. |
Object |
clone() |
protected void |
doAutoImportsAndIncludes(Environment env) |
CacheStorage |
getCacheStorage()
The getter pair of
setCacheStorage(CacheStorage) . |
protected String |
getCorrectedNameForUnknownSetting(String name) |
static Configuration |
getDefaultConfiguration()
Deprecated.
The usage of the static singleton (the "default")
Configuration instance can easily cause erroneous, unpredictable
behavior. This is because multiple independent software components may use
FreeMarker internally inside the same application, so they will interfere
because of the common Configuration instance. Each such component
should use its own private Configuration object instead, that it
typically creates with new Configuration() when the component
is initialized. |
String |
getDefaultEncoding()
Gets the default encoding for converting bytes to characters when
reading template files in a locale for which no explicit encoding
was specified.
|
static ObjectWrapper |
getDefaultObjectWrapper(Version incompatibleImprovements)
Returns the default object wrapper for a given "incompatible_improvements" version.
|
String |
getEncoding(Locale locale)
Gets the preferred character encoding for the given locale, or the
default encoding if no encoding is set explicitly for the specified
locale.
|
String |
getIncompatibleEnhancements()
Deprecated.
Use
getIncompatibleImprovements() instead. |
Version |
getIncompatibleImprovements() |
boolean |
getLocalizedLookup()
The getter pair of
setLocalizedLookup(boolean) . |
int |
getParsedIncompatibleEnhancements()
Deprecated.
Use
getIncompatibleImprovements() instead. |
TemplateModel |
getSharedVariable(String name)
Gets a shared variable.
|
Set |
getSharedVariableNames()
Returns the set containing the names of all defined shared sharedVariables.
|
boolean |
getStrictSyntaxMode()
The getter pair of
setStrictSyntaxMode(boolean) . |
Set |
getSupportedBuiltInDirectiveNames()
Returns the names of the directives that are predefined by FreeMarker.
|
Set |
getSupportedBuiltInNames()
Returns the names of the supported "built-ins".
|
int |
getTagSyntax()
The getter pair of
setTagSyntax(int) . |
Template |
getTemplate(String name)
Retrieves the template with the given name from the template cache, loading it into the cache first if it's
missing/staled.
|
Template |
getTemplate(String name,
Locale locale)
Shorthand for
getTemplate(name, locale, null, null, true, false) . |
Template |
getTemplate(String name,
Locale locale,
Object customLookupCondition,
String encoding,
boolean parseAsFTL,
boolean ignoreMissing)
Retrieves the template with the given name (and according the specified further parameters) from the template
cache, loading it into the cache first if it's missing/staled.
|
Template |
getTemplate(String name,
Locale locale,
String encoding)
Shorthand for
getTemplate(name, locale, null, encoding, true, false) . |
Template |
getTemplate(String name,
Locale locale,
String encoding,
boolean parseAsFTL)
Shorthand for
getTemplate(name, locale, null, encoding, parseAsFTL, false) . |
Template |
getTemplate(String name,
Locale locale,
String encoding,
boolean parseAsFTL,
boolean ignoreMissing)
|
Template |
getTemplate(String name,
String encoding)
Shorthand for
getTemplate(name, null, null, encoding, true, false) . |
TemplateLoader |
getTemplateLoader()
The getter pair of
setTemplateLoader(TemplateLoader) . |
TemplateLookupStrategy |
getTemplateLookupStrategy()
The getter pair of
setTemplateLookupStrategy(TemplateLookupStrategy) . |
TemplateNameFormat |
getTemplateNameFormat()
The getter pair of
setTemplateNameFormat(TemplateNameFormat) . |
static Version |
getVersion()
Returns the FreeMarker version information, most importantly the major.minor.micro version numbers.
|
static String |
getVersionNumber()
Deprecated.
Use
getVersion() instead. |
boolean |
getWhitespaceStripping()
Gets whether the FTL parser will try to remove
superfluous white-space around certain FTL tags.
|
boolean |
isCacheStorageExplicitlySet()
Tells if
setCacheStorage(CacheStorage) (or equivalent) was already called on this instance. |
boolean |
isLogTemplateExceptionsExplicitlySet()
Tells if
setLogTemplateExceptions(boolean) (or equivalent) was already called on this instance. |
boolean |
isObjectWrapperExplicitlySet()
Tells if
setObjectWrapper(ObjectWrapper) (or equivalent) was already called on this instance. |
boolean |
isTemplateExceptionHandlerExplicitlySet()
Tells if
setTemplateExceptionHandler(TemplateExceptionHandler) (or equivalent) was already called on
this instance. |
boolean |
isTemplateLoaderExplicitlySet()
Tells if
setTemplateLoader(TemplateLoader) (or equivalent) was already called on this instance. |
boolean |
isTemplateLookupStrategyExplicitlySet()
Tells if
setTemplateLookupStrategy(TemplateLookupStrategy) (or equivalent) was already called on this
instance. |
boolean |
isTemplateNameFormatExplicitlySet()
Tells if
setTemplateNameFormat(TemplateNameFormat) (or equivalent) was already called on this instance. |
void |
loadBuiltInEncodingMap()
Loads a preset language-to-encoding map, similarly as if you have called
clearEncodingMap() and then did multiple setEncoding(Locale, String) calls. |
void |
removeAutoImport(String namespaceVarName)
Removes an auto-import; see
addAutoImport(String, String) . |
void |
removeAutoInclude(String templateName)
Removes a template from the auto-include list; see
addAutoInclude(String) . |
void |
removeTemplateFromCache(String name)
Equivalent to removeTemplateFromCache(name, thisCfg.getLocale(), thisCfg.getEncoding(thisCfg.getLocale()), true).
|
void |
removeTemplateFromCache(String name,
Locale locale)
Equivalent to removeTemplateFromCache(name, locale, thisCfg.getEncoding(locale), true).
|
void |
removeTemplateFromCache(String name,
Locale locale,
String encoding)
Equivalent to removeTemplateFromCache(name, locale, encoding, true).
|
void |
removeTemplateFromCache(String name,
Locale locale,
String encoding,
boolean parse)
Removes a template from the template cache, hence forcing the re-loading
of it when it's next time requested.
|
void |
removeTemplateFromCache(String name,
String encoding)
Equivalent to removeTemplateFromCache(name, thisCfg.getLocale(), encoding, true).
|
void |
setAllSharedVariables(TemplateHashModelEx hash)
Adds all object in the hash as shared variable to the configuration; it's like doing several
setSharedVariable(String, Object) calls, one for each hash entry. |
void |
setAutoImports(Map map)
Removes all auto-imports, then calls
addAutoImport(String, String) for each Map -entry (the entry
key is the namespaceVarName ). |
void |
setAutoIncludes(List templateNames)
Removes all auto-includes, then calls
addAutoInclude(String) for each List items. |
void |
setCacheStorage(CacheStorage cacheStorage)
Sets the
CacheStorage used for caching Template -s;
the earlier content of the template cache will be dropt. |
void |
setClassForTemplateLoading(Class resourceLoaderClass,
String basePackagePath)
Sets the class whose
Class.getResource(String) method will be used to load templates, from the inside the
package specified. |
void |
setClassLoaderForTemplateLoading(ClassLoader classLoader,
String basePackagePath)
Sets the
ClassLoader whose ClassLoader.getResource(String) method will be used to load templates,
from the inside the package specified. |
static void |
setDefaultConfiguration(Configuration config)
Deprecated.
Using the "default"
Configuration instance can
easily lead to erroneous, unpredictable behaviour.
See more here... . |
void |
setDefaultEncoding(String encoding)
Sets the charset used for decoding byte sequences to character sequences when
reading template files in a locale for which no explicit encoding
was specified via
setEncoding(Locale, String) . |
void |
setDirectoryForTemplateLoading(File dir)
Sets the file system directory from which to load templates.
|
void |
setEncoding(Locale locale,
String encoding)
Sets the character set encoding to use for templates of
a given locale.
|
void |
setIncompatibleEnhancements(String version)
Deprecated.
Use
Configuration(Version) , or
as last chance, setIncompatibleImprovements(Version) instead. |
void |
setIncompatibleImprovements(Version incompatibleImprovements)
Use
Configuration(Version) instead if possible; see the meaning of the parameter there. |
void |
setLocalizedLookup(boolean localizedLookup)
Enables/disables localized template lookup.
|
void |
setLogTemplateExceptions(boolean value)
Specifies if
TemplateException -s thrown by template processing are logged by FreeMarker or not. |
void |
setObjectWrapper(ObjectWrapper objectWrapper)
Sets the object wrapper used to wrap objects to
TemplateModel -s. |
void |
setServletContextForTemplateLoading(Object servletContext,
String path)
Sets the servlet context from which to load templates.
|
void |
setSetting(String name,
String value)
Sets a FreeMarker setting by a name and string value.
|
void |
setSharedVariable(String name,
Object value)
Adds shared variable to the configuration; It uses
Configurable.getObjectWrapper() to wrap the
value , so it's important that the object wrapper is set before this. |
void |
setSharedVariable(String name,
TemplateModel tm)
Adds a shared variable to the configuration.
|
void |
setSharedVaribles(Map map)
Replaces all shared variables (removes all previously added ones).
|
void |
setStrictSyntaxMode(boolean b)
Deprecated.
Only
true (the default) value will be supported sometimes in the future. |
void |
setTagSyntax(int tagSyntax)
Determines the syntax of the template files (angle bracket VS square bracket)
that has no
#ftl in it. |
void |
setTemplateExceptionHandler(TemplateExceptionHandler templateExceptionHandler)
Sets the exception handler used to handle exceptions occurring inside templates.
|
void |
setTemplateLoader(TemplateLoader templateLoader)
Sets a
TemplateLoader that is used to look up and load templates;
as a side effect the template cache will be emptied. |
void |
setTemplateLookupStrategy(TemplateLookupStrategy templateLookupStrategy)
Sets a
TemplateLookupStrategy that is used to look up templates based on the requested name; as a side
effect the template cache will be emptied. |
void |
setTemplateNameFormat(TemplateNameFormat templateNameFormat)
Sets the template name format used.
|
void |
setTemplateUpdateDelay(int seconds)
Sets the time in seconds that must elapse before checking whether there is a newer version of a template file
than the cached one.
|
void |
setWhitespaceStripping(boolean b)
Sets whether the FTL parser will try to remove
superfluous white-space around certain FTL tags.
|
void |
unsetCacheStorage()
Resets the setting to its default, as it was never set.
|
void |
unsetLogTemplateExceptions()
Resets the setting to its default, as it was never set.
|
void |
unsetObjectWrapper()
Resets the setting to its default, as it was never set.
|
void |
unsetTemplateExceptionHandler()
Resets the setting to its default, as it was never set.
|
void |
unsetTemplateLoader()
Resets the setting to its default, as it was never set.
|
void |
unsetTemplateLookupStrategy()
Resets the setting to its default, as it was never set.
|
void |
unsetTemplateNameFormat()
Resets the setting to its default, as it was never set.
|
getArithmeticEngine, getAutoFlush, getBooleanFormat, getClassicCompatibleAsInt, getCustomAttribute, getCustomAttributeNames, getDateFormat, getDateTimeFormat, getEnvironment, getLocale, getLogTemplateExceptions, getNewBuiltinClassResolver, getNumberFormat, getObjectWrapper, getOutputEncoding, getParent, getSetting, getSettings, getShowErrorTips, getSQLDateAndTimeTimeZone, getTemplateExceptionHandler, getTimeFormat, getTimeZone, getURLEscapingCharset, invalidSettingValueException, isAPIBuiltinEnabled, isClassicCompatible, parseAsImportList, parseAsList, parseAsSegmentedList, removeCustomAttribute, setAPIBuiltinEnabled, setArithmeticEngine, setAutoFlush, setBooleanFormat, setClassicCompatible, setClassicCompatibleAsInt, setCustomAttribute, setDateFormat, setDateTimeFormat, setLocale, setNewBuiltinClassResolver, setNumberFormat, setOutputEncoding, setSettings, setSettings, setShowErrorTips, setSQLDateAndTimeTimeZone, setStrictBeanModels, setTimeFormat, setTimeZone, settingValueAssignmentException, setURLEscapingCharset, unknownSettingException
public static final String DEFAULT_ENCODING_KEY
public static final String LOCALIZED_LOOKUP_KEY
public static final String STRICT_SYNTAX_KEY
public static final String WHITESPACE_STRIPPING_KEY
public static final String CACHE_STORAGE_KEY
public static final String TEMPLATE_UPDATE_DELAY_KEY
public static final String AUTO_IMPORT_KEY
public static final String AUTO_INCLUDE_KEY
public static final String TAG_SYNTAX_KEY
public static final String TEMPLATE_LOADER_KEY
public static final String TEMPLATE_LOOKUP_STRATEGY_KEY
public static final String TEMPLATE_NAME_FORMAT_KEY
public static final String INCOMPATIBLE_IMPROVEMENTS_KEY
public static final String INCOMPATIBLE_IMPROVEMENTS
INCOMPATIBLE_IMPROVEMENTS_KEY
instead.public static final String INCOMPATIBLE_ENHANCEMENTS
INCOMPATIBLE_IMPROVEMENTS_KEY
instead.public static final int AUTO_DETECT_TAG_SYNTAX
public static final int ANGLE_BRACKET_TAG_SYNTAX
public static final int SQUARE_BRACKET_TAG_SYNTAX
public static final Version VERSION_2_3_0
incompatible improvements break-point
)public static final Version VERSION_2_3_19
incompatible improvements break-point
)public static final Version VERSION_2_3_20
incompatible improvements break-point
)public static final Version VERSION_2_3_21
incompatible improvements break-point
)public static final Version VERSION_2_3_22
incompatible improvements break-point
)public static final Version DEFAULT_INCOMPATIBLE_IMPROVEMENTS
getIncompatibleImprovements()
, currently VERSION_2_3_0
.public static final String DEFAULT_INCOMPATIBLE_ENHANCEMENTS
DEFAULT_INCOMPATIBLE_IMPROVEMENTS
instead.public static final int PARSED_DEFAULT_INCOMPATIBLE_ENHANCEMENTS
DEFAULT_INCOMPATIBLE_IMPROVEMENTS
instead.public Configuration()
Configuration(Version)
instead. Note that the version can be still modified later with
setIncompatibleImprovements(Version)
(or
Configurable.setSettings(Properties)
).public Configuration(Version incompatibleImprovements)
incompatible_improvements
configuration setting, and
can be changed later, with setIncompatibleImprovements(Version)
for example.
About the "incompatible improvements" setting
This setting value is the FreeMarker version number where the not 100% backward compatible bug fixes and
improvements that you want to enable were already implemented. In new projects you should set this to the
FreeMarker version that you are actually using. In older projects it's also usually better to keep this high,
however you better check the changes activated (find them below), at least if not only the 3rd version number
(the micro version) of incompatibleImprovements
is increased. Generally, as far as you only increase the
last version number of this setting, the changes are always low risk. The default value is 2.3.0 to maximize
backward compatibility, but that value isn't recommended.
Bugfixes and improvements that are fully backward compatible, also those that are important security fixes, are enabled regardless of the incompatible improvements setting.
An important consequence of setting this setting is that now your application will check if the stated minimum FreeMarker version requirement is met. Like if you set this setting to 2.3.22, but accidentally the application is deployed with FreeMarker 2.3.21, then FreeMarker will fail, telling that a higher version is required. After all, the fixes/improvements you have requested aren't available on a lower version.
Note that as FreeMarker's minor (2nd) or major (1st) version number increments, it's possible that emulating some of the old bugs will become unsupported, that is, even if you set this setting to a low value, it silently wont bring back the old behavior anymore. Information about that will be present here.
Currently the effects of this setting are:
2.3.0: This is the lowest supported value, the version used in older projects. This is the default in the FreeMarker 2.3.x series.
2.3.19 (or higher): Bug fix: Wrong #
tags were printed as static text instead of
causing parsing error when there was no correct #
or @
tag earlier in the
same template.
2.3.20 (or higher): ?html
will escape apostrophe-quotes just like ?xhtml
does. Utilizing
this is highly recommended, because otherwise if interpolations are used inside attribute values that use
apostrophe-quotation (<foo bar='${val}'>) instead of plain quotation mark
(<foo bar="${val}">), they might produce HTML/XML that's not well-formed. Note that
?html
didn't do this because long ago there was no cross-browser way of doing this, but it's not a
concern anymore.
2.3.21 (or higher):
The default of the object_wrapper
setting (Configurable.getObjectWrapper()
) changes from
ObjectWrapper.DEFAULT_WRAPPER
to another almost identical DefaultObjectWrapper
singleton,
returned by DefaultObjectWrapperBuilder.build()
. The new default object wrapper's
"incompatible improvements" version is set to the same as of the Configuration
.
See BeansWrapper.BeansWrapper(Version)
for further details. Furthermore, the new default
object wrapper doesn't allow changing its settings; setter methods throw IllegalStateException
).
(If anything tries to call setters on the old default in your application, that's a dangerous bug that
won't remain hidden now. As the old default is a singleton too, potentially shared by independently
developed components, most of them expects the out-of-the-box behavior from it (and the others are
necessarily buggy). Also, then concurrency glitches can occur (and even pollute the class introspection
cache) because the singleton is modified after publishing to other threads.)
Furthermore the new default object wrapper shares class introspection cache with other
BeansWrapper
-s created with BeansWrapperBuilder
, which has an impact as
BeansWrapper.clearClassIntrospecitonCache()
will be disallowed; see more about it there.
The ?iso_...
built-ins won't show the time zone offset for Time
values anymore,
because most databases store time values that aren't in any time zone, but just store hour, minute,
second, and decimal second field values. If you still want to show the offset (like for PostgreSQL
"time with time zone" columns you should), you can force showing the time zone offset by using
myTime?string.iso_fz
(and its other variants).
?is_enumerable
correctly returns false
for Java methods get from Java objects that
are wrapped with BeansWrapper
and its subclasses, like DefaultObjectWrapper
. Although
method values implement TemplateSequenceModel
(because of a historical design quirk in
BeansWrapper
), trying to #list
them will cause error, hence they aren't enumerable.
?c
will return "INF"
, "-INF"
and "NaN"
for positive/negative infinity
and IEEE floating point Not-a-Number, respectively. These are the XML Schema compatible representations
of these special values. Earlier it has returned what DecimalFormat
did with US locale, none of
which was understood by any (common) computer language.
FTL hash literals that repeat keys now only have the key once with ?keys
, and only has the last
value associated to that key with ?values
. This is consistent with the behavior of
hash[key]
and how maps work in Java.
In most cases (where FreeMarker is able to do that), for TemplateLoader
-s that use
URLConnection
, URLConnection#setUseCaches(boolean)
will called with false
,
so that only FreeMarker will do caching, not the URL scheme's handler.
See URLTemplateLoader.setURLConnectionUsesCaches(Boolean)
for more details.
The default of the template_loader
setting (getTemplateLoader()
) changes
to null
, which means that FreeMarker will not find any templates. Earlier
the default was a FileTemplateLoader
that used the current directory as the root. This was
dangerous and fragile as you usually don't have good control over what the current directory will be.
Luckily, the old default almost never looked for the templates at the right place
anyway, so pretty much all applications had to set the template_loader
setting, so it's unlikely
that changing the default breaks your application.
Right-unlimited ranges become readable (like listable), so <#list 1.. as i>...</#list>
works.
Earlier they were only usable for slicing (like hits[10..]
).
Empty ranges return Constants.EMPTY_SEQUENCE
instead of an empty SimpleSequence
. This
is in theory backward compatible, as the API only promises to give something that implements
TemplateSequenceModel
.
Unclosed comments (<#-- ...
) and #noparse
-s won't be silently closed at the end of
template anymore, but cause a parsing error instead.
2.3.22 (or higher):
DefaultObjectWrapper
has some substantial changes with incompatibleImprovements
2.3.22;
check them out at DefaultObjectWrapper.DefaultObjectWrapper(Version)
. It's important to know
that if you set the object_wrapper
setting (to an other value than "default"
), rather
than leaving it on its default value, the object_wrapper
won't inherit the
incompatibleImprovements
of the Configuration
. In that case, if you want the 2.3.22
improvements of DefaultObjectWrapper
, you have to set it in the DefaultObjectWrapper
object itself too! (Note that it's OK to use a DefaultObjectWrapper
with a different
incompatibleImprovements
version number than that of the Configuration
, if that's
really what you want.)
#include
and #nested
doesn't change the parent Template
(see
Configurable.getParent()
) of the Environment
anymore to the Template
that's
included or where #nested
"returns" to. Thus, the parent of Environment
will be now
always the main Template
. (The main Template
is the Template
whose
process
or createProcessingEnvironment
method was called to initiate the output
generation.)
Note all this only matters if you have set settings directly on Template
objects, and almost
nobody does that. Also note that macro calls have never changed the Environment
parent to the
Template
that contains the macro definition, so there's no change there.
When using freemarker.ext.servlet.FreemarkerServlet
:
When using custom JSP tag libraries: Fixes bug where some kind of
values, when put into the JSP page scope (via #global
or via the JSP
PageContext
API) and later read back with the JSP PageContext
API (typically in a
custom JSP tag), might come back as FreeMarker TemplateModel
objects instead of as objects
with a standard Java type. Other Servlet scopes aren't affected. It's highly unlikely that
something expects the presence of this bug. The affected values are of the FTL types listed below,
and to trigger the bug, they either had to be created directly in the template (like as an FTL
literal or with ?date
/time
/datetime
), or you had to use
DefaultObjectWrapper
or SimpleObjectWrapper
(or a subclass of them):
SimpleDate
-s, now they come back as
java.util.Date
-s instead.SimpleSequence
-s, now they come back as
List
-s as expected. This at least stands assuming that the
object_wrapper
configuration setting is a
subclass of BeansWrapper
(such as DefaultObjectWrapper
, which is the default),
but that's practically always the case in applications that use FreeMarker's JSP extension
(otherwise it can still work, but it depends on the quality and capabilities of the
ObjectWrapper
implementation).SimpleHash
-es, now they come back as
Map
-s as expected (again, assuming that the object wrapper is a subclass of
BeansWrapper
, like preferably DefaultObjectWrapper
, which is also the default).
SimpleCollection
-s, now they come back as
Collection
-s as expected (again, assuming that the object wrapper is a subclass
of BeansWrapper
, like preferably DefaultObjectWrapper
).
Initial "["
in the TemplatePath
init-param
has special meaning; it's used for specifying multiple comma separated locations, like in
<param-value>[ WEB-INF/templates, classpath:com/example/myapp/templates ]</param-value>
Initial "{" in the TemplatePath
init-param is reserved for future purposes, and
thus will throw exception.
IllegalArgumentException
- If incompatibleImmprovements
refers to a version that wasn't released yet when the currently
used FreeMarker version was released, or is less than 2.3.0, or is null
.public Object clone()
clone
in class Configurable
public void loadBuiltInEncodingMap()
clearEncodingMap()
and then did multiple setEncoding(Locale, String)
calls.
It assumes the usual character encodings for most languages.
The previous content of the encoding map will be lost.
This default map currently contains the following mappings:
ar | ISO-8859-6 |
be | ISO-8859-5 |
bg | ISO-8859-5 |
ca | ISO-8859-1 |
cs | ISO-8859-2 |
da | ISO-8859-1 |
de | ISO-8859-1 |
el | ISO-8859-7 |
en | ISO-8859-1 |
es | ISO-8859-1 |
et | ISO-8859-1 |
fi | ISO-8859-1 |
fr | ISO-8859-1 |
hr | ISO-8859-2 |
hu | ISO-8859-2 |
is | ISO-8859-1 |
it | ISO-8859-1 |
iw | ISO-8859-8 |
ja | Shift_JIS |
ko | EUC-KR |
lt | ISO-8859-2 |
lv | ISO-8859-2 |
mk | ISO-8859-5 |
nl | ISO-8859-1 |
no | ISO-8859-1 |
pl | ISO-8859-2 |
pt | ISO-8859-1 |
ro | ISO-8859-2 |
ru | ISO-8859-5 |
sh | ISO-8859-5 |
sk | ISO-8859-2 |
sl | ISO-8859-2 |
sq | ISO-8859-2 |
sr | ISO-8859-5 |
sv | ISO-8859-1 |
tr | ISO-8859-9 |
uk | ISO-8859-5 |
zh | GB2312 |
zh_TW | Big5 |
public void clearEncodingMap()
public static Configuration getDefaultConfiguration()
Configuration
instance can easily cause erroneous, unpredictable
behavior. This is because multiple independent software components may use
FreeMarker internally inside the same application, so they will interfere
because of the common Configuration
instance. Each such component
should use its own private Configuration
object instead, that it
typically creates with new Configuration()
when the component
is initialized.public static void setDefaultConfiguration(Configuration config)
Configuration
instance can
easily lead to erroneous, unpredictable behaviour.
See more here...
.getDefaultConfiguration()
.public void setTemplateLoader(TemplateLoader templateLoader)
TemplateLoader
that is used to look up and load templates;
as a side effect the template cache will be emptied.
By providing your own TemplateLoader
implementation, you can load templates from whatever kind of
storages, like from relational databases, NoSQL-storages, etc.
Convenience methods exists to install commonly used loaders, instead of using this method:
setClassForTemplateLoading(Class, String)
,
setClassLoaderForTemplateLoading(ClassLoader, String)
,
setDirectoryForTemplateLoading(File)
, and
setServletContextForTemplateLoading(Object, String)
.
You can chain several TemplateLoader
-s together with MultiTemplateLoader
.
Default value: You should always set the template loader instead of relying on the default value.
(But if you still care what it is, before "incompatible improvements" 2.3.21 it's a FileTemplateLoader
that uses the current directory as its root; as it's hard tell what that directory will be, it's not very useful
and dangerous. Starting with "incompatible improvements" 2.3.21 the default is null
.)
public void unsetTemplateLoader()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isTemplateLoaderExplicitlySet()
will return false
.public boolean isTemplateLoaderExplicitlySet()
setTemplateLoader(TemplateLoader)
(or equivalent) was already called on this instance.public TemplateLoader getTemplateLoader()
setTemplateLoader(TemplateLoader)
.public void setTemplateLookupStrategy(TemplateLookupStrategy templateLookupStrategy)
TemplateLookupStrategy
that is used to look up templates based on the requested name; as a side
effect the template cache will be emptied. The default value is TemplateLookupStrategy.DEFAULT_2_3_0
.public void unsetTemplateLookupStrategy()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isTemplateLookupStrategyExplicitlySet()
will return false
.public boolean isTemplateLookupStrategyExplicitlySet()
setTemplateLookupStrategy(TemplateLookupStrategy)
(or equivalent) was already called on this
instance.public TemplateLookupStrategy getTemplateLookupStrategy()
setTemplateLookupStrategy(TemplateLookupStrategy)
.public void setTemplateNameFormat(TemplateNameFormat templateNameFormat)
TemplateNameFormat.DEFAULT_2_3_0
, while the
recommended value for new projects is TemplateNameFormat.DEFAULT_2_4_0
.public void unsetTemplateNameFormat()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isTemplateNameFormatExplicitlySet()
will return false
.public boolean isTemplateNameFormatExplicitlySet()
setTemplateNameFormat(TemplateNameFormat)
(or equivalent) was already called on this instance.public TemplateNameFormat getTemplateNameFormat()
setTemplateNameFormat(TemplateNameFormat)
.public void setCacheStorage(CacheStorage cacheStorage)
CacheStorage
used for caching Template
-s;
the earlier content of the template cache will be dropt.
The default is a SoftCacheStorage
. If the total size of the Template
objects is significant but most templates are used rarely, using a
MruCacheStorage
instead might be advisable. If you don't want caching at
all, use NullCacheStorage
(you can't use null
).
Note that setting the cache storage will re-create the template cache, so all its content will be lost.
public void unsetCacheStorage()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isCacheStorageExplicitlySet()
will return false
.public boolean isCacheStorageExplicitlySet()
setCacheStorage(CacheStorage)
(or equivalent) was already called on this instance.public CacheStorage getCacheStorage()
setCacheStorage(CacheStorage)
.public void setDirectoryForTemplateLoading(File dir) throws IOException
setTemplateLoader(new FileTemplateLoader(dir))
,
so see FileTemplateLoader.FileTemplateLoader(File)
for more details.
Note that FreeMarker can load templates from non-file-system sources too.
See setTemplateLoader(TemplateLoader)
from more details.IOException
public void setServletContextForTemplateLoading(Object servletContext, String path)
setTemplateLoader(new WebappTemplateLoader(sctxt, path))
or setTemplateLoader(new WebappTemplateLoader(sctxt))
if path
was
null
, so see freemarker.cache.WebappTemplateLoader
for more details.servletContext
- the javax.servlet.ServletContext
object. (The declared type is Object
to prevent class loading error when using FreeMarker in an environment where
there's no servlet classes available.)path
- the path relative to the ServletContext.setTemplateLoader(TemplateLoader)
public void setClassForTemplateLoading(Class resourceLoaderClass, String basePackagePath)
Class.getResource(String)
method will be used to load templates, from the inside the
package specified. See ClassTemplateLoader.ClassTemplateLoader(Class, String)
for more details.basePackagePath
- Separate steps with "/"
, not "."
, and note that it matters if this starts with
/
or not. See ClassTemplateLoader.ClassTemplateLoader(Class, String)
for more details.setClassLoaderForTemplateLoading(ClassLoader, String)
,
setTemplateLoader(TemplateLoader)
public void setClassLoaderForTemplateLoading(ClassLoader classLoader, String basePackagePath)
ClassLoader
whose ClassLoader.getResource(String)
method will be used to load templates,
from the inside the package specified. See ClassTemplateLoader.ClassTemplateLoader(Class, String)
for
more details.basePackagePath
- Separate steps with "/"
, not "."
. See
ClassTemplateLoader.ClassTemplateLoader(Class, String)
for more details.setClassForTemplateLoading(Class, String)
,
setTemplateLoader(TemplateLoader)
public void setTemplateUpdateDelay(int seconds)
Historical note: Despite what the API documentation said earlier, this method is not thread-safe. While it works well on most hardware, it's not guaranteed that FreeMarker will see the update in all threads, and theoretically it's also possible that it will see a value that's a binary mixture of the new and the old one.
public void setStrictSyntaxMode(boolean b)
true
(the default) value will be supported sometimes in the future.if
, else
, etc must be written as #if
, #else
, etc.
Defaults to true
.
When this is true
,
any tag not starting with <# or </# or <@ or </@ is considered as plain text
and will go to the output as is. Tag starting with <# or </# must
be valid FTL tag, or else the template is invalid (i.e. <#noSuchDirective>
is an error).
public void setObjectWrapper(ObjectWrapper objectWrapper)
Configurable
TemplateModel
-s.
The default is ObjectWrapper.DEFAULT_WRAPPER
.setObjectWrapper
in class Configurable
public void unsetObjectWrapper()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isObjectWrapperExplicitlySet()
will return false
.public boolean isObjectWrapperExplicitlySet()
setObjectWrapper(ObjectWrapper)
(or equivalent) was already called on this instance.public void setTemplateExceptionHandler(TemplateExceptionHandler templateExceptionHandler)
Configurable
TemplateExceptionHandler.DEBUG_HANDLER
. The recommended values are:
TemplateExceptionHandler.RETHROW_HANDLER
TemplateExceptionHandler.HTML_DEBUG_HANDLER
TemplateExceptionHandler.DEBUG_HANDLER
All of these will let the exception propagate further, so that you can catch it around
Template.process(Object, Writer)
for example. The difference is in what they print on the output before
they do that.
Note that the TemplateExceptionHandler
is not meant to be used for generating HTTP error pages.
Neither is it meant to be used to roll back the printed output. These should be solved outside template
processing when the exception raises from Template.process
.
TemplateExceptionHandler
meant to be used if you want to include special content in the template
output, or if you want to suppress certain exceptions.
setTemplateExceptionHandler
in class Configurable
public void unsetTemplateExceptionHandler()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isTemplateExceptionHandlerExplicitlySet()
will return false
.public boolean isTemplateExceptionHandlerExplicitlySet()
setTemplateExceptionHandler(TemplateExceptionHandler)
(or equivalent) was already called on
this instance.public void setLogTemplateExceptions(boolean value)
Configurable
TemplateException
-s thrown by template processing are logged by FreeMarker or not. The
default is true
for backward compatibility, but that results in logging the exception twice in properly
written applications, because there the TemplateException
thrown by the public FreeMarker API is also
logged by the caller (even if only as the cause exception of a higher level exception). Hence, in modern
applications it should be set to false
. Note that this setting has no effect on the logging of exceptions
caught by #attempt
; those are always logged, no mater what (because those exceptions won't bubble up
until the API caller).setLogTemplateExceptions
in class Configurable
public void unsetLogTemplateExceptions()
incompatibe_improvements
setting later, the default will also change as appropriate. Also
isTemplateExceptionHandlerExplicitlySet()
will return false
.public boolean isLogTemplateExceptionsExplicitlySet()
setLogTemplateExceptions(boolean)
(or equivalent) was already called on this instance.public boolean getStrictSyntaxMode()
setStrictSyntaxMode(boolean)
.public void setIncompatibleImprovements(Version incompatibleImprovements)
Configuration(Version)
instead if possible; see the meaning of the parameter there.
If the default value of a setting depends on the incompatibleImprovements
and the value of that setting
was never set in this Configuration
object through the public API, its value will be set to the default
value appropriate for the new incompatibleImprovements
. (This adjustment of a setting value doesn't
count as setting that setting, so setting incompatibleImprovements
for multiple times also works as
expected.) Note that if the template_loader
have to be changed because of this, the template cache will
be emptied.IllegalArgumentException
- If incompatibleImmprovements
refers to a version that wasn't released yet when the currently
used FreeMarker version was released, or is less than 2.3.0, or is null
.public Version getIncompatibleImprovements()
null
.setIncompatibleImprovements(Version)
public void setIncompatibleEnhancements(String version)
Configuration(Version)
, or
as last chance, setIncompatibleImprovements(Version)
instead.public String getIncompatibleEnhancements()
getIncompatibleImprovements()
instead.public int getParsedIncompatibleEnhancements()
getIncompatibleImprovements()
instead.public void setWhitespaceStripping(boolean b)
public boolean getWhitespaceStripping()
setWhitespaceStripping(boolean)
public void setTagSyntax(int tagSyntax)
#ftl
in it. The tagSyntax
parameter must be one of:
AUTO_DETECT_TAG_SYNTAX
:
use the syntax of the first FreeMarker tag (can be anything, like #list,
#include, user defined, etc.)
ANGLE_BRACKET_TAG_SYNTAX
:
use the angle bracket syntax (the normal syntax)
SQUARE_BRACKET_TAG_SYNTAX
:
use the square bracket syntax
In FreeMarker 2.3.x ANGLE_BRACKET_TAG_SYNTAX
is the
default for better backward compatibility. Starting from 2.4.x AUTO_DETECT_TAG_SYNTAX
is the default, so it's recommended to use
that even for 2.3.x.
This setting is ignored for the templates that have ftl
directive in
it. For those templates the syntax used for the ftl
directive determines
the syntax.
public int getTagSyntax()
setTagSyntax(int)
.public Template getTemplate(String name) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
This is a shorthand for getTemplate(name, null, null, null, true, false)
; see more details there.
See Configuration
for an example of basic usage.
public Template getTemplate(String name, Locale locale) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
getTemplate(name, locale, null, null, true, false)
.public Template getTemplate(String name, String encoding) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
getTemplate(name, null, null, encoding, true, false)
.public Template getTemplate(String name, Locale locale, String encoding) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
getTemplate(name, locale, null, encoding, true, false)
.public Template getTemplate(String name, Locale locale, String encoding, boolean parseAsFTL) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
getTemplate(name, locale, null, encoding, parseAsFTL, false)
.public Template getTemplate(String name, Locale locale, String encoding, boolean parseAsFTL, boolean ignoreMissing) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
TemplateNotFoundException
MalformedTemplateNameException
ParseException
IOException
public Template getTemplate(String name, Locale locale, Object customLookupCondition, String encoding, boolean parseAsFTL, boolean ignoreMissing) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException
This method is thread-safe.
See Configuration
for an example of basic usage.
name
- The name or path of the template, which is not a real path, but interpreted inside the current
TemplateLoader
. Can't be null
. The exact syntax of the name depends on the underlying
TemplateLoader
, but the cache makes some assumptions. First, the name is expected to be a
hierarchical path, with path components separated by a slash character (not with backslash!). The path
(the name) given here must not begin with slash; it's always interpreted relative to the
"template root directory". Then, the ..
and .
path meta-elements will be resolved. For
example, if the name is a/../b/./c.ftl
, then it will be simplified to b/c.ftl
. The
rules regarding this are the same as with conventional UN*X paths. The path must not reach outside the
template root directory, that is, it can't be something like "../templates/my.ftl"
(not even
if this path happens to be equivalent with "/my.ftl"
). Furthermore, the path is allowed to
contain at most one path element whose name is *
(asterisk). This path meta-element triggers
the acquisition mechanism. If the template is not found in the location described by the
concatenation of the path left to the asterisk (called base path) and the part to the right of the
asterisk (called resource path), the cache will attempt to remove the rightmost path component from
the base path ("go up one directory") and concatenate that with the resource path. The process is
repeated until either a template is found, or the base path is completely exhausted.locale
- The requested locale of the template. Can be null
since 2.3.22, in which case it defaults
Configurable.getLocale()
. Assuming that you have specified en_US
as the locale and
myTemplate.ftl
as the name of the template, and the default TemplateLookupStrategy
is
used and #setLocalizedLookup(boolean) localized_lookup
is true
, FreeMarker will first
try to retrieve myTemplate_en_US.html
, then myTemplate.en.ftl
, and finally
myTemplate.ftl
.customLookupCondition
- This value can be used by a custom TemplateLookupStrategy
; has no effect with the default one.
Can be null
(though it's up to the custom TemplateLookupStrategy
if it allows that).
This object will be used as part of a cache key, so it must to have a proper
Object.equals(Object)
and Object.hashCode()
method. It also should have reasonable
Object.toString()
, as it's possibly quoted in error messages. The expected type is up to the
custom TemplateLookupStrategy
. See also:
TemplateLookupContext.getCustomLookupCondition()
.encoding
- The charset used to interpret the template source code bytes (if it's read from a binary source). Can
be null
since 2.3.22, will default to getEncoding(Locale)
where
Locale
is the locale
parameter (when locale
was null
too, the its
default value is used instead).parseAsFTL
- If true
, the loaded template is parsed and interpreted normally, as a regular FreeMarker
template. If false
, the loaded template is treated as a static text, so ${...}
,
<#...>
etc. will not have special meaning in it.ignoreMissing
- If true
, the method won't throw TemplateNotFoundException
if the template doesn't
exist, instead it returns null
. Other kind of exceptions won't be suppressed.null
when the ignoreMissing
parameter is true
.TemplateNotFoundException
- If the template could not be found. Note that this exception extends IOException
.MalformedTemplateNameException
- If the template name given was in violation with the TemplateNameFormat
in use. Note that
this exception extends IOException
.ParseException
- (extends IOException
) if the template is syntactically bad. Note that this exception
extends IOException
.IOException
- If there was some other problem with reading the template "file". Note that the other exceptions
extend IOException
, so this should be catched the last.public void setDefaultEncoding(String encoding)
setEncoding(Locale, String)
. Note that by default there is no locale specified for
any locale, so the default encoding is always in effect.
Defaults to the default system encoding, which can change from one server to
another, so you should always set this setting. If you don't know what charset your should chose,
"UTF-8"
is usually a good choice.
Note that individual templates may specify their own charset by starting with <#ftl encoding="...">
encoding
- The name of the charset, such as "UTF-8"
or "ISO-8859-1"
public String getDefaultEncoding()
public String getEncoding(Locale locale)
setEncoding(Locale, String)
or loadBuiltInEncodingMap()
.public void setEncoding(Locale locale, String encoding)
setDefaultEncoding(java.lang.String)
.clearEncodingMap()
,
loadBuiltInEncodingMap()
public void setSharedVariable(String name, TemplateModel tm)
Never use TemplateModel implementation that is not thread-safe for shared sharedVariables, if the configuration is used by multiple threads! It is the typical situation for Servlet based Web sites.
This method is not thread safe; use it with the same restrictions as those that modify setting values.
name
- the name used to access the data object from your template.
If a shared variable with this name already exists, it will replace
that.setAllSharedVariables(freemarker.template.TemplateHashModelEx)
,
setSharedVariable(String,Object)
public Set getSharedVariableNames()
public void setSharedVariable(String name, Object value) throws TemplateModelException
Configurable.getObjectWrapper()
to wrap the
value
, so it's important that the object wrapper is set before this.
This method is not thread safe; use it with the same restrictions as those that modify setting values.
The added value should be thread safe, if you are running templates from multiple threads with this configuration.
TemplateModelException
- If some of the variables couldn't be wrapped via Configurable.getObjectWrapper()
.setSharedVaribles(Map)
,
setSharedVariable(String,TemplateModel)
,
setAllSharedVariables(TemplateHashModelEx)
public void setSharedVaribles(Map map) throws TemplateModelException
The values in the map can be TemplateModel
-s or plain Java objects which will be immediately converted
to TemplateModel
with the ObjectWrapper
returned by Configurable.getObjectWrapper()
. If
setObjectWrapper(ObjectWrapper)
is called later, this conversion will be re-applied. Thus, ignoring some
extra resource usage, it doesn't mater if in what order are setObjectWrapper(ObjectWrapper)
and
setSharedVaribles(Map)
called. This is essential when you don't have control over the order in which
the setters are called.
The values in the map must be thread safe, if you are running templates from multiple threads with
this configuration. This means that both the plain Java object and the TemplateModel
-s created from them
by the ObjectWrapper
must be thread safe. (The standard ObjectWrapper
-s of FreeMarker create
thread safe TemplateModel
-s.) The Map
itself need not be thread-safe.
This setter method has no getter pair because of the tricky relation ship with
setSharedVariable(String, Object)
.
TemplateModelException
- If some of the variables couldn't be wrapped via Configurable.getObjectWrapper()
.public void setAllSharedVariables(TemplateHashModelEx hash) throws TemplateModelException
setSharedVariable(String, Object)
calls, one for each hash entry. It doesn't remove the already added
shared variable before doing this.
Never use TemplateModel implementation that is not thread-safe for shared shared variable values, if the configuration is used by multiple threads! It is the typical situation for Servlet based Web sites.
This method is not thread safe; use it with the same restrictions as those that modify setting values.
hash
- a hash model whose objects will be copied to the
configuration with same names as they are given in the hash.
If a shared variable with these names already exist, it will be replaced
with those from the map.TemplateModelException
setSharedVaribles(Map)
,
setSharedVariable(String,Object)
,
setSharedVariable(String,TemplateModel)
public TemplateModel getSharedVariable(String name)
public void clearSharedVariables()
public void clearTemplateCache()
getTemplate
calls.
This method is thread-safe and can be called while the engine processes templates.
public void removeTemplateFromCache(String name) throws IOException
IOException
public void removeTemplateFromCache(String name, Locale locale) throws IOException
IOException
public void removeTemplateFromCache(String name, String encoding) throws IOException
IOException
public void removeTemplateFromCache(String name, Locale locale, String encoding) throws IOException
IOException
public void removeTemplateFromCache(String name, Locale locale, String encoding, boolean parse) throws IOException
setTemplateUpdateDelay(int)
alone does.
For the meaning of the parameters, see
getTemplate(String, Locale, String, boolean)
.
This method is thread-safe and can be called while the engine processes templates.
IOException
public boolean getLocalizedLookup()
setLocalizedLookup(boolean)
.
This method is thread-safe and can be called while the engine works.
public void setLocalizedLookup(boolean localizedLookup)
With the default TemplateLookupStrategy
, localized lookup works like this: Let's say your locale setting
is Locale("en", "AU")
, and you call cfg.getTemplate("foo.ftl")
.
Then FreeMarker will look for the template under these names, stopping at the first that exists:
"foo_en_AU.ftl"
, "foo_en.ftl"
, "foo.ftl"
. See the description of the default value at
setTemplateLookupStrategy(TemplateLookupStrategy)
for a more details. If you need to generate different
template names, use setTemplateLookupStrategy(TemplateLookupStrategy)
with your custom
TemplateLookupStrategy
.
Note that changing the value of this setting causes the template cache to be emptied so that old lookup results won't be reused (since 2.3.22).
Historical note: Despite what the API documentation said earlier, this method is not thread-safe. While setting it can't cause any serious problems, and in fact it works well on most hardware, it's not guaranteed that FreeMarker will see the update in all threads.
public void setSetting(String name, String value) throws TemplateException
Configurable
Configurable.setObjectWrapper(ObjectWrapper)
. This meant to be used if you get the settings from somewhere
as text. Regardless, below you will find an overview of the settings available no matter how you set them.
The list of settings commonly supported in all Configurable
subclasses:
"locale"
:
See Configurable.setLocale(Locale)
.
String value: local codes with the usual format in Java, such as "en_US"
.
"classic_compatible"
:
See Configurable.setClassicCompatible(boolean)
and Configurable.setClassicCompatibleAsInt(int)
.
String value: "true"
, "false"
, also since 2.3.20 0
or 1
or 2
.
(Also accepts "yes"
, "no"
, "t"
, "f"
, "y"
, "n"
.)
Case insensitive.
"template_exception_handler"
:
See Configurable.setTemplateExceptionHandler(TemplateExceptionHandler)
.
String value: If the value contains dot, then it's interpreted as an object builder
expression.
If the value does not contain dot, then it must be one of these predefined values (case insensitive):
"rethrow"
(means TemplateExceptionHandler.RETHROW_HANDLER
),
"debug"
(means TemplateExceptionHandler.DEBUG_HANDLER
),
"html_debug"
(means TemplateExceptionHandler.HTML_DEBUG_HANDLER
),
"ignore"
(means TemplateExceptionHandler.IGNORE_HANDLER
),
"default"
(only allowed for Configuration
instances) for the default.
"arithmetic_engine"
:
See Configurable.setArithmeticEngine(ArithmeticEngine)
.
String value: If the value contains dot, then it's interpreted as an object builder
expression.
If the value does not contain dot,
then it must be one of these special values (case insensitive):
"bigdecimal"
, "conservative"
.
"object_wrapper"
:
See Configurable.setObjectWrapper(ObjectWrapper)
.
String value: If the value contains dot, then it's interpreted as an object builder
expression, with the addition that BeansWrapper
, DefaultObjectWrapper
and
SimpleObjectWrapper
can be referred without package name. For example, these strings are valid
values: "DefaultObjectWrapper(2.3.21)"
,
"BeansWrapper(2.3.21, simpleMapWrapper=true)"
.
If the value does not contain dot, then it must be one of these special values (case insensitive):
"default"
means the default of Configuration
(the default depends on the
Configuration#Configuration(Version) incompatible_improvements
, but a bug existed in 2.3.21 where
that was ignored),
"default_2_3_0"
(means the deprecated ObjectWrapper.DEFAULT_WRAPPER
)
"simple"
(means the deprecated ObjectWrapper.SIMPLE_WRAPPER
),
"beans"
(means the deprecated ObjectWrapper.BEANS_WRAPPER
or BeansWrapperBuilder.build()
),
"jython"
(means ObjectWrapper.DEFAULT_WRAPPER
)
"number_format"
: See Configurable.setNumberFormat(String)
.
"boolean_format"
: See Configurable.setBooleanFormat(String)
.
"date_format", "time_format", "datetime_format"
:
See Configurable.setDateFormat(String)
, Configurable.setTimeFormat(String)
, Configurable.setDateTimeFormat(String)
.
"time_zone"
:
See Configurable.setTimeZone(TimeZone)
.
String value: With the format as TimeZone.getTimeZone(java.lang.String)
defines it. Also, since 2.3.21
"JVM default"
can be used that will be replaced with the actual JVM default time zone when
Configurable.setSetting(String, String)
is called.
For example "GMT-8:00"
or "America/Los_Angeles"
If you set this setting, consider setting sql_date_and_time_time_zone
too (see below)!
sql_date_and_time_time_zone
:
See Configurable.setSQLDateAndTimeTimeZone(TimeZone)
.
Since 2.3.21.
String value: With the format as TimeZone.getTimeZone(java.lang.String)
defines it. Also, "JVM default"
can be used that will be replaced with the actual JVM default time zone when
Configurable.setSetting(String, String)
is called. Also "null"
can be used, which has the same effect
as setSQLDateAndTimeTimeZone(null)
.
"output_encoding"
:
See Configurable.setOutputEncoding(String)
.
"url_escaping_charset"
:
See Configurable.setURLEscapingCharset(String)
.
"auto_flush"
:
See Configurable.setAutoFlush(boolean)
.
Since 2.3.17.
String value: "true"
, "false"
, "y"
, etc.
"new_builtin_class_resolver"
:
See Configurable.setNewBuiltinClassResolver(TemplateClassResolver)
.
Since 2.3.17.
The value must be one of these (ignore the quotation marks):
"unrestricted"
:
Use TemplateClassResolver.UNRESTRICTED_RESOLVER
"safer"
:
Use TemplateClassResolver.SAFER_RESOLVER
"allows_nothing"
:
Use TemplateClassResolver.ALLOWS_NOTHING_RESOLVER
Something that contains colon will use
OptInTemplateClassResolver
and is expected to
store comma separated values (possibly quoted) segmented
with "allowed_classes:"
and/or
"trusted_templates:"
. Examples of valid values:
Setting value | Meaning |
---|---|
allowed_classes: com.example.C1, com.example.C2,
trusted_templates: lib/*, safe.ftl
|
Only allow instantiating the com.example.C1 and
com.example.C2 classes. But, allow templates
within the lib/ directory (like
lib/foo/bar.ftl ) and template safe.ftl
(that does not match foo/safe.ftl , only
exactly safe.ftl ) to instantiate anything
that TemplateClassResolver.SAFER_RESOLVER allows.
|
allowed_classes: com.example.C1, com.example.C2
| Only allow instantiating the com.example.C1 and
com.example.C2 classes. There are no
trusted templates.
|
trusted_templates: lib/*, safe.ftl
|
Do not allow instantiating any classes, except in
templates inside lib/ or in template
safe.ftl .
|
For more details see OptInTemplateClassResolver
.
Otherwise if the value contains dot, it's interpreted as an object builder expression.
"show_error_tips"
:
See Configurable.setShowErrorTips(boolean)
.
Since 2.3.21.
String value: "true"
, "false"
, "y"
, etc.
api_builtin_enabled
:
See Configurable.setAPIBuiltinEnabled(boolean)
.
Since 2.3.22.
String value: "true"
, "false"
, "y"
, etc.
Configuration
(a subclass of Configurable
) also understands these:
"auto_import"
:
See setAutoImports(Map)
String value is something like:
/lib/form.ftl as f, /lib/widget as w, "/lib/odd name.ftl" as odd
"auto_include"
: Sets the list of auto-includes.
See setAutoIncludes(List)
String value is something like:
/include/common.ftl, "/include/evil name.ftl"
"default_encoding"
:
See setDefaultEncoding(String)
.
As the default value is the system default, which can change
from one server to another, you should always set this!
"localized_lookup"
:
See setLocalizedLookup(boolean)
.
String value: "true"
, "false"
(also the equivalents: "yes"
, "no"
,
"t"
, "f"
, "y"
, "n"
).
Case insensitive.
"strict_syntax"
:
See setStrictSyntaxMode(boolean)
. Deprecated.
String value: "true"
, "false"
, yes
, etc.
"whitespace_stripping"
:
See setWhitespaceStripping(boolean)
.
String value: "true"
, "false"
, yes
, etc.
"cache_storage"
:
See setCacheStorage(freemarker.cache.CacheStorage)
.
String value: If the value contains dot, then it's interpreted as an object builder
expression.
If the value does not contain dot,
then a MruCacheStorage
will be used with the
maximum strong and soft sizes specified with the setting value. Examples
of valid setting values:
Setting value | max. strong size | max. soft size |
---|---|---|
"strong:50, soft:500" | 50 | 500 |
"strong:100, soft" | 100 | Integer.MAX_VALUE
|
"strong:100" | 100 | 0 |
"soft:100" | 0 | 100 |
"strong" | Integer.MAX_VALUE | 0 |
"soft" | 0 | Integer.MAX_VALUE
|
The value is not case sensitive. The order of soft and strong entries is not significant.
"template_update_delay"
:
See setTemplateUpdateDelay(int)
.
String value: Valid positive integer, the update delay measured in seconds.
"tag_syntax"
:
See setTagSyntax(int)
.
String value: Must be one of
"auto_detect"
, "angle_bracket"
, and "square_bracket"
.
"incompatible_improvements"
:
See setIncompatibleImprovements(Version)
.
String value: version number like 2.3.20
.
"incompatible_enhancements"
:
See: setIncompatibleEnhancements(String)
.
This setting name is deprecated, use "incompatible_improvements"
instead.
"template_loader"
:
See: setTemplateLoader(TemplateLoader)
.
String value: "default"
(case insensitive) for the default, or else interpreted as an
object builder expression.
"template_lookup_strategy"
:
See: setTemplateLookupStrategy(freemarker.cache.TemplateLookupStrategy)
.
String value: "default"
(case insensitive) for the default, or else interpreted as an
object builder expression.
"template_name_format"
:
See: setTemplateNameFormat(freemarker.cache.TemplateNameFormat)
.
String value: "default"
(case insensitive) for the default, "default_2_3_0"
for TemplateNameFormat.DEFAULT_2_3_0
, "default_2_4_0"
for
TemplateNameFormat.DEFAULT_2_4_0
.
Regarding object builder expressions (used by the setting values where it was indicated):
Before FreeMarker 2.3.21 it had to be a fully qualified class name, and nothing else.
Since 2.3.21, the generic syntax is: className(constrArg1, constrArg2, ... constrArgN, propName1=propValue1, propName2=propValue2, ... propNameN=propValueN), where className is the fully qualified class name of the instance to create (except if we have builder class or INSTANCE field around, but see that later), constrArg-s are the values of constructor arguments, and propName=propValue-s set JavaBean properties (like x=1 means setX(1)) on the created instance. You can have any number of constructor arguments and property setters, including 0. Constructor arguments must precede any property setters.
If you have no constructor arguments and property setters, and the className class has
a public static 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 INSTANCE
.
If there exists a class named classNameBuilder, 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 build() method of the instance will be called, whose return value will be the value of the whole expression. (The builder class and the build() 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.
Currently, the values of arguments and properties can only be one of these:
123
or -1.5
. Like in FTL, there are no numerical types,
the value will be automatically converted to the type of the target.true
or false
null
"Line 1\nLine 2"
or r"C:\temp"
.
The top-level object builder expressions may omit ()
. In that case, for backward compatibility,
the 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 ()
can't be omitted for nested expressions.
The classes and methods that the expression meant to access must be all public.
setSetting
in class Configurable
name
- the name of the setting.value
- the string that describes the new value of the setting.Configurable.UnknownSettingException
- if the name is wrong.TemplateException
- if the new value of the setting can't be set for any other reasons.protected String getCorrectedNameForUnknownSetting(String name)
getCorrectedNameForUnknownSetting
in class Configurable
name
- The wrong namenull
if there's no known correctionpublic void addAutoImport(String namespaceVarName, String templateName)
#import templateName as namespaceVarName
at the beginning of all
templates. The order of the imports will be the same as the order in which they were added with this method.public void removeAutoImport(String namespaceVarName)
addAutoImport(String, String)
. Does nothing if the auto-import doesn't
exist.public void setAutoImports(Map map)
addAutoImport(String, String)
for each Map
-entry (the entry
key is the namespaceVarName
). The order of the auto-imports will be the same as Map.keySet()
returns the keys, thus, it's not the best idea to use a HashMap
(although the order of imports doesn't
mater for properly designed libraries).protected void doAutoImportsAndIncludes(Environment env) throws TemplateException, IOException
doAutoImportsAndIncludes
in class Configurable
TemplateException
IOException
public void addAutoInclude(String templateName)
#include templateName as namespaceVarName
at the beginning of all
templates. The order of the inclusions will be the same as the order in which they were added with this method.public void setAutoIncludes(List templateNames)
addAutoInclude(String)
for each List
items.public void removeAutoInclude(String templateName)
addAutoInclude(String)
. Does nothing if the template
is not there.public static String getVersionNumber()
getVersion()
instead.public static Version getVersion()
public static ObjectWrapper getDefaultObjectWrapper(Version incompatibleImprovements)
setIncompatibleImprovements(Version)
public Set getSupportedBuiltInNames()
expr?builtin_name
-like things). As of this
writing, this information doesn't depend on the configuration options, so it could be a static method, but
to be future-proof, it's an instance method.