| <!doctype html> |
| <!-- Generated by FreeMarker/Docgen from DocBook --> |
| <html lang="en" class="page-type-section"> |
| <head prefix="og: http://ogp.me/ns#"> |
| <meta charset="utf-8"> |
| <title>Bean wrapper - FreeMarker Manual</title> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| <meta name="format-detection" content="telephone=no"> |
| <meta property="og:site_name" content="FreeMarker Manual"> |
| <meta property="og:title" content="Bean wrapper"> |
| <meta property="og:locale" content="en_US"> |
| <meta property="og:url" content="http://example.com/pgui_misc_beanwrapper.html"> |
| <link rel="canonical" href="http://example.com/pgui_misc_beanwrapper.html"> |
| <link rel="icon" href="favicon.png" type="image/png"> |
| <link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1594338517553"> |
| </head> |
| <body itemscope itemtype="https://schema.org/Code"> |
| <meta itemprop="url" content="http://example.com/"> |
| <meta itemprop="name" content="FreeMarker Manual"> |
| |
| <!--[if lte IE 9]> |
| <div style="background-color: #C00; color: #fff; padding: 12px 24px;">Please use a modern browser to view this website.</div> |
| <![endif]--><div class="header-top-bg"><div class="site-width header-top"><a class="logo" href="http://example.com" role="banner"> <img itemprop="image" src="logo.png" alt="My Logo"> |
| </a></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">FreeMarker Manual</a><div class="navigation-header"></div></div><div class="site-width breadcrumb-row"><ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui.html"><span itemprop="name">Programmer's Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_misc.html"><span itemprop="name">Miscellaneous</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_misc_beanwrapper.html"><span itemprop="name">Bean wrapper</span></a></li></ul><div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul class="bookmark-list"><li><a href="alphaidx.html">Index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="ref.html">Reference</a></li><li><a href="app_faq.html">FAQ</a></li><li><a href="preface.html#test_target">Bőregér</a></li></ul></div></div></div> <div class="main-content site-width"> |
| <div class="content-wrapper no-toc"> |
| <div id="table-of-contents-wrapper" class="col-left"> |
| </div> |
| <div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="pgui_misc_multithreading.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_misc_logging.html"><span>Next</span></a></div><div class="title-wrapper"> |
| <h1 class="content-header header-section1" id="pgui_misc_beanwrapper" itemprop="headline">Bean wrapper</h1> |
| </div></div><div class="page-menu"> |
| <div class="page-menu-title">Page Contents</div> |
| <ul><li><a class="page-menu-link" href="#beanswrapper_hash" data-menu-target="beanswrapper_hash">TemplateHashModel functionality</a></li><li><a class="page-menu-link" href="#autoid_48" data-menu-target="autoid_48">A word on security</a></li><li><a class="page-menu-link" href="#autoid_49" data-menu-target="autoid_49">TemplateScalarModel functionality</a></li><li><a class="page-menu-link" href="#autoid_50" data-menu-target="autoid_50">TemplateNumberModel functionality</a></li><li><a class="page-menu-link" href="#autoid_51" data-menu-target="autoid_51">TemplateCollectionModel functionality</a></li><li><a class="page-menu-link" href="#autoid_52" data-menu-target="autoid_52">TemplateSequenceModel functionality</a></li><li><a class="page-menu-link" href="#beanswrapper_method" data-menu-target="beanswrapper_method">TemplateMethodModel functionality</a></li><li><a class="page-menu-link" href="#autoid_53" data-menu-target="autoid_53">Unwrapping rules</a></li><li><a class="page-menu-link" href="#autoid_54" data-menu-target="autoid_54">Accessing static methods</a></li><li><a class="page-menu-link" href="#jdk_15_enums" data-menu-target="jdk_15_enums">Accessing enums</a></li></ul> </div><p>The <code class="inline-code">freemarker.ext.beans.BeansWrapper</code> is an |
| <a href="pgui_datamodel_objectWrapper.html">object wrapper</a> |
| that was originally added to FreeMarker so arbitrary POJO-s (Plain Old |
| Java Objects) can be wrapped into <code class="inline-code">TemplateModel</code> |
| interfaces. Since then it has becomed the normal way of doing things, |
| and in fact the <code class="inline-code">DefaultObjectWrapper</code> itself is a |
| <code class="inline-code">BeansWrapper</code> extension. So everything described |
| here goes for the <code class="inline-code">DefaultObjectWrapper</code> too, except |
| that the <code class="inline-code">DefaultObjectWrapper</code> will wrap |
| <code class="inline-code">String</code>, <code class="inline-code">Number</code>, |
| <code class="inline-code">Date</code>, <code class="inline-code">array</code>, |
| <code class="inline-code">Collection</code> (like <code class="inline-code">List</code>), |
| <code class="inline-code">Map</code>, <code class="inline-code">Boolean</code> and |
| <code class="inline-code">Iterator</code> objects with the |
| <code class="inline-code">freemarker.template.Simple<em class="code-color">Xxx</em></code> |
| classes, and W3C DOM nodes with |
| <code class="inline-code">freemarker.ext.dom.NodeModel</code> (<a href="xgui.html">more about wrapped W3C DOM...</a>), so for those the |
| above described rules doesn't apply.</p><p>You will want to use <code class="inline-code">BeansWrapper</code> instead of |
| <code class="inline-code">DefaultObjectWrapper</code> when any of these |
| stands:</p><ul> |
| <li> |
| <p>The <code class="inline-code">Collection</code>-s and |
| <code class="inline-code">Map</code>-s of the model should be allowed to be |
| modified during template execution. |
| (<code class="inline-code">DefaultObjectWrapper</code> prevents that, since it |
| creates a copy of the collections when they are wrapped, and the |
| copies will be read-only.)</p> |
| </li> |
| |
| <li> |
| <p>If the identity of the <code class="inline-code">array</code>, |
| <code class="inline-code">Collection</code> and <code class="inline-code">Map</code> objects |
| 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.</p> |
| </li> |
| |
| <li> |
| <p>If the Java API of the earlier listed classes |
| (<code class="inline-code">String</code>, <code class="inline-code">Map</code>, |
| <code class="inline-code">List</code> ...etc) should be visible for the |
| templates. Even with <code class="inline-code">BeansWrapper</code>, 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 <a href="ref_builtins.html">the built-ins</a> (like |
| <code class="inline-code">foo?size</code>, <code class="inline-code">foo?upper</code>, |
| <code class="inline-code">foo?replace('_', '-')</code> ...etc) instead of the |
| Java API.</p> |
| </li> |
| </ul><p>Below is a summary of the <code class="inline-code">TemplateModel</code>-s |
| that the <code class="inline-code">BeansWrapper</code> creates. Let's assume that |
| the object is called <code class="inline-code">obj</code> before wrapping, and |
| <code class="inline-code">model</code> after wrapping for the sake of the following |
| discussion.</p> |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="beanswrapper_hash">TemplateHashModel functionality</h2> |
| |
| |
| <p>Every object will be wrapped into a |
| <code class="inline-code">TemplateHashModel</code> that will expose JavaBeans |
| properties and methods of the object. This way, you can use |
| <code class="inline-code">model.foo</code> in the template to invoke |
| <code class="inline-code">obj.getFoo()</code> or <code class="inline-code">obj.isFoo()</code> |
| 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 <code class="inline-code">model.doBar()</code> to invoke |
| <code class="inline-code">object.doBar()</code>. More on this on discussion of |
| method model functionality.</p> |
| |
| <p>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 |
| <code class="inline-code"><em class="code-color">any-return-type</em> |
| get(String)</code> or public |
| <code class="inline-code"><em class="code-color">any-return-type</em> |
| get(Object)</code> and invoke that method with the requested key. |
| Note that this allows convenient access to mappings in a |
| <code class="inline-code">java.util.Map</code> and similar classes - as long as |
| the keys of the map are <code class="inline-code">String</code>s 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 |
| <code class="inline-code">java.util.ResourceBundle</code> objects use the |
| <code class="inline-code">getObject(String)</code> as the generic get |
| method.</p> |
| |
| <p>If you call <code class="inline-code">setExposeFields(true)</code> on a |
| <code class="inline-code">BeansWrapper</code> instance, it will also expose |
| public, non-static fields of classes as hash keys and values. I.e. |
| if <code class="inline-code">foo</code> is a public, non-static field of the class |
| <code class="inline-code">Bar</code>, and <code class="inline-code">bar</code> is a template |
| variable wrapping an instance of <code class="inline-code">Bar</code>, then |
| <code class="inline-code">bar.foo</code> expression will evaluate as the value of |
| the field <code class="inline-code">foo</code> of the <code class="inline-code">bar</code> |
| object. The public fields in all superclasses of the class are also |
| exposed.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_48">A word on security</h2> |
| |
| |
| <p>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 (<code class="inline-code">wait</code>, |
| <code class="inline-code">notify</code>, <code class="inline-code">notifyAll</code>), thread and |
| thread group management methods (<code class="inline-code">stop</code>, |
| <code class="inline-code">suspend</code>, <code class="inline-code">resume</code>, |
| <code class="inline-code">setDaemon</code>, <code class="inline-code">setPriority</code>), |
| reflection (<code class="inline-code">Field</code> |
| <code class="inline-code">set<em class="code-color">Xxx</em></code> methods, |
| <code class="inline-code">Method.invoke</code>, |
| <code class="inline-code">Constructor.newInstance</code>, |
| <code class="inline-code">Class.newInstance</code>, |
| <code class="inline-code">Class.getClassLoader</code> etc.) and various dangerous |
| methods in <code class="inline-code">System</code> and <code class="inline-code">Runtime</code> |
| classes (<code class="inline-code">exec</code>, <code class="inline-code">exit</code>, |
| <code class="inline-code">halt</code>, <code class="inline-code">load</code>, etc.). The |
| <code class="inline-code">BeansWrapper</code> has several security levels (called |
| "levels of method exposure"), and the default called |
| <code class="inline-code">EXPOSE_SAFE</code> is probably suited for most |
| applications. There is a no-safeguard level called |
| <code class="inline-code">EXPOSE_ALL</code> that allows you to call even the above |
| unsafe methods, and a strict level |
| <code class="inline-code">EXPOSE_PROPERTIES_ONLY</code> that will expose only bean |
| property getters. Finally, there is a level named |
| <code class="inline-code">EXPOSE_NOTHING</code> 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 |
| <code class="inline-code">get(Object)</code> or <code class="inline-code">get(String)</code> |
| methods - provided the affected objects have such method.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_49">TemplateScalarModel functionality</h2> |
| |
| |
| <p>Models for <code class="inline-code">java.lang.String</code> objects will |
| implement <code class="inline-code">TemplateScalarModel</code> whose |
| <code class="inline-code">getAsString()</code> method simply delegates to |
| <code class="inline-code">toString()</code>. Note that wrapping |
| <code class="inline-code">String</code> objects into Bean wrappers provides much |
| more functionality than just them being scalars: because of the hash |
| interface described above, the models that wrap |
| <code class="inline-code">String</code>s also provide access to all |
| <code class="inline-code">String</code> methods (<code class="inline-code">indexOf</code>, |
| <code class="inline-code">substring</code>, etc.).</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_50">TemplateNumberModel functionality</h2> |
| |
| |
| <p>Model wrappers for objects that are instances of |
| <code class="inline-code">java.lang.Number</code> implement |
| <code class="inline-code">TemplateNumberModel</code> whose |
| <code class="inline-code">getAsNumber()</code> method returns the wrapped number |
| object. Note that wrapping <code class="inline-code">Number</code> 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 <code class="inline-code">Number</code>s also provide access to |
| all their methods.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_51">TemplateCollectionModel functionality</h2> |
| |
| |
| <p>Model wrappers for native Java arrays and all classes that |
| implement <code class="inline-code">java.util.Collection</code> will implement |
| <code class="inline-code">TemplateCollectionModel</code> and thus gain the |
| additional capability of being usable through |
| <code class="inline-code">list</code> directive.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_52">TemplateSequenceModel functionality</h2> |
| |
| |
| <p>Model wrappers for native Java arrays and all classes that |
| implement <code class="inline-code">java.util.List</code> will implement |
| <code class="inline-code">TemplateSequenceModel</code> and thus their elements |
| will be accessible by index using the <code class="inline-code">model[i]</code> |
| syntax. You can also query the length of the array or the size of |
| the list using the <code class="inline-code">model?size</code> built-in.</p> |
| |
| <p>Also, every method that takes a single parameter that is |
| assignable through reflective method invocation from a |
| <code class="inline-code">java.lang.Integer</code> (these are |
| <code class="inline-code">int</code>, <code class="inline-code">long</code>, |
| <code class="inline-code">float</code>, <code class="inline-code">double</code>, |
| <code class="inline-code">java.lang.Object</code>, |
| <code class="inline-code">java.lang.Number</code>, and |
| <code class="inline-code">java.lang.Integer</code>) also implements this |
| interface. What this means is that you have a convenient way for |
| accessing the so-called indexed bean properties: |
| <code class="inline-code">model.foo[i]</code> will translate into |
| <code class="inline-code">obj.getFoo(i)</code>.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="beanswrapper_method">TemplateMethodModel functionality</h2> |
| |
| |
| <p>All methods of an object are represented as |
| <code class="inline-code">TemplateMethodModelEx</code> objects accessible using a |
| hash key with method name on their object's model. When you call a |
| method using |
| <code class="inline-code">model.<em class="code-color">method</em>(<em class="code-color">arg1</em>, |
| <em class="code-color">arg2</em>, |
| <em class="code-color">...</em>)</code> 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 |
| <code class="inline-code">TemplateModelException</code> is thrown.</p> |
| |
| <p>Methods of return type <code class="inline-code">void</code> return |
| <code class="inline-code">TemplateModel.NOTHING</code>, so they can be safely |
| called with the <code class="inline-code">${obj.method(args)}</code> |
| syntax.</p> |
| |
| <p>Models for instances of <code class="inline-code">java.util.Map</code> also |
| implement <code class="inline-code">TemplateMethodModelEx</code> as a means for |
| invoking their <code class="inline-code">get()</code> 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 <code class="inline-code">String</code> keys only with that |
| approach. In contrast, invoking <code class="inline-code">model(key)</code> |
| translates to <code class="inline-code">model.get(key)</code> 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, <code class="inline-code">model(key)</code> on a <code class="inline-code">Map</code> |
| is equal to <code class="inline-code">model.get(key)</code>, only shorter to |
| write.</p> |
| |
| <p>Models for <code class="inline-code">java.util.ResourceBundle</code> also |
| implement <code class="inline-code">TemplateMethodModelEx</code> 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 <code class="inline-code">toString()</code> value of the |
| unwrapped argument. A multiple-argument call to a bundle will also |
| retrieve the resource with the name that corresponds to the |
| <code class="inline-code">toString()</code> value of the unwrapped argument, but |
| it will use it as a format pattern and pass it to |
| <code class="inline-code">java.text.MessageFormat</code> using the unwrapped |
| values of second and later arguments as formatting parameters. |
| <code class="inline-code">MessageFormat</code> objects will be initialized with |
| the locale of the bundle that originated them.</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_53">Unwrapping rules</h2> |
| |
| |
| <p>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 <code class="inline-code">T</code>, the following |
| rules are tried in the following order:</p> |
| |
| <ul> |
| <li> |
| <p>If the model is the null model for this wrapper, Java |
| <code class="inline-code">null</code> is returned.</p> |
| </li> |
| |
| <li> |
| <p>If the model implements |
| <code class="inline-code">AdapterTemplateModel</code>, the result of |
| <code class="inline-code">model.getAdaptedObject(T)</code> is returned if it |
| is instance of <code class="inline-code">T</code> or it is a number and can be |
| converted to <code class="inline-code">T</code> using numeric coercion as |
| described three bullets lower. <span class="marked-for-programmers">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.</span></p> |
| </li> |
| |
| <li> |
| <p>If the model implements the deprecated |
| <code class="inline-code">WrapperTemplateModel</code>, the result of |
| <code class="inline-code">model.getWrappedObject()</code> is returned if it is |
| instance of <code class="inline-code">T</code> or it is a number and can be |
| converted to <code class="inline-code">T</code> using numeric coercion as |
| described two bullets lower.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is |
| <code class="inline-code">java.lang.String</code>, then if model implements |
| <code class="inline-code">TemplateScalarModel</code> its string value is |
| returned. <span class="marked-for-programmers">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.</span></p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is a primitive numeric type or |
| <code class="inline-code">java.lang.Number</code> is assignable from |
| <code class="inline-code">T</code>, and model implements |
| <code class="inline-code">TemplateNumberModel</code>, then its numeric value |
| is returned if it is instance of <code class="inline-code">T</code> or its |
| boxing type (if <code class="inline-code">T</code> is primitive type). |
| Otherwise, if <code class="inline-code">T</code> is a built-in Java numeric |
| type (primitive type or a standard subclass of |
| <code class="inline-code">java.lang.Number</code>, including |
| <code class="inline-code">BigInteger</code> and <code class="inline-code">BigDecimal</code>) |
| a new object of class <code class="inline-code">T</code> or its boxing type is |
| created with the number model's appropriately coerced |
| value.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is <code class="inline-code">boolean</code> or |
| <code class="inline-code">java.lang.Boolean</code>, and model implements |
| <code class="inline-code">TemplateBooleanModel</code>, then its boolean value |
| is returned.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is |
| <code class="inline-code">java.util.Map</code> and the model implements |
| <code class="inline-code">TemplateHashModel</code>, then a special Map |
| representation of the hash model is returned.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is |
| <code class="inline-code">java.util.List</code> and the model implements |
| <code class="inline-code">TemplateSequenceModel</code>, then a special List |
| representation of the sequence model is returned.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is |
| <code class="inline-code">java.util.Set</code> and the model implements |
| <code class="inline-code">TemplateCollectionModel</code>, then a special Set |
| representation of the collection model is returned.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is |
| <code class="inline-code">java.util.Collection</code> or |
| <code class="inline-code">java.lang.Iterable</code> and the model implements |
| either <code class="inline-code">TemplateCollectionModel</code> or |
| <code class="inline-code">TemplateSequenceModel</code>, then a special Set or |
| List representation of the collection or sequence model |
| (respectively) is returned.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is a Java array type and the model |
| implements <code class="inline-code">TemplateSequenceModel</code>, then a new |
| array of the specified type is created and its elements |
| unwrapped into the array recursively using the array's component |
| type as <code class="inline-code">T</code>.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">T</code> is <code class="inline-code">char</code> or |
| <code class="inline-code">java.lang.Character</code>, and model implements |
| <code class="inline-code">TemplateScalarModel</code>, and its string |
| representation contains exactly one character, then a |
| <code class="inline-code">java.lang.Character</code> with that value is |
| retured.</p> |
| </li> |
| |
| <li> |
| <p>If <code class="inline-code">java.util.Date</code> is assignable from |
| <code class="inline-code">T</code>, and model implements |
| <code class="inline-code">TemplateDateModel</code>, and its date value is |
| instance of <code class="inline-code">T</code>, then its date value is |
| returned.</p> |
| </li> |
| |
| <li> |
| <p>If model is a number model, and its numeric value is |
| instance of <code class="inline-code">T</code>, the numeric value is returned. |
| <span class="marked-for-programmers">You can have a custom subclass of |
| java.lang.Number that implements a custom interface, and T might |
| be that interface. (*)</span></p> |
| </li> |
| |
| <li> |
| <p>If model is a date model, and its date value is instance |
| of <code class="inline-code">T</code>, the date value is returned. <span class="marked-for-programmers">Similar consideration as for |
| (*)</span></p> |
| </li> |
| |
| <li> |
| <p>If model is a scalar model, and <code class="inline-code">T</code> is |
| assignable from <code class="inline-code">java.lang.String</code>, the string |
| value is returned. <span class="marked-for-programmers">This covers |
| cases when T is java.lang.Object, java.lang.Comparable, and |
| java.io.Serializable (**)</span></p> |
| </li> |
| |
| <li> |
| <p>If model is a boolean model, and <code class="inline-code">T</code> is |
| assignable from <code class="inline-code">java.lang.Boolean</code>, the |
| boolean value is returned. <span class="marked-for-programmers">Same as |
| (**)</span></p> |
| </li> |
| |
| <li> |
| <p>If model is a hash model, and <code class="inline-code">T</code> is |
| assignable from |
| <code class="inline-code">freemarker.ext.beans.HashAdapter</code>, a hash |
| adapter is returned. <span class="marked-for-programmers">Same as |
| (**)</span></p> |
| </li> |
| |
| <li> |
| <p>If model is a sequence model, and <code class="inline-code">T</code> is |
| assignable from |
| <code class="inline-code">freemarker.ext.beans.SequenceAdapter</code>, a |
| sequence adapter is returned. <span class="marked-for-programmers">Same |
| as (**)</span></p> |
| </li> |
| |
| <li> |
| <p>If model is a collection model, and <code class="inline-code">T</code> |
| is assignable from |
| <code class="inline-code">freemarker.ext.beans.SetAdapter</code>, a set |
| adapter for the collection is returned. <span class="marked-for-programmers">Same as (**)</span></p> |
| </li> |
| |
| <li> |
| <p>If the model is instance of <code class="inline-code">T</code>, the |
| model itself is returned. <span class="marked-for-programmers">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.</span></p> |
| </li> |
| |
| <li> |
| <p>An exception signifying no conversion is possible is |
| thrown.</p> |
| </li> |
| </ul> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="autoid_54">Accessing static methods</h2> |
| |
| |
| |
| |
| <p>The <code class="inline-code">TemplateHashModel</code> returned from |
| <code class="inline-code">BeansWrapper.getStaticModels()</code> can be used to |
| create hash models for accessing static methods and fields of an |
| arbitrary class.</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-unspecified">BeansWrapper wrapper = BeansWrapper.getDefaultInstance(); |
| TemplateHashModel staticModels = wrapper.getStaticModels(); |
| TemplateHashModel fileStatics = |
| (TemplateHashModel) staticModels.get("java.io.File");</pre></div> |
| |
| <p>And you will get a template hash model that exposes all static |
| methods and static fields (both final and non-final) of the |
| <code class="inline-code">java.lang.System</code> class as hash keys. Suppose that |
| you put the previous model in your root model:</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-unspecified">root.put("File", fileStatics);</pre></div> |
| |
| <p>From now on, you can use <code class="inline-code">${File.SEPARATOR}</code> |
| to insert the file separator character into your template, or you |
| can even list all roots of your file system by:</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-template"><#list File.listRoots() as fileSystemRoot>...</#list></pre></div> |
| |
| <p>Of course, you must be aware of the potential security issues |
| this model brings.</p> |
| |
| <p>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</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-unspecified">root.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());</pre></div> |
| |
| <p>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 |
| <code class="inline-code">${statics["java.lang.System"].currentTimeMillis()}</code> |
| in your template. Note, however that this has even more security |
| implications, as someone could even invoke |
| <code class="inline-code">System.exit()</code> using this model if the method |
| exposure level is weakened to <code class="inline-code">EXPOSE_ALL</code>.</p> |
| |
| <p>Note that in above examples, we always use the default |
| <code class="inline-code">BeansWrapper</code> instance. This is a convenient |
| static wrapper instance that you can use in most cases. You are also |
| free to create your own <code class="inline-code">BeansWrapper</code> 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).</p> |
| |
| |
| |
| |
| |
| <h2 class="content-header header-section2" id="jdk_15_enums">Accessing enums</h2> |
| |
| |
| <p>The <code class="inline-code">TemplateHashModel</code> returned from |
| <code class="inline-code">BeansWrapper.getEnumModels()</code> can be used to |
| create hash models for accessing values of enums on JRE 1.5 or |
| later. (An attempt to invoke this method on an earlier JRE will |
| result in an |
| <code class="inline-code">UnsupportedOperationException</code>.)</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-unspecified">BeansWrapper wrapper = BeansWrapper.getDefaultInstance(); |
| TemplateHashModel enumModels = wrapper.getEnumModels(); |
| TemplateHashModel roundingModeEnums = |
| (TemplateHashModel) enumModels.get("java.math.RoundingMode");</pre></div> |
| |
| <p>And you will get a template hash model that exposes all enum |
| values of the <code class="inline-code">java.math.RoundingMode</code> class as |
| hash keys. Suppose that you put the previous model in your root |
| model:</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-unspecified">root.put("RoundingMode", roundingModeEnums);</pre></div> |
| |
| <p>From now on, you can use <code class="inline-code">RoundingMode.UP</code> as |
| an expression to reference the <code class="inline-code">UP</code> enum value in |
| your template.</p> |
| |
| <p>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</p> |
| |
| |
| |
| <div class="code-wrapper"><pre class="code-block code-unspecified">root.put("enums", BeansWrapper.getDefaultInstance().getEnumModels());</pre></div> |
| |
| <p>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 |
| <code class="inline-code">${enums["java.math.RoundingMode"].UP}</code> in your |
| template.</p> |
| |
| <p>The exposed enum values can be used as scalars (they'll |
| delegate to their <code class="inline-code">toString()</code> method), and can be |
| used in equality and inequality comparisons as well.</p> |
| |
| <p>Note that in above examples, we always use the default |
| <code class="inline-code">BeansWrapper</code> instance. This is a convenient |
| static wrapper instance that you can use in most cases. You are also |
| free to create your own <code class="inline-code">BeansWrapper</code> 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).</p> |
| <div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="pgui_misc_multithreading.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_misc_logging.html"><span>Next</span></a></div></div></div></div> </div> |
| </div> |
| <div class="site-footer"><div class="site-width"><div class="footer-bottom"> <p class="last-generated"> |
| Last generated: |
| <time itemprop="dateModified" datetime="2020-07-09T23:48:37Z" title="Thursday, July 9, 2020 11:48:37 PM GMT">2020-07-09 23:48:37 GMT</time> </p> |
| <p class="copyright"> |
| © <span itemprop="copyrightYear">1999</span>–2020 |
| <a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a> </p> |
| </div></div></div></body> |
| </html> |