public class DefaultObjectWrapper extends BeansWrapper
ObjectWrapper interface. Usually, you don't need to create instances of
this, as an instance of this is already the default value of the
object_wrapper setting. Then the
incompatibleImprovements of the DefaultObjectWrapper will be the same
that you have set for the Configuration itself. As of this writing, it's highly recommended to use
incompatibleImprovements 2.3.22 (or higher).
If you still need to create an instance, that should be done with an DefaultObjectWrapperBuilder (or
with Configuration.setSetting(String, String) with "object_wrapper" key), not with
its constructor, as that allows FreeMarker to reuse singletons. For new projects, it's recommended to set
forceLegacyNonListCollections to
false, and iterableSupport to true;
setting incompatibleImprovements to 2.3.22 won't do these, as they could break legacy templates too easily.
This class is only thread-safe after you have finished calling its setter methods, and then safely published it (see
JSR 133 and related literature). When used as part of Configuration, of course it's enough if that was safely
published and then left unmodified.
BeansWrapper.MethodAppearanceDecision, BeansWrapper.MethodAppearanceDecisionInputEXPOSE_ALL, EXPOSE_NOTHING, EXPOSE_PROPERTIES_ONLY, EXPOSE_SAFECANT_UNWRAP_TO_TARGET_CLASSBEANS_WRAPPER, DEFAULT_WRAPPER, SIMPLE_WRAPPER| Modifier | Constructor and Description |
|---|---|
|
DefaultObjectWrapper()
Deprecated.
Use
DefaultObjectWrapperBuilder, or in rare cases,
DefaultObjectWrapper(Version) instead. |
protected |
DefaultObjectWrapper(BeansWrapperConfiguration bwCfg,
boolean writeProtected)
Use
DefaultObjectWrapper(DefaultObjectWrapperConfiguration, boolean) instead if possible;
it does the same, except that it tolerates a non-DefaultObjectWrapperConfiguration configuration too. |
protected |
DefaultObjectWrapper(DefaultObjectWrapperConfiguration dowCfg,
boolean writeProtected)
Calls
BeansWrapper.BeansWrapper(BeansWrapperConfiguration, boolean) and sets up
DefaultObjectWrapper-specific fields. |
|
DefaultObjectWrapper(Version incompatibleImprovements)
Use
DefaultObjectWrapperBuilder instead if possible. |
| Modifier and Type | Method and Description |
|---|---|
protected java.lang.Object |
convertArray(java.lang.Object arr)
Converts an array to a java.util.List.
|
boolean |
getDOMNodeSupport()
Getter pair of
setDOMNodeSupport(boolean); see there. |
boolean |
getForceLegacyNonListCollections()
Getter pair of
setForceLegacyNonListCollections(boolean); see there. |
boolean |
getIterableSupport()
Getter pair of
setIterableSupport(boolean); see there. |
boolean |
getJythonSupport()
Getter pair of
setJythonSupport(boolean); see there. |
boolean |
getUseAdaptersForContainers()
The getter pair of
setUseAdaptersForContainers(boolean). |
protected TemplateModel |
handleUnknownType(java.lang.Object obj)
Called for an object that isn't considered to be of a "basic" Java type, like for an application specific type,
or for a W3C DOM node.
|
protected static Version |
normalizeIncompatibleImprovementsVersion(Version incompatibleImprovements)
Returns the lowest version number that is equivalent with the parameter version.
|
void |
setDOMNodeSupport(boolean domNodeSupport)
Enables wrapping
Node-s on a special way (as described in the "XML Processing Guide" in the Manual);
defaults to true.. |
void |
setForceLegacyNonListCollections(boolean forceLegacyNonListCollections)
Specifies whether non-
List Collection-s (like Set-s) must be wrapped by pre-fetching into
a SimpleSequence. |
void |
setIterableSupport(boolean iterableSupport)
Specifies whether
Iterable-s (not to be confused with Iterator-s) that don't implement any other
recognized Java interfaces (most notably Collection) will be recognized as listable objects
(TemplateCollectionModel-s), or they will be just seen as generic objects (JavaBean-s). |
void |
setJythonSupport(boolean jythonSupport)
Enables wrapping Jython objects in a special way; defaults to
true. |
void |
setUseAdaptersForContainers(boolean useAdaptersForContainers)
Sets if to wrap container objects (
Map-s, List-s, arrays and such) the legacy copying approach or
the newer adapter approach should be used. |
protected java.lang.String |
toPropertiesString()
Returns the name-value pairs that describe the configuration of this
BeansWrapper; called from
BeansWrapper.toString(). |
TemplateModel |
wrap(java.lang.Object obj)
Wraps the parameter object to
TemplateModel interface(s). |
TemplateModel |
wrapDomNode(java.lang.Object obj) |
checkModifiable, clearClassIntrospecitonCache, clearClassIntrospectionCache, coerceBigDecimal, coerceBigDecimals, coerceBigDecimals, finalizeConstruction, finetuneMethodAppearance, getDefaultDateType, getDefaultInstance, getEnumModels, getExposureLevel, getIncompatibleImprovements, getInstance, getMemberAccessPolicy, getMethodAppearanceFineTuner, getModelFactory, getOuterIdentity, getPreferIndexedReadMethod, getStaticModels, getTreatDefaultMethodsAsBeanMembers, getUseCache, invokeMethod, isClassIntrospectionCacheRestricted, isExposeFields, isSimpleMapWrapper, isStrict, isWriteProtected, newInstance, readField, removeFromClassIntrospectionCache, setDefaultDateType, setExposeFields, setExposureLevel, setMemberAccessPolicy, setMethodAppearanceFineTuner, setMethodsShadowItems, setNullModel, setOuterIdentity, setPreferIndexedReadMethod, setSimpleMapWrapper, setStrict, setTreatDefaultMethodsAsBeanMembers, setUseCache, toString, tryUnwrapTo, unwrap, unwrap, wrap, wrapAsAPI, writeProtect@Deprecated public DefaultObjectWrapper()
DefaultObjectWrapperBuilder, or in rare cases,
DefaultObjectWrapper(Version) instead.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS.public DefaultObjectWrapper(Version incompatibleImprovements)
DefaultObjectWrapperBuilder instead if possible. Instances created with this constructor won't share
the class introspection caches with other instances. See BeansWrapper.BeansWrapper(Version) (the
superclass constructor) for more details.incompatibleImprovements - It's the same as in BeansWrapper.BeansWrapper(Version), plus these changes:
useAdaptersForContainers changes to
true.Iterator, operations on it that only check if the
collection is empty without reading an element from it, such as ?has_content,
won't cause the a later iteration (or further emptiness check) to fail anymore. Earlier, in
certain situations, the second operation has failed saying that the iterator "can be listed only
once".
Enumeration-s are wrapped into DefaultEnumerationAdapter
instead of into EnumerationModel (as far as
useAdaptersForContainers is true, which is
the default). This adapter is cleaner than EnumerationModel as it only implements the
minimally required FTL type, which avoids some ambiguous situations. (Note that Java API methods
aren't exposed anymore as subvariables; if you really need them, you can use ?api).
protected DefaultObjectWrapper(BeansWrapperConfiguration bwCfg, boolean writeProtected)
DefaultObjectWrapper(DefaultObjectWrapperConfiguration, boolean) instead if possible;
it does the same, except that it tolerates a non-DefaultObjectWrapperConfiguration configuration too.protected DefaultObjectWrapper(DefaultObjectWrapperConfiguration dowCfg, boolean writeProtected)
BeansWrapper.BeansWrapper(BeansWrapperConfiguration, boolean) and sets up
DefaultObjectWrapper-specific fields.public TemplateModel wrap(java.lang.Object obj) throws TemplateModelException
TemplateModel interface(s). Simple types like numbers, strings, booleans
and dates will be wrapped into the corresponding SimpleXxx classes (like SimpleNumber).
Map-s, List-s, other Collection-s, arrays and Iterator-s will be wrapped into the
corresponding SimpleXxx or DefaultXxxAdapter classes (like SimpleHash or
DefaultMapAdapter), depending on getUseAdaptersForContainers() and
getForceLegacyNonListCollections(). After that, the wrapping is handled by
handleUnknownType(Object), so see more there.wrap in interface ObjectWrapperwrap in class BeansWrapperobj - The object to wrap into a TemplateModel. If it already implements TemplateModel,
it should just return the object as is. If it's null, the method should return null
(however, BeansWrapper, has a legacy option for returning a null model object instead, but it's not
a good idea).TemplateModel wrapper of the object passed in. To support un-wrapping, you may consider the
return value to implement WrapperTemplateModel and AdapterTemplateModel.
The default expectation is that the TemplateModel isn't less thread safe than the wrapped object.
If the ObjectWrapper returns less thread safe objects, that should be clearly documented, as it
restricts how it can be used, like, then it can't be used to wrap "shared variables"
(Configuration.setSharedVaribles(Map)).TemplateModelExceptionprotected TemplateModel handleUnknownType(java.lang.Object obj) throws TemplateModelException
Node-s will be wrapped as NodeModel-s
(allows DOM tree traversal), Jython objects will be delegated to the JythonWrapper, others will be
wrapped using BeansWrapper.wrap(Object). However, these can be turned off with the
setDOMNodeSupport(boolean) and setJythonSupport(boolean). Note that if
BeansWrapper.getMemberAccessPolicy() doesn't return a DefaultMemberAccessPolicy or
LegacyDefaultMemberAccessPolicy, then Jython wrapper will be skipped for security reasons.
When you override this method, you should first decide if you want to wrap the object in a custom way (and if so then do it and return with the result), and if not, then you should call the super method (assuming the default behavior is fine with you).
TemplateModelExceptionpublic TemplateModel wrapDomNode(java.lang.Object obj)
protected java.lang.Object convertArray(java.lang.Object arr)
public boolean getUseAdaptersForContainers()
setUseAdaptersForContainers(boolean).public void setUseAdaptersForContainers(boolean useAdaptersForContainers)
Map-s, List-s, arrays and such) the legacy copying approach or
the newer adapter approach should be used. true is recommended, which is also the default when the
incompatible_improvements of this instance was set to Configuration.VERSION_2_3_22 or higher. To
understand the difference, check some of the classes that implement the two approaches:
SimpleHash, SimpleSequenceDefaultMapAdapter, DefaultListAdapter, DefaultArrayAdapter,
DefaultIteratorAdapterSee also the related Version History entry under 2.3.22 in the FreeMarker Manual, which gives a breakdown of the consequences.
Attention: For backward compatibility, currently, non-List collections (like Set-s) will
only be wrapped with adapter approach (with DefaultNonListCollectionAdapter) if
forceLegacyNonListCollections was set to false.
Currently the default is true, but in new projects you should set it to false. See
setForceLegacyNonListCollections(boolean) for more.
setForceLegacyNonListCollections(boolean)public boolean getForceLegacyNonListCollections()
setForceLegacyNonListCollections(boolean); see there.public void setForceLegacyNonListCollections(boolean forceLegacyNonListCollections)
List Collection-s (like Set-s) must be wrapped by pre-fetching into
a SimpleSequence. The modern approach is wrapping into a DefaultNonListCollectionAdapter. This
setting only has effect when getUseAdaptersForContainers() is also true, as otherwise
SimpleSequence will be used regardless of this. In new projects you should set this to false. At
least before incompatible_improvements 2.4.0 it defaults to true, because of backward
compatibility concerns: with TemplateSequenceModel templates could access the items by index if they
wanted to (the index values were defined by the iteration order). This was not very useful, or was even
confusing, and it conflicts with the adapter approach.setUseAdaptersForContainers(boolean)public boolean getIterableSupport()
setIterableSupport(boolean); see there.public void setIterableSupport(boolean iterableSupport)
Iterable-s (not to be confused with Iterator-s) that don't implement any other
recognized Java interfaces (most notably Collection) will be recognized as listable objects
(TemplateCollectionModel-s), or they will be just seen as generic objects (JavaBean-s). Defaults to
false for backward compatibility, but in new projects you should set this to true. Before setting
this to true in older projects, check if you have called myIterable.iterator() directly from any
templates, because the Java API is only exposed to the templates if the Iterable is wrapped as generic
object.public final boolean getDOMNodeSupport()
setDOMNodeSupport(boolean); see there.public void setDOMNodeSupport(boolean domNodeSupport)
Node-s on a special way (as described in the "XML Processing Guide" in the Manual);
defaults to true.. If this is true, Node+s will be wrapped like any other generic object.handleUnknownType(Object)public final boolean getJythonSupport()
setJythonSupport(boolean); see there.public void setJythonSupport(boolean jythonSupport)
true. If this is false, they will
be wrapped like any other generic object. Note that Jython wrapping is legacy feature, and might by disabled by
the selected MemberAccessPolicy, even if this is true; see handleUnknownType(Object).handleUnknownType(Object)protected static Version normalizeIncompatibleImprovementsVersion(Version incompatibleImprovements)
protected java.lang.String toPropertiesString()
BeansWrapperBeansWrapper; called from
BeansWrapper.toString(). The expected format is like "foo=bar, baaz=wombat". When overriding this, you should
call the super method, and then insert the content before it with a following ", ", or after it with a
preceding ", ".toPropertiesString in class BeansWrapper