Using BeansWrapper directly is not
          recommended anymore. Use its subclass,
          DefaultObjectWrapper instead, though by ensuring
          that its incompatibleImprovements property is at
          least 2.3.22. DefaultObjectWrapper gives cleaner
          data-model (less confusing multi-type FTL values) and is usually
          faster. See more
          about DefaultObjectWrapper here...
The freemarker.ext.beans.BeansWrapper is an
        object wrapper
        that was originally added to FreeMarker so arbitrary POJO-s (Plain Old
        Java Objects) can be wrapped into TemplateModel
        interfaces. Since then it has became the normal way of doing things,
        and in fact the DefaultObjectWrapper itself is a
        BeansWrapper extension. So everything described
        here goes for the DefaultObjectWrapper too, except
        that the DefaultObjectWrapper will wrap
        String, Number,
        Date, array,
        Collection (like List),
        Map, Boolean and
        Iterator objects with the
        freemarker.template.SimpleXxx
        classes, and W3C DOM nodes with
        freemarker.ext.dom.NodeModel (more about wrapped W3C DOM...), so for those the
        above described rules doesn't apply.
You will want to use BeansWrapper instead of
        DefaultObjectWrapper when any of these
        stands:
- 
            The Collection-s andMap-s of the model should be allowed to be modified during template execution. (DefaultObjectWrapperprevents that, since it creates a copy of the collections when they are wrapped, and the copies will be read-only.)
- 
            If the identity of the array,CollectionandMapobjects must be kept when they are passed to a wrapped object's method in the template. That is, if those methods must get exactly the same object that was earlier wrapped.
- 
            If the Java API of the earlier listed classes ( String,Map,List...etc) should be visible for the templates. Even withBeansWrapper, they are not visible by default, but it can be achieved by setting the exposure level (see later). Note that this is usually a bad practice; try to use the built-ins (likefoo?size,foo?upper_case,foo?replace('_', '-')...etc) instead of the Java API.
Below is a summary of the TemplateModel-s
        that the BeansWrapper creates. Let's assume that
        the object is called obj before wrapping, and
        model after wrapping for the sake of the following
        discussion.
TemplateHashModel functionality
Every object will be wrapped into a
          TemplateHashModel that will expose JavaBeans
          properties and methods of the object. This way, you can use
          model.foo in the template to invoke
          obj.getFoo() or obj.isFoo()
          methods. (Note that public fields are not visible directly; you must
          write a getter method for them.) Public methods are also retrievable
          through the hash model as template method models, therefore you can
          use the model.doBar() to invoke
          object.doBar(). More on this on discussion of
          method model functionality.
If the requested key can not be mapped to a bean property or
          method, the framework will attempt to locate the so-called "generic
          get method", that is a method with signature public
          any-return-type
          get(String) or public
          any-return-type
          get(Object) and invoke that method with the requested key.
          Note that this allows convenient access to mappings in a
          java.util.Map and similar classes - as long as
          the keys of the map are Strings and some property
          or method name does not shadow the mapping. (There is a solution to
          avoid shadowing, read on.) Also note that the models for
          java.util.ResourceBundle objects use the
          getObject(String) as the generic get
          method.
If you call setExposeFields(true) on a
          BeansWrapper instance, it will also expose
          public, non-static fields of classes as hash keys and values. I.e.
          if foo is a public, non-static field of the class
          Bar, and bar is a template
          variable wrapping an instance of Bar, then
          bar.foo expression will evaluate as the value of
          the field foo of the bar
          object. The public fields in all superclasses of the class are also
          exposed.
A word on security
By default, you will not be able to access several methods
          that are considered not safe for templating. For instance, you can't
          use synchronization methods (wait,
          notify, notifyAll), thread and
          thread group management methods (stop,
          suspend, resume,
          setDaemon, setPriority),
          reflection (Field
          setXxx methods,
          Method.invoke,
          Constructor.newInstance,
          Class.newInstance,
          Class.getClassLoader etc.) and various dangerous
          methods in System and Runtime
          classes (exec, exit,
          halt, load, etc.). The
          BeansWrapper has several security levels (called
          "levels of method exposure"), and the default called
          EXPOSE_SAFE is probably suited for most
          applications. There is a no-safeguard level called
          EXPOSE_ALL that allows you to call even the above
          unsafe methods, and a strict level
          EXPOSE_PROPERTIES_ONLY that will expose only bean
          property getters. Finally, there is a level named
          EXPOSE_NOTHING that will expose no properties and
          no methods. The only data you will be able to access through hash
          model interface in this case are items in maps and resource bundles,
          as well as objects returned from a call to generic
          get(Object) or get(String)
          methods - provided the affected objects have such method.
TemplateScalarModel functionality
Models for java.lang.String objects will
          implement TemplateScalarModel whose
          getAsString() method simply delegates to
          toString(). Note that wrapping
          String objects into Bean wrappers provides much
          more functionality than just them being scalars: because of the hash
          interface described above, the models that wrap
          Strings also provide access to all
          String methods (indexOf,
          substring, etc.), though most of them has native
          FreeMarker equivalent which are better to use
          (s?index_of(n),
          s[start..<end], etc).
TemplateNumberModel functionality
Model wrappers for objects that are instances of
          java.lang.Number implement
          TemplateNumberModel whose
          getAsNumber() method returns the wrapped number
          object. Note that wrapping Number objects into
          Bean wrappers provides much more functionality than just them being
          number models: because of the hash interface described above, the
          models that wrap Numbers also provide access to
          all their methods.
TemplateCollectionModel functionality
Model wrappers for native Java arrays and all classes that
          implement java.util.Collection will implement
          TemplateCollectionModel and thus gain the
          additional capability of being usable through
          list directive.
TemplateSequenceModel functionality
Model wrappers for native Java arrays and all classes that
          implement java.util.List will implement
          TemplateSequenceModel and thus their elements
          will be accessible by index using the model[i]
          syntax. You can also query the length of the array or the size of
          the list using the model?size built-in.
Also, every method that takes a single parameter that is
          assignable through reflective method invocation from a
          java.lang.Integer (these are
          int, long,
          float, double,
          java.lang.Object,
          java.lang.Number, and
          java.lang.Integer) also implements this
          interface. What this means is that you have a convenient way for
          accessing the so-called indexed bean properties:
          model.foo[i] will translate into
          obj.getFoo(i).
TemplateMethodModel functionality
All methods of an object are represented as
          TemplateMethodModelEx objects accessible using a
          hash key with method name on their object's model. When you call a
          method using
          model.method(arg1,
          arg2,
          ...) the arguments are passed
          to the method as template models. The method will first try to
          unwrap them - see below for details about unwrapping. These
          unwrapped arguments are then used for the actual method call. In
          case the method is overloaded, the most specific method will be
          selected using the same rules that are used by the Java compiler to
          select a method from several overloaded methods. In case that no
          method signature matches the passed parameters, or that no method
          can be chosen without ambiguity, a
          TemplateModelException is thrown.
Methods of return type void return
          TemplateModel.NOTHING, so they can be safely
          called with the ${obj.method(args)}
          syntax.
Models for instances of java.util.Map also
          implement TemplateMethodModelEx as a means for
          invoking their get() method. As it was discussed
          previously, you can use the hash functionality to access the "get"
          method as well, but it has several drawbacks: it's slower because
          first property and method names are checked for the key; keys that
          conflict with property and method names will be shadowed by them;
          finally you can use String keys only with that
          approach. In contrast, invoking model(key)
          translates to model.get(key) directly: it's
          faster because there's no property and method name lookup; it is
          subject to no shadowing; and finally it works for non-String keys
          since the argument is unwrapped just as with ordinary method calls.
          In effect, model(key) on a Map
          is equal to model.get(key), only shorter to
          write.
Models for java.util.ResourceBundle also
          implement TemplateMethodModelEx as a convenient
          way of resource access and message formatting. A single-argument
          call to a bundle will retrieve the resource with the name that
          corresponds to the toString() value of the
          unwrapped argument. A multiple-argument call to a bundle will also
          retrieve the resource with the name that corresponds to the
          toString() value of the unwrapped argument, but
          it will use it as a format pattern and pass it to
          java.text.MessageFormat using the unwrapped
          values of second and later arguments as formatting parameters.
          MessageFormat objects will be initialized with
          the locale of the bundle that originated them.
Unwrapping rules
When invoking a Java method from a template, its arguments
          need to be converted from template models back to Java objects.
          Assuming that the target type (the declared type of the method's
          formal parameter) is denoted as T, the following
          rules are tried in the following order:
- 
              If the model is the null model for this wrapper, Java nullis returned.
- 
              If the model implements AdapterTemplateModel, the result ofmodel.getAdaptedObject(T)is returned if it is instance ofTor it is a number and can be converted toTusing numeric coercion as described three bullets lower. All models created by the BeansWrapper are themselves AdapterTemplateModel implementations, so unwrapping a model that was created by BeansWrapper for an underlying Java object always yields the original Java object.
- 
              If the model implements the deprecated WrapperTemplateModel, the result ofmodel.getWrappedObject()is returned if it is instance ofTor it is a number and can be converted toTusing numeric coercion as described two bullets lower.
- 
              If Tisjava.lang.String, then if model implementsTemplateScalarModelits string value is returned. Note that if the model doesn't implement TemplateScalarModel we don't attempt to automatically convert the model to string using String.valueOf(model). You'll have to use the ?string built-in explicitly to pass non-scalars as strings.
- 
              If Tis a primitive numeric type orjava.lang.Numberis assignable fromT, and model implementsTemplateNumberModel, then its numeric value is returned if it is instance ofTor its boxing type (ifTis primitive type). Otherwise, ifTis a built-in Java numeric type (primitive type or a standard subclass ofjava.lang.Number, includingBigIntegerandBigDecimal) a new object of classTor its boxing type is created with the number model's appropriately coerced value.
- 
              If Tisbooleanorjava.lang.Boolean, and model implementsTemplateBooleanModel, then its boolean value is returned.
- 
              If Tisjava.util.Mapand the model implementsTemplateHashModel, then a special Map representation of the hash model is returned.
- 
              If Tisjava.util.Listand the model implementsTemplateSequenceModel, then a special List representation of the sequence model is returned.
- 
              If Tisjava.util.Setand the model implementsTemplateCollectionModel, then a special Set representation of the collection model is returned.
- 
              If Tisjava.util.Collectionorjava.lang.Iterableand the model implements eitherTemplateCollectionModelorTemplateSequenceModel, then a special Set or List representation of the collection or sequence model (respectively) is returned.
- 
              If Tis a Java array type and the model implementsTemplateSequenceModel, then a new array of the specified type is created and its elements unwrapped into the array recursively using the array's component type asT.
- 
              If Tischarorjava.lang.Character, and model implementsTemplateScalarModel, and its string representation contains exactly one character, then ajava.lang.Characterwith that value is retured.
- 
              If java.util.Dateis assignable fromT, and model implementsTemplateDateModel, and its date value is instance ofT, then its date value is returned.
- 
              If model is a number model, and its numeric value is instance of T, the numeric value is returned. You can have a custom subclass of java.lang.Number that implements a custom interface, and T might be that interface. (*)
- 
              If model is a date model, and its date value is instance of T, the date value is returned. Similar consideration as for (*)
- 
              If model is a scalar model, and Tis assignable fromjava.lang.String, the string value is returned. This covers cases when T is java.lang.Object, java.lang.Comparable, and java.io.Serializable (**)
- 
              If model is a boolean model, and Tis assignable fromjava.lang.Boolean, the boolean value is returned. Same as (**)
- 
              If model is a hash model, and Tis assignable fromfreemarker.ext.beans.HashAdapter, a hash adapter is returned. Same as (**)
- 
              If model is a sequence model, and Tis assignable fromfreemarker.ext.beans.SequenceAdapter, a sequence adapter is returned. Same as (**)
- 
              If model is a collection model, and Tis assignable fromfreemarker.ext.beans.SetAdapter, a set adapter for the collection is returned. Same as (**)
- 
              If the model is instance of T, the model itself is returned. This covers the case where the method explicitly declared a FreeMarker-specific model interface, as well as allows returning directive, method and transform models when java.lang.Object is requested.
- 
              An exception signifying no conversion is possible is thrown. 
Accessing static methods
The TemplateHashModel returned from
          BeansWrapper.getStaticModels() can be used to
          create hash models for accessing static methods and fields of an
          arbitrary class.
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel staticModels = wrapper.getStaticModels();
TemplateHashModel fileStatics =
    (TemplateHashModel) staticModels.get("java.io.File");    And you will get a template hash model that exposes all static
          methods and static fields (both final and non-final) of the
          java.lang.System class as hash keys. Suppose that
          you put the previous model in your root model:
root.put("File", fileStatics);    From now on, you can use ${File.SEPARATOR}
          to insert the file separator character into your template, or you
          can even list all roots of your file system by:
<#list File.listRoots() as fileSystemRoot>...</#list>
Of course, you must be aware of the potential security issues this model brings.
You can even give the template authors complete freedom over which classes' static methods they use by placing the static models hash into your template root model with
root.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());    This object exposes just about any class' static methods if
          it's used as a hash with class name as the key. You can then use
          expression like
          ${statics["java.lang.System"].currentTimeMillis()}
          in your template. Note, however that this has even more security
          implications, as someone could even invoke
          System.exit() using this model if the method
          exposure level is weakened to EXPOSE_ALL.
Note that in above examples, we always use the default
          BeansWrapper instance. This is a convenient
          static wrapper instance that you can use in most cases. You are also
          free to create your own BeansWrapper instances
          and use them instead especially when you want to modify some of its
          characteristics (like model caching, security level, or the null
          model representation).
Accessing enums
The TemplateHashModel returned from
          BeansWrapper.getEnumModels() can be used to
          create hash models for accessing values of enums. (An attempt to
          invoke this method on an earlier JRE will result in an
          UnsupportedOperationException.)
BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
TemplateHashModel enumModels = wrapper.getEnumModels();
TemplateHashModel roundingModeEnums =
    (TemplateHashModel) enumModels.get("java.math.RoundingMode");    And you will get a template hash model that exposes all enum
          values of the java.math.RoundingMode class as
          hash keys. Suppose that you put the previous model in your root
          model:
root.put("RoundingMode", roundingModeEnums);    From now on, you can use RoundingMode.UP as
          an expression to reference the UP enum value in
          your template.
You can even give the template authors complete freedom over which enum classes they use by placing the enum models hash into your template root model with
root.put("enums", BeansWrapper.getDefaultInstance().getEnumModels());    This object exposes any enum class if it's used as a hash with
          class name as the key. You can then use expression like
          ${enums["java.math.RoundingMode"].UP} in your
          template.
The exposed enum values can be used as scalars (they'll
          delegate to their toString() method), and can be
          used in equality and inequality comparisons as well.
Note that in above examples, we always use the default
          BeansWrapper instance. This is a convenient
          static wrapper instance that you can use in most cases. You are also
          free to create your own BeansWrapper instances
          and use them instead especially when you want to modify some of its
          characteristics (like model caching, security level, or the null
          model representation).
