You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2016/12/06 22:29:56 UTC

[01/24] incubator-freemarker git commit: (Manual: Release date filled)

Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3 dd7a2aa3f -> 44201a6d1


(Manual: Release date filled)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/5348248a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/5348248a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/5348248a

Branch: refs/heads/2.3
Commit: 5348248a4b6d95462db62f638b8969ff99583de7
Parents: 32b7be4
Author: ddekany <dd...@apache.org>
Authored: Tue Jul 5 21:16:46 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Jul 5 21:16:46 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5348248a/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index b58779f..32f0823 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26558,8 +26558,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
       <section xml:id="versions_2_3_25">
         <title>2.3.25 (incubating at Apache)</title>
 
-        <para>Release date: 2016-06-14 + voting process (usually around 2
-        weeks)</para>
+        <para>Release date: 2016-06-26</para>
 
         <para>This is a stable, final release. The <quote>incubating</quote>
         suffix is required by the Apache Software Foundation until the project


[09/24] incubator-freemarker git commit: Emphasize that the "incubating" release is a final release.

Posted by dd...@apache.org.
Emphasize that the "incubating" release is a final release.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/32c88790
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/32c88790
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/32c88790

Branch: refs/heads/2.3
Commit: 32c88790d559b2f019ab9ebba2b0ffe9a62e54fb
Parents: 2b1ff0e
Author: ddekany <dd...@apache.org>
Authored: Thu Aug 11 20:41:05 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Thu Aug 11 20:41:05 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/32c88790/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 212aeb1..bd5ba49 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26587,9 +26587,10 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
         <para>Release date: 2016-06-26</para>
 
-        <para>This is a stable, final release. The <quote>incubating</quote>
-        suffix is required by the Apache Software Foundation until the project
-        becomes a fully accepted (graduated) Apache project.</para>
+        <para><emphasis role="bold">This is a stable, final
+        release.</emphasis> The <quote>incubating</quote> suffix is required
+        by the Apache Software Foundation until the project becomes a fully
+        accepted (graduated) Apache project.</para>
 
         <section>
           <title>Changes on the FTL side</title>
@@ -26766,10 +26767,10 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
         <para>Release date: 2016-03-28</para>
 
-        <para>This is a stable, final release. The <quote>incubating</quote>
-        suffix is required by the Apache Software Foundation until the project
-        becomes a fully accepted (graduated) Apache project. See disclaimer
-        below.</para>
+        <para><emphasis role="bold">This is a stable, final
+        release.</emphasis> The <quote>incubating</quote> suffix is required
+        by the Apache Software Foundation until the project becomes a fully
+        accepted (graduated) Apache project. See disclaimer below.</para>
 
         <section>
           <title>Legal changes</title>


[02/24] incubator-freemarker git commit: FREEMARKER-28: Manual typo fix

Posted by dd...@apache.org.
FREEMARKER-28: Manual typo fix


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/6032411a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/6032411a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/6032411a

Branch: refs/heads/2.3
Commit: 6032411ae052dd55aceb311c799ad4069979ecfa
Parents: 5348248
Author: ddekany <dd...@apache.org>
Authored: Tue Jul 5 22:37:20 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Jul 5 22:37:20 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6032411a/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 32f0823..14732b5 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -5332,6 +5332,7 @@ other@example.com, other@example.com, other@example.com</programlisting>
                 <literal>&amp;</literal>, <literal>"</literal>,
                 <literal>'</literal> as <literal>&amp;lt;</literal>,
                 <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;quot;</literal>,
                 <literal>&amp;#39;</literal></td>
 
                 <td><literal>text/html</literal></td>
@@ -5346,6 +5347,7 @@ other@example.com, other@example.com, other@example.com</programlisting>
                 <literal>&amp;</literal>, <literal>"</literal>,
                 <literal>'</literal> as <literal>&amp;lt;</literal>,
                 <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;quot;</literal>,
                 <literal>&amp;#39;</literal></td>
 
                 <td><literal>application/xhtml+xml</literal></td>
@@ -5362,6 +5364,7 @@ other@example.com, other@example.com, other@example.com</programlisting>
                 <literal>&amp;</literal>, <literal>"</literal>,
                 <literal>'</literal> as <literal>&amp;lt;</literal>,
                 <literal>&amp;gt;</literal>, <literal>&amp;amp;</literal>,
+                <literal>&amp;quot;</literal>,
                 <literal>&amp;apos;</literal></td>
 
                 <td><literal>application/xml</literal></td>


[06/24] incubator-freemarker git commit: grammar, phrasing fixes

Posted by dd...@apache.org.
grammar, phrasing fixes


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/0815e14f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/0815e14f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/0815e14f

Branch: refs/heads/2.3
Commit: 0815e14ffc1e0b91a51fa62b69cef412b0a82ccb
Parents: b64ab13
Author: ratherblue <ra...@gmail.com>
Authored: Mon Jul 25 23:19:18 2016 -0700
Committer: ratherblue <ra...@gmail.com>
Committed: Mon Jul 25 23:19:18 2016 -0700

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0815e14f/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 2938787..b93691a 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -759,18 +759,18 @@ All Rights Reserved.
 
           <para>Note that since FreeMarker does not interpret text outside FTL
           tags, interpolations and FTL comments, above you could use the FTL
-          tags inside a HTML attributes without problem.</para>
+          tags inside HTML attributes without problem.</para>
         </section>
 
         <section>
           <title>Using built-ins</title>
 
-          <para>The so called built-ins are like subvariables (or rather like
-          methods, if you know that Java term) that aren't coming coming from
-          the data-model, but added by FreeMarker to the values. To make it
-          unambiguous where the subvarable comes from, to access them you have
+          <para>The so-called built-ins are like subvariables (or rather like
+          methods, if you know that Java term) that aren't coming from
+          the data-model, but added by FreeMarker to the values. In order to make it
+          clear where subvariables comes from, you have
           to use <literal>?</literal> (question mark) instead of
-          <literal>.</literal> (dot). <anchor
+          <literal>.</literal> (dot) to access them. <anchor
           xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most
           commonly used built-ins:</para>
 
@@ -875,17 +875,17 @@ All Rights Reserved.
 
           <para>The data-model often has variables that are optional (i.e.,
           sometimes missing). To spot some typical human mistakes, FreeMarker
-          doesn't tolerate the referring to missing variables, unless you tell
+          doesn't tolerate references to missing variables unless you tell
           explicitly what to do if the variable is missing. Here we will show
           the two most typical ways of doing that.</para>
 
           <para><phrase role="forProgrammers">Note for programmers: A
           non-existent variable and a variable with <literal>null</literal>
-          value is the same for FreeMarker, so the "missing" term used here
+          value is the same for FreeMarker. The "missing" term used here
           covers both cases.</phrase></para>
 
           <para>Wherever you refer to a variable, you can specify a default
-          value for the case the variable is missing, by following the
+          value for the case the variable is missing by following the
           variable name with a <literal>!</literal> and the default value.
           Like in the following example, when <literal>user</literal> is
           missing from data model, the template will behave like if


[08/24] incubator-freemarker git commit: (Fixed line wrapping differences caused be editing without XXE.)

Posted by dd...@apache.org.
(Fixed line wrapping differences caused be editing without XXE.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/2b1ff0e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/2b1ff0e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/2b1ff0e8

Branch: refs/heads/2.3
Commit: 2b1ff0e8d7b06e2837e86d448ecac18e69fc1805
Parents: 58cba5b
Author: ddekany <dd...@apache.org>
Authored: Thu Aug 11 20:30:41 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Thu Aug 11 20:30:41 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 70 +++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2b1ff0e8/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index c6b0c38..212aeb1 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -44,11 +44,12 @@
 
     <para>Templates are written in the FreeMarker Template Language (FTL).
     It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
-    programming language like PHP. You are meant to prepare the data to display in
-    a real programming language, like issue database queries and do business
-    calculations, and then the template displays that already prepared data.
-    In the template you are focusing on how to present the data, and outside
-    the template you are focusing on what data to present.</para>
+    programming language like PHP. You are meant to prepare the data to
+    display in a real programming language, like issue database queries and do
+    business calculations, and then the template displays that already
+    prepared data. In the template you are focusing on how to present the
+    data, and outside the template you are focusing on what data to
+    present.</para>
 
     <mediaobject>
       <imageobject>
@@ -59,10 +60,10 @@
     <para>This approach is often referred to as the <link
     linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
     particularly popular for dynamic web pages. It helps in separating web
-    page designers (HTML authors) from developers (Java programmers
-    usually). Designers won't face complicated logic in templates, and can
-    change the appearance of a page without programmers having to change or
-    recompile code.</para>
+    page designers (HTML authors) from developers (Java programmers usually).
+    Designers won't face complicated logic in templates, and can change the
+    appearance of a page without programmers having to change or recompile
+    code.</para>
 
     <para>While FreeMarker was originally created for generating HTML pages in
     MVC web application frameworks, it isn't bound to servlets or HTML or
@@ -116,11 +117,11 @@
 
         <para>But the user's name ("John Doe" above) depends on who the
         logged-in user is, and the latest product information should come from
-        a database. Because this data changes, you cannot you cannot use static HTML. Instead, you
-        can use a <emphasis role="term">template</emphasis> of the desired
-        output. The template is the same as the static HTML would be, except
-        that it contains some instructions to FreeMarker that makes it
-        dynamic:</para>
+        a database. Because this data changes, you cannot you cannot use
+        static HTML. Instead, you can use a <emphasis
+        role="term">template</emphasis> of the desired output. The template is
+        the same as the static HTML would be, except that it contains some
+        instructions to FreeMarker that makes it dynamic:</para>
 
         <programlisting role="template" xml:id="example.first">&lt;html&gt;
 &lt;head&gt;
@@ -419,8 +420,8 @@
         </itemizedlist>
 
         <para>Anything not an FTL tag or an interpolation or comment is
-        considered static text and will not be interpreted by FreeMarker;
-        it is just printed to the output as-is.</para>
+        considered static text and will not be interpreted by FreeMarker; it
+        is just printed to the output as-is.</para>
 
         <para>With FTL tags you refer to so-called <emphasis
         role="term">directives</emphasis>. This is the same kind of
@@ -428,8 +429,8 @@
         <literal>&lt;table&gt;</literal> and
         <literal>&lt;/table&gt;</literal>) and HTML elements (e.g., the
         <literal>table</literal> element) to which you refer to with the HTML
-        tags. (If you don't understand this difference then consider "FTL tag" and
-        "directive" synonyms.)</para>
+        tags. (If you don't understand this difference then consider "FTL tag"
+        and "directive" synonyms.)</para>
 
         <note>
           <para>You can easily try writing templates on <link
@@ -499,8 +500,8 @@
             here a number is specified directly (<literal>0</literal>). Note
             that the number is <emphasis>not</emphasis> quoted. If you quoted
             it (<literal>"0"</literal>), FreeMarker would misinterpret it as a
-            string literal, and because the price to compare it to is a number,
-            you get an error.</para>
+            string literal, and because the price to compare it to is a
+            number, you get an error.</para>
 
             <para>This will print "Pythons are not free today!" if their price
             is not 0:</para>
@@ -594,8 +595,8 @@
             <literal>&lt;/#list&gt;</literal> tags.</para>
 
             <para>The <literal><replaceable>sequence</replaceable></literal>
-            can be any kind of expression. For example we could list the fruits of
-            the example data model like this:</para>
+            can be any kind of expression. For example we could list the
+            fruits of the example data model like this:</para>
 
             <programlisting role="template">&lt;ul&gt;
 <emphasis>&lt;#list misc.fruits as fruit&gt;</emphasis>
@@ -766,11 +767,11 @@ All Rights Reserved.
           <title>Using built-ins</title>
 
           <para>The so-called built-ins are like subvariables (or rather like
-          methods, if you know that Java term) that aren't coming from
-          the data-model, but added by FreeMarker to the values. In order to make it
-          clear where subvariables comes from, you have
-          to use <literal>?</literal> (question mark) instead of
-          <literal>.</literal> (dot) to access them. <anchor
+          methods, if you know that Java term) that aren't coming from the
+          data-model, but added by FreeMarker to the values. In order to make
+          it clear where subvariables comes from, you have to use
+          <literal>?</literal> (question mark) instead of <literal>.</literal>
+          (dot) to access them. <anchor
           xml:id="topic.commonlyUsedBuiltIns"/>Examples with some of the most
           commonly used built-ins:</para>
 
@@ -885,14 +886,13 @@ All Rights Reserved.
           covers both cases.</phrase></para>
 
           <para>Wherever you refer to a variable, you can specify a default
-          value for the case the variable is missing by following the
-          variable name with a <literal>!</literal> and the default value.
-          Like in the following example, when <literal>user</literal> is
-          missing from data model, the template will behave like if
-          <literal>user</literal>'s value were the string
-          <literal>"visitor"</literal>. (When <literal>user</literal> isn't
-          missing, this template behaves exactly like with
-          <literal>${user}</literal>):</para>
+          value for the case the variable is missing by following the variable
+          name with a <literal>!</literal> and the default value. Like in the
+          following example, when <literal>user</literal> is missing from data
+          model, the template will behave like if <literal>user</literal>'s
+          value were the string <literal>"visitor"</literal>. (When
+          <literal>user</literal> isn't missing, this template behaves exactly
+          like with <literal>${user}</literal>):</para>
 
           <programlisting role="template">&lt;h1&gt;Welcome ${user<emphasis>!"visitor"</emphasis>}!&lt;/h1&gt;</programlisting>
 


[05/24] incubator-freemarker git commit: more text clean up, typos

Posted by dd...@apache.org.
more text clean up, typos


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/b64ab137
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/b64ab137
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/b64ab137

Branch: refs/heads/2.3
Commit: b64ab13748c100ae9964e142d107d9fd9d42ea5c
Parents: a3fa4d2
Author: ratherblue <ra...@gmail.com>
Authored: Mon Jul 25 23:11:55 2016 -0700
Committer: ratherblue <ra...@gmail.com>
Committed: Mon Jul 25 23:11:55 2016 -0700

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b64ab137/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 18c486d..2938787 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -419,8 +419,8 @@
         </itemizedlist>
 
         <para>Anything not an FTL tag or an interpolation or comment is
-        considered as static text, and will not be interpreted by FreeMarker;
-        it is just printed to the output as is.</para>
+        considered static text and will not be interpreted by FreeMarker;
+        it is just printed to the output as-is.</para>
 
         <para>With FTL tags you refer to so-called <emphasis
         role="term">directives</emphasis>. This is the same kind of
@@ -428,8 +428,8 @@
         <literal>&lt;table&gt;</literal> and
         <literal>&lt;/table&gt;</literal>) and HTML elements (e.g., the
         <literal>table</literal> element) to which you refer to with the HTML
-        tags. (If you don't feel this difference then just take "FTL tag" and
-        "directive" as synonyms.)</para>
+        tags. (If you don't understand this difference then consider "FTL tag" and
+        "directive" synonyms.)</para>
 
         <note>
           <para>You can easily try writing templates on <link
@@ -498,8 +498,8 @@
             <para>Similarly as earlier when a string was specified directly,
             here a number is specified directly (<literal>0</literal>). Note
             that the number is <emphasis>not</emphasis> quoted. If you quoted
-            it (<literal>"0"</literal>), FreeMarker were misinterpret it as a
-            string literal, and because the price to compare it to is number,
+            it (<literal>"0"</literal>), FreeMarker would misinterpret it as a
+            string literal, and because the price to compare it to is a number,
             you get an error.</para>
 
             <para>This will print "Pythons are not free today!" if their price
@@ -594,7 +594,7 @@
             <literal>&lt;/#list&gt;</literal> tags.</para>
 
             <para>The <literal><replaceable>sequence</replaceable></literal>
-            can be any kind of expression, like we could list the fruits of
+            can be any kind of expression. For example we could list the fruits of
             the example data model like this:</para>
 
             <programlisting role="template">&lt;ul&gt;
@@ -630,7 +630,7 @@
             case.</para>
 
             <para>Another frequent listing-related task: let's list the fruits
-            separating them with something, like comma:</para>
+            separating them with something, like a comma:</para>
 
             <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}<emphasis>&lt;#sep&gt;, </emphasis>&lt;/#list&gt;</programlisting>
 
@@ -643,7 +643,7 @@
             there will be a next item. Hence there's no comma after the last
             fruit.</para>
 
-            <para>Here again, what's if we have 0 fruits? Just printing
+            <para>Here again, what if we have 0 fruits? Just printing
             <quote>Fruits:</quote> and then nothing is awkward. A
             <literal>list</literal>, just like an <literal>if</literal>, can
             have an <literal>else</literal>, which is executed if there were 0


[23/24] incubator-freemarker git commit: Made `+` operator when adding two hashes significantly faster (be removing the overhead caused be throwing and then catching an exception).

Posted by dd...@apache.org.
Made `+` operator when adding two hashes significantly faster (be removing the overhead caused be throwing and then catching an exception).


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/4b989f89
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/4b989f89
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/4b989f89

Branch: refs/heads/2.3
Commit: 4b989f89ba54b0ba309b7385e56e2ecf2466ffef
Parents: 496ddfb
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 6 23:25:42 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 6 23:25:55 2016 +0100

----------------------------------------------------------------------
 .../freemarker/core/AddConcatExpression.java    | 58 ++++++++++++++------
 src/main/java/freemarker/core/EvalUtil.java     | 26 +++++++--
 src/manual/en_US/book.xml                       |  4 +-
 3 files changed, 65 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b989f89/src/main/java/freemarker/core/AddConcatExpression.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/AddConcatExpression.java b/src/main/java/freemarker/core/AddConcatExpression.java
index 4dbfd78..5523118 100644
--- a/src/main/java/freemarker/core/AddConcatExpression.java
+++ b/src/main/java/freemarker/core/AddConcatExpression.java
@@ -74,11 +74,26 @@ final class AddConcatExpression extends Expression {
         } else if (leftModel instanceof TemplateSequenceModel && rightModel instanceof TemplateSequenceModel) {
             return new ConcatenatedSequence((TemplateSequenceModel) leftModel, (TemplateSequenceModel) rightModel);
         } else {
+            boolean hashConcatPossible
+                    = leftModel instanceof TemplateHashModel && rightModel instanceof TemplateHashModel;
             try {
+                // We try string addition first. If hash addition is possible, then instead of throwing exception
+                // we return null and do hash addition instead. (We can't simply give hash addition a priority, like
+                // with sequence addition above, as FTL strings are often also FTL hashes.)
                 Object leftOMOrStr = EvalUtil.coerceModelToStringOrMarkup(
-                        leftModel, leftExp, (String) null, env);
+                        leftModel, leftExp, /* returnNullOnNonCoercableType = */ hashConcatPossible, (String) null,
+                        env);
+                if (leftOMOrStr == null) {
+                    return _eval_concatenateHashes(leftModel, rightModel);
+                }
+
+                // Same trick with null return as above.
                 Object rightOMOrStr = EvalUtil.coerceModelToStringOrMarkup(
-                        rightModel, rightExp, (String) null, env);
+                        rightModel, rightExp, /* returnNullOnNonCoercableType = */ hashConcatPossible, (String) null,
+                        env);
+                if (rightOMOrStr == null) {
+                    return _eval_concatenateHashes(leftModel, rightModel);
+                }
 
                 if (leftOMOrStr instanceof String) {
                     if (rightOMOrStr instanceof String) {
@@ -98,25 +113,14 @@ final class AddConcatExpression extends Expression {
                     } else { // rightOMOrStr instanceof TemplateMarkupOutputModel
                         return EvalUtil.concatMarkupOutputs(parent,
                                 leftMO,
-                                (TemplateMarkupOutputModel) rightOMOrStr);
+                                (TemplateMarkupOutputModel<?>) rightOMOrStr);
                     }
                 }
             } catch (NonStringOrTemplateOutputException e) {
-                if (leftModel instanceof TemplateHashModel && rightModel instanceof TemplateHashModel) {
-                    if (leftModel instanceof TemplateHashModelEx && rightModel instanceof TemplateHashModelEx) {
-                        TemplateHashModelEx leftModelEx = (TemplateHashModelEx) leftModel;
-                        TemplateHashModelEx rightModelEx = (TemplateHashModelEx) rightModel;
-                        if (leftModelEx.size() == 0) {
-                            return rightModelEx;
-                        } else if (rightModelEx.size() == 0) {
-                            return leftModelEx;
-                        } else {
-                            return new ConcatenatedHashEx(leftModelEx, rightModelEx);
-                        }
-                    } else {
-                        return new ConcatenatedHash((TemplateHashModel) leftModel,
-                                                    (TemplateHashModel) rightModel);
-                    }
+                // 2.4: Remove this catch; it's for BC, after reworking hash addition so it doesn't rely on this. But
+                // user code might throws this (very unlikely), and then in 2.3.x we did catch that too, incorrectly.
+                if (hashConcatPossible) {
+                    return _eval_concatenateHashes(leftModel, rightModel);
                 } else {
                     throw e;
                 }
@@ -124,6 +128,24 @@ final class AddConcatExpression extends Expression {
         }
     }
 
+    private static TemplateModel _eval_concatenateHashes(TemplateModel leftModel, TemplateModel rightModel)
+            throws TemplateModelException {
+        if (leftModel instanceof TemplateHashModelEx && rightModel instanceof TemplateHashModelEx) {
+            TemplateHashModelEx leftModelEx = (TemplateHashModelEx) leftModel;
+            TemplateHashModelEx rightModelEx = (TemplateHashModelEx) rightModel;
+            if (leftModelEx.size() == 0) {
+                return rightModelEx;
+            } else if (rightModelEx.size() == 0) {
+                return leftModelEx;
+            } else {
+                return new ConcatenatedHashEx(leftModelEx, rightModelEx);
+            }
+        } else {
+            return new ConcatenatedHash((TemplateHashModel) leftModel,
+                                        (TemplateHashModel) rightModel);
+        }
+    }
+
     static TemplateModel _evalOnNumbers(Environment env, TemplateObject parent, Number first, Number second)
             throws TemplateException {
         ArithmeticEngine ae = EvalUtil.getArithmeticEngine(env, parent);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b989f89/src/main/java/freemarker/core/EvalUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/EvalUtil.java b/src/main/java/freemarker/core/EvalUtil.java
index 886308c..5580a40 100644
--- a/src/main/java/freemarker/core/EvalUtil.java
+++ b/src/main/java/freemarker/core/EvalUtil.java
@@ -27,6 +27,7 @@ import freemarker.template.TemplateBooleanModel;
 import freemarker.template.TemplateCollectionModel;
 import freemarker.template.TemplateDateModel;
 import freemarker.template.TemplateException;
+import freemarker.template.TemplateHashModel;
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelException;
 import freemarker.template.TemplateNumberModel;
@@ -349,9 +350,22 @@ class EvalUtil {
      *            Tip to display if the value type is not coercable, but it's sequence or collection.
      * 
      * @return Never {@code null}
+     * @throws TemplateException 
      */
     static Object coerceModelToStringOrMarkup(TemplateModel tm, Expression exp, String seqTip, Environment env)
             throws TemplateException {
+        return coerceModelToStringOrMarkup(tm, exp, false, seqTip, env);
+    }
+    
+    /**
+     * @return {@code null} if the {@code returnNullOnNonCoercableType} parameter is {@code true}, and the coercion is
+     *         not possible, because of the type is not right for it.
+     * 
+     * @see #coerceModelToStringOrMarkup(TemplateModel, Expression, String, Environment)
+     */
+    static Object coerceModelToStringOrMarkup(
+            TemplateModel tm, Expression exp, boolean returnNullOnNonCoercableType, String seqTip, Environment env)
+            throws TemplateException {
         if (tm instanceof TemplateNumberModel) {
             TemplateNumberModel tnm = (TemplateNumberModel) tm; 
             TemplateNumberFormat format = env.getTemplateNumberFormat(exp, false);
@@ -371,7 +385,7 @@ class EvalUtil {
         } else if (tm instanceof TemplateMarkupOutputModel) {
             return tm;
         } else { 
-            return coerceModelToTextualCommon(tm, exp, seqTip, true, env);
+            return coerceModelToTextualCommon(tm, exp, seqTip, true, returnNullOnNonCoercableType, env);
         }
     }
 
@@ -404,7 +418,7 @@ class EvalUtil {
                 throw MessageUtil.newCantFormatDateException(format, exp, e, false);
             }
         } else { 
-            return coerceModelToTextualCommon(tm, exp, seqTip, false, env);
+            return coerceModelToTextualCommon(tm, exp, seqTip, false, false, env);
         }
     }
 
@@ -424,7 +438,7 @@ class EvalUtil {
         } else if (tm instanceof TemplateDateModel) {
             return assertFormatResultNotNull(env.formatDateToPlainText((TemplateDateModel) tm, exp, false));
         } else {
-            return coerceModelToTextualCommon(tm, exp, seqTip, false, env);
+            return coerceModelToTextualCommon(tm, exp, seqTip, false, false, env);
         }
     }
 
@@ -438,7 +452,8 @@ class EvalUtil {
      * @return Never {@code null}
      */
     private static String coerceModelToTextualCommon(
-            TemplateModel tm, Expression exp, String seqHint, boolean supportsTOM, Environment env)
+            TemplateModel tm, Expression exp, String seqHint, boolean supportsTOM, boolean returnNullOnNonCoercableType,
+            Environment env)
             throws TemplateModelException, InvalidReferenceException, TemplateException,
                     NonStringOrTemplateOutputException, NonStringException {
         if (tm instanceof TemplateScalarModel) {
@@ -481,6 +496,9 @@ class EvalUtil {
             if (env.isClassicCompatible() && tm instanceof BeanModel) {
                 return _BeansAPI.getAsClassicCompatibleString((BeanModel) tm);
             }
+            if (returnNullOnNonCoercableType) {
+                return null;
+            }
             if (seqHint != null && (tm instanceof TemplateSequenceModel || tm instanceof TemplateCollectionModel)) {
                 if (supportsTOM) {
                     throw new NonStringOrTemplateOutputException(exp, tm, seqHint, env);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4b989f89/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 4adf154..6424689 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26648,7 +26648,9 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
           <itemizedlist>
             <listitem>
-              <para>FIXME</para>
+              <para>Made <literal>+</literal> operator when adding two hashes
+              significantly faster (be removing the overhead caused be
+              throwing and then catching an exception).</para>
             </listitem>
           </itemizedlist>
         </section>


[17/24] incubator-freemarker git commit: Setting version to 2.3.26-nightly. Also cleaned up version related testing a bit.

Posted by dd...@apache.org.
Setting version to 2.3.26-nightly. Also cleaned up version related testing a bit.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/cded5be7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/cded5be7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/cded5be7

Branch: refs/heads/2.3
Commit: cded5be79eb22bca2735275c239cd87bfe25ec27
Parents: ad4d726
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 3 15:15:12 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Dec 3 15:24:05 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/template/Configuration.java     |  3 +++
 src/main/java/freemarker/template/_TemplateAPI.java      |  1 +
 src/main/resources/freemarker/version.properties         |  8 ++++----
 .../freemarker/ext/beans/BeansWrapperSingletonsTest.java |  3 ++-
 .../freemarker/template/DefaultObjectWrapperTest.java    |  1 +
 .../freemarker/template/TemplateLanguageVersionTest.java |  3 ++-
 src/test/java/freemarker/test/TestUtil.java              | 11 +++++++++++
 7 files changed, 24 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index a888a60..3d9ec04 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -410,6 +410,9 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
 
     /** FreeMarker version 2.3.25 (an {@link #Configuration(Version) incompatible improvements break-point}) */
     public static final Version VERSION_2_3_25 = new Version(2, 3, 25);
+
+    /** FreeMarker version 2.3.26 (an {@link #Configuration(Version) incompatible improvements break-point}) */
+    public static final Version VERSION_2_3_26 = new Version(2, 3, 26);
     
     /** The default of {@link #getIncompatibleImprovements()}, currently {@link #VERSION_2_3_0}. */
     public static final Version DEFAULT_INCOMPATIBLE_IMPROVEMENTS = Configuration.VERSION_2_3_0;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/main/java/freemarker/template/_TemplateAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/_TemplateAPI.java b/src/main/java/freemarker/template/_TemplateAPI.java
index c3d6e23..0fc702a 100644
--- a/src/main/java/freemarker/template/_TemplateAPI.java
+++ b/src/main/java/freemarker/template/_TemplateAPI.java
@@ -47,6 +47,7 @@ public class _TemplateAPI {
     public static final int VERSION_INT_2_3_23 = Configuration.VERSION_2_3_23.intValue();
     public static final int VERSION_INT_2_3_24 = Configuration.VERSION_2_3_24.intValue();
     public static final int VERSION_INT_2_3_25 = Configuration.VERSION_2_3_25.intValue();
+    public static final int VERSION_INT_2_3_26 = Configuration.VERSION_2_3_26.intValue();
     public static final int VERSION_INT_2_4_0 = Version.intValueFor(2, 4, 0);
     
     public static void checkVersionNotNullAndSupported(Version incompatibleImprovements) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/main/resources/freemarker/version.properties
----------------------------------------------------------------------
diff --git a/src/main/resources/freemarker/version.properties b/src/main/resources/freemarker/version.properties
index 04a41da..35cabc6 100644
--- a/src/main/resources/freemarker/version.properties
+++ b/src/main/resources/freemarker/version.properties
@@ -58,12 +58,12 @@
 # - When the major version number is increased, major backward
 #   compatibility violations are allowed, but still should be avoided.
 # During Apache Incubation, "-incubating" is added to this string.
-version=2.3.25-incubating
+version=2.3.26-nightly_@timestampInVersion@-incubating
 # This exists as oss.sonatype only allows SNAPSHOT and final releases,
 # so instead 2.3.21-rc01 and such we have to use 2.3.21-SNAPSHOT there.
 # For final releases it's the same as "version".
 # During Apache Incubation, "-incubating" is added to this string.
-mavenVersion=2.3.25-incubating
+mavenVersion=2.3.26-SNAPSHOT-incubating
 
 # Version string that conforms to OSGi
 # ------------------------------------
@@ -77,7 +77,7 @@ mavenVersion=2.3.25-incubating
 #   2.4.0.pre01
 #   2.4.0.nightly_@timestampInVersion@
 # During Apache Incubation, "-incubating" is added to this string.
-versionForOSGi=2.3.25.stable-incubating
+versionForOSGi=2.3.26.nightly_@timestampInVersion@-incubating
 
 # Version string that conforms to legacy MF
 # -----------------------------------------
@@ -95,7 +95,7 @@ versionForOSGi=2.3.25.stable-incubating
 # "97 denotes "nightly", 98 denotes "pre", 99 denotes "rc" build.
 # In general, for the nightly/preview/rc Y of version 2.X, the versionForMf is
 # 2.X-1.(99|98).Y. Note the X-1.
-versionForMf=2.3.25
+versionForMf=2.3.25.97
 
 # The date of the build.
 # This should be automatically filled by the building tool (Ant).

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java b/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
index baa8ee2..d4f762f 100644
--- a/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
+++ b/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
@@ -39,6 +39,7 @@ import freemarker.template.TemplateModelException;
 import freemarker.template.TemplateScalarModel;
 import freemarker.template.Version;
 import freemarker.template._TemplateAPI;
+import freemarker.test.TestUtil;
 import junit.framework.TestCase;
 
 public class BeansWrapperSingletonsTest extends TestCase {
@@ -58,7 +59,7 @@ public class BeansWrapperSingletonsTest extends TestCase {
         assertEquals(Configuration.VERSION_2_3_21, new BeansWrapperBuilder(Configuration.VERSION_2_3_21).getIncompatibleImprovements());
         assertEquals(Configuration.VERSION_2_3_0, new BeansWrapperBuilder(Configuration.VERSION_2_3_20).getIncompatibleImprovements());
         try {
-            new BeansWrapperBuilder(new Version(2, 3, 26));
+            new BeansWrapperBuilder(TestUtil.getClosestFutureVersion());
             fail("Maybe you need to update this test for the new FreeMarker version");
         } catch (IllegalArgumentException e) {
             assertThat(e.getMessage(), containsString("upgrade"));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/test/java/freemarker/template/DefaultObjectWrapperTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/DefaultObjectWrapperTest.java b/src/test/java/freemarker/template/DefaultObjectWrapperTest.java
index 70bf263..77d513d 100644
--- a/src/test/java/freemarker/template/DefaultObjectWrapperTest.java
+++ b/src/test/java/freemarker/template/DefaultObjectWrapperTest.java
@@ -91,6 +91,7 @@ public class DefaultObjectWrapperTest {
         expected.add(Configuration.VERSION_2_3_22); // no non-BC change in 2.3.23
         expected.add(Configuration.VERSION_2_3_24);
         expected.add(Configuration.VERSION_2_3_24); // no non-BC change in 2.3.25
+        expected.add(Configuration.VERSION_2_3_24); // no non-BC change in 2.3.26
 
         List<Version> actual = new ArrayList<Version>();
         for (int i = _TemplateAPI.VERSION_INT_2_3_0; i <= Configuration.getVersion().intValue(); i++) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/TemplateLanguageVersionTest.java b/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
index 97dc183..7d60c30 100644
--- a/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
+++ b/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
@@ -27,6 +27,7 @@ import java.io.IOException;
 import org.junit.Test;
 
 import freemarker.cache.StringTemplateLoader;
+import freemarker.test.TestUtil;
 public class TemplateLanguageVersionTest {
 
     @Test
@@ -37,7 +38,7 @@ public class TemplateLanguageVersionTest {
         testDefaultWithVersion(Configuration.VERSION_2_3_20, Configuration.VERSION_2_3_20);
         testDefaultWithVersion(Configuration.VERSION_2_3_21, Configuration.VERSION_2_3_21);
         try {
-            testDefaultWithVersion(new Version(2, 3, 26), Configuration.VERSION_2_3_21);
+            testDefaultWithVersion(TestUtil.getClosestFutureVersion(), Configuration.VERSION_2_3_21);
             fail("Maybe you need to update this test for the new FreeMarker version");
         } catch (IllegalArgumentException e) {
             assertThat(e.getMessage(), containsString("version"));

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cded5be7/src/test/java/freemarker/test/TestUtil.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/TestUtil.java b/src/test/java/freemarker/test/TestUtil.java
index 9505d55..23669c0 100644
--- a/src/test/java/freemarker/test/TestUtil.java
+++ b/src/test/java/freemarker/test/TestUtil.java
@@ -18,6 +18,9 @@
  */
 package freemarker.test;
 
+import freemarker.template.Configuration;
+import freemarker.template.Version;
+
 public final class TestUtil {
     
     private TestUtil() {
@@ -112,4 +115,12 @@ public final class TestUtil {
         return ftl.substring(0, commentFirstIdx) + ftl.substring(commentLastIdx + afterCommentNLChars + 1);
     }
 
+    /**
+     * Returns the closes FreeMarker version number that doesn't exit yet (so it's illegal).
+     */
+    public static Version getClosestFutureVersion() {
+        Version v = Configuration.getVersion();
+        return new Version(v.getMajor(), v.getMinor(), v.getMicro() + 1);
+    }
+
 }


[16/24] incubator-freemarker git commit: (JavaDoc typo)

Posted by dd...@apache.org.
(JavaDoc typo)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/ad4d7268
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/ad4d7268
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/ad4d7268

Branch: refs/heads/2.3
Commit: ad4d7268e727aed954b8af7c7365aca013e0b264
Parents: d70e8da
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 3 15:14:42 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Dec 3 15:14:42 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/template/TemplateCollectionModelEx.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ad4d7268/src/main/java/freemarker/template/TemplateCollectionModelEx.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/TemplateCollectionModelEx.java b/src/main/java/freemarker/template/TemplateCollectionModelEx.java
index 604eebc..8101f2b 100644
--- a/src/main/java/freemarker/template/TemplateCollectionModelEx.java
+++ b/src/main/java/freemarker/template/TemplateCollectionModelEx.java
@@ -47,7 +47,7 @@ public interface TemplateCollectionModelEx extends TemplateCollectionModel {
     boolean isEmpty() throws TemplateModelException;
 
     /**
-     * Tells if a given value occurs in the collection, accodring the rules of the wrapped collection. As of 2.3.22,
+     * Tells if a given value occurs in the collection, according the rules of the wrapped collection. As of 2.3.22,
      * this interface is not yet utilized by FTL, and certainly it won't be earlier than 2.4.0. The usefulness of this
      * method is questionable, as the equality rules of Java differs from that of FTL, hence, calling this won't be
      * equivalent with {@code ?seq_contains(e)}.


[13/24] incubator-freemarker git commit: Manual: Documented % operator weirdness

Posted by dd...@apache.org.
Manual: Documented % operator weirdness


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/3ccd9e4c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/3ccd9e4c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/3ccd9e4c

Branch: refs/heads/2.3
Commit: 3ccd9e4cfcfd13e4b392a7d9a8ef1f669fef649e
Parents: ed65316
Author: ddekany <dd...@apache.org>
Authored: Thu Oct 13 22:28:00 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Thu Oct 13 22:28:00 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3ccd9e4c/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index ce9b08f..38741d3 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -3286,7 +3286,8 @@ Slicing with right-unlimited ranges:
             </listitem>
 
             <listitem>
-              <para>Modulus (remainder): <literal>%</literal></para>
+              <para>Modulus (remainder) of integer operands:
+              <literal>%</literal></para>
             </listitem>
           </itemizedlist>
 
@@ -3323,8 +3324,6 @@ ${12 % 10}</programlisting>
 
           <programlisting role="template">${3 + "5"}</programlisting>
 
-          <para>will output this:</para>
-
           <programlisting role="output">35</programlisting>
 
           <para>Generally, FreeMarker never converts a string to a number
@@ -3353,6 +3352,26 @@ ${-1.999?int}</programlisting>
 1
 -1
 -1</programlisting>
+
+          <para>Due to historical reasons, the <literal>%</literal> operator
+          works by first truncating the operands to an integer number, and
+          then returning the remainder of the division:</para>
+
+          <programlisting role="template">${12 % 5}   &lt;#-- Prints 2 --&gt;
+${12.9 % 5} &lt;#-- Prints 2 --&gt;
+${12.1 % 5} &lt;#-- Prints 2 --&gt;
+
+${12 % 6}   &lt;#-- Prints 0 --&gt;
+${12 % 6.9} &lt;#-- Prints 0 --&gt;</programlisting>
+
+          <para>The sign of the result of <literal>%</literal> is the same as
+          the sign of the left hand operand, and its absolute value is the
+          same as if both operands where positive:</para>
+
+          <programlisting role="template">${-12 % -5} &lt;#-- Prints -2 --&gt;
+${-12 % 5} &lt;#-- Prints -2 --&gt;
+${12 % -5} &lt;#-- Prints 2 --&gt;
+</programlisting>
         </section>
 
         <section xml:id="dgui_template_exp_comparison">


[22/24] incubator-freemarker git commit: FREEMARKER-42: ?first now works with FTL collections (things that can be listed but doesn't support getting items by index), not only with sequences. The practical importance of this is that ?first now always work

Posted by dd...@apache.org.
FREEMARKER-42: ?first now works with FTL collections (things that can be listed but doesn't support getting items by index), not only with sequences. The practical importance of this is that ?first now always works on Java Set-s (which is useful for Set-s with well defined ordering), while earlier it has failed depending on the object_wrapper configuration setting.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/496ddfbc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/496ddfbc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/496ddfbc

Branch: refs/heads/2.3
Commit: 496ddfbc08c6d3242ab5c31694db152d9c1e4c58
Parents: ed403c8
Author: ddekany <dd...@apache.org>
Authored: Mon Dec 5 00:49:38 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Dec 5 00:49:38 2016 +0100

----------------------------------------------------------------------
 .../freemarker/core/BuiltInsForSequences.java   | 33 ++++++++++--
 src/manual/en_US/book.xml                       | 57 ++++++++++++++++++--
 .../test/templatesuite/TemplateTestCase.java    |  1 +
 .../expected/sequence-builtins.txt              |  7 +++
 .../templates/sequence-builtins.ftl             |  8 ++-
 5 files changed, 98 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/main/java/freemarker/core/BuiltInsForSequences.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltInsForSequences.java b/src/main/java/freemarker/core/BuiltInsForSequences.java
index a12d274..d56a95f 100644
--- a/src/main/java/freemarker/core/BuiltInsForSequences.java
+++ b/src/main/java/freemarker/core/BuiltInsForSequences.java
@@ -138,15 +138,40 @@ class BuiltInsForSequences {
         
     }
     
-    static class firstBI extends BuiltInForSequence {
+    static class firstBI extends BuiltIn {
+        
         @Override
-        TemplateModel calculateResult(TemplateSequenceModel tsm)
+        TemplateModel _eval(Environment env)
+                throws TemplateException {
+            TemplateModel model = target.eval(env);
+            // In 2.3.x only, we prefer TemplateSequenceModel for
+            // backward compatibility. In 2.4.x, we prefer TemplateCollectionModel. 
+            if (model instanceof TemplateSequenceModel && !isBuggySeqButGoodCollection(model)) {
+                return calculateResultForSequence((TemplateSequenceModel) model);
+            } else if (model instanceof TemplateCollectionModel) {
+                return calculateResultForColletion((TemplateCollectionModel) model);
+            } else {
+                throw new NonSequenceOrCollectionException(target, model, env);
+            }
+        }        
+        
+        private TemplateModel calculateResultForSequence(TemplateSequenceModel seq)
         throws TemplateModelException {
-            if (tsm.size() == 0) {
+            if (seq.size() == 0) {
+                return null;
+            }
+            return seq.get(0);
+        }
+        
+        private TemplateModel calculateResultForColletion(TemplateCollectionModel coll)
+        throws TemplateModelException {
+            TemplateModelIterator iter = coll.iterator();
+            if (!iter.hasNext()) {
                 return null;
             }
-            return tsm.get(0);
+            return iter.next();
         }
+        
     }
 
     static class joinBI extends BuiltIn {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index e592d47..4adf154 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -30,7 +30,7 @@
 
     <titleabbrev>Manual</titleabbrev>
 
-    <productname>Freemarker 2.3.25</productname>
+    <productname>Freemarker 2.3.26</productname>
   </info>
 
   <preface role="index.html" xml:id="preface">
@@ -16416,8 +16416,19 @@ N
             <primary>first built-in</primary>
           </indexterm>
 
-          <para>The first subvariable of the sequence. Template processing
-          will die with error if the sequence is empty.</para>
+          <para>Returns the first item of the sequence. Thus
+          <literal><replaceable>value</replaceable>?first</literal> is the
+          same as <literal><replaceable>value</replaceable>[0]</literal>,
+          except that, since FreeMarker 2.3.26,
+          <literal><replaceable>value</replaceable>?first</literal> also works
+          if <literal><replaceable>value</replaceable></literal> doesn't
+          support getting items with numerical index, but still supports to be
+          listed (i.e., with FTL collection values).</para>
+
+          <para>If the sequence or collection is empty, the result will be a
+          missing value (as in
+          <literal><replaceable>empty</replaceable>?first!'No item was
+          found'</literal>).</para>
         </section>
 
         <section xml:id="ref_builtin_join">
@@ -26603,6 +26614,46 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
     <appendix xml:id="app_versions">
       <title>Version history</title>
 
+      <section xml:id="versions_2_3_26">
+        <title>2.3.26 (incubating at Apache)</title>
+
+        <para>Release date: FIXME</para>
+
+        <para><emphasis role="bold">This is a stable, final
+        release.</emphasis> The <quote>incubating</quote> suffix is required
+        by the Apache Software Foundation until the project becomes a fully
+        accepted (graduated) Apache project.</para>
+
+        <section>
+          <title>Changes on the FTL side</title>
+
+          <itemizedlist>
+            <listitem>
+              <para>Bug fixed (<link
+              xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-42">FREEMARKER-42</link>):
+              <literal>?first</literal> now works with FTL collections (things
+              that can be listed but doesn't support getting items by index),
+              not only with sequences. The practical importance of this is
+              that <literal>?first</literal> now always works on Java
+              <literal>Set</literal>-s (which is useful for
+              <literal>Set</literal>-s with well defined ordering), while
+              earlier it has failed depending on the
+              <literal>object_wrapper</literal> configuration setting.</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section>
+          <title>Changes on the Java side</title>
+
+          <itemizedlist>
+            <listitem>
+              <para>FIXME</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+      </section>
+
       <section xml:id="versions_2_3_25">
         <title>2.3.25 (incubating at Apache)</title>
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
index dfac6b3..24b67f8 100644
--- a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
+++ b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
@@ -377,6 +377,7 @@ public class TemplateTestCase extends FileTestCase {
             abcSet.add("b");
             abcSet.add("c");
             dataModel.put("abcSet", abcSet);
+            dataModel.put("abcSetNonSeq", DefaultNonListCollectionAdapter.adapt(abcSet, beansWrapper));
             
             List<String> listWithNull = new ArrayList<String>();
             listWithNull.add("a");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt b/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
index 664c95b..1201da9 100644
--- a/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
+++ b/src/test/resources/freemarker/test/templatesuite/expected/sequence-builtins.txt
@@ -395,3 +395,10 @@ Join
 - (empty)
 - a, b, c.
 - a, b, c.
+
+
+Misc
+----
+
+First of set 1: a
+First of set 2: a
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/496ddfbc/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl b/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
index c431048..1586ad9 100644
--- a/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
+++ b/src/test/resources/freemarker/test/templatesuite/templates/sequence-builtins.ftl
@@ -351,4 +351,10 @@ Join
 - ${listWithNullsOnly?join(", ", "(empty)", ".")}
 - ${abcSet?join(", ", "(empty)", ".")}
 - ${abcCollection?join(", ", "(empty)", ".")}
-<@assertFails message="index 1">${['a', [], 'c']?join(", ", "(empty)", ".")}</@>
\ No newline at end of file
+<@assertFails message="index 1">${['a', [], 'c']?join(", ", "(empty)", ".")}</@>
+
+Misc
+----
+
+First of set 1: ${abcSet?first}
+First of set 2: ${abcSetNonSeq?first}
\ No newline at end of file


[14/24] incubator-freemarker git commit: Manual: Added missing "since" to outputformat documentation

Posted by dd...@apache.org.
Manual: Added missing "since" to outputformat documentation


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/bc5f45b1
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/bc5f45b1
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/bc5f45b1

Branch: refs/heads/2.3
Commit: bc5f45b1b498fd2c5d8d2ff38f414551241520e7
Parents: 3ccd9e4
Author: ddekany <dd...@apache.org>
Authored: Sun Oct 23 15:22:31 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sun Oct 23 15:22:31 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bc5f45b1/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 38741d3..e592d47 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -21355,8 +21355,10 @@ ${"&amp;"}</programlisting>
             </listitem>
           </itemizedlist>
 
-          <para>Camel case name variant:
-          <literal>outputFormat</literal></para>
+          <para>Camel case name variant: <literal>outputFormat</literal><note>
+              <para><literal>outputformat</literal> exists since FreeMarker
+              2.3.24.</para>
+            </note></para>
         </section>
 
         <section>


[11/24] incubator-freemarker git commit: (JavaDoc typo fix)

Posted by dd...@apache.org.
(JavaDoc typo fix)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/84c26cc0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/84c26cc0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/84c26cc0

Branch: refs/heads/2.3
Commit: 84c26cc0676df5404df661f7fe6770fc5c3f6618
Parents: 479ea6c
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 28 20:09:07 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 28 20:09:07 2016 +0200

----------------------------------------------------------------------
 src/main/java/freemarker/ext/beans/MethodAppearanceFineTuner.java | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/84c26cc0/src/main/java/freemarker/ext/beans/MethodAppearanceFineTuner.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/MethodAppearanceFineTuner.java b/src/main/java/freemarker/ext/beans/MethodAppearanceFineTuner.java
index 2198772..eeefb68 100644
--- a/src/main/java/freemarker/ext/beans/MethodAppearanceFineTuner.java
+++ b/src/main/java/freemarker/ext/beans/MethodAppearanceFineTuner.java
@@ -35,12 +35,11 @@ import freemarker.ext.beans.BeansWrapper.MethodAppearanceDecisionInput;
 public interface MethodAppearanceFineTuner {
 
     /**
-     * <b>Experimental method; subject to change!</b>
      * Implement this to tweak certain aspects of how methods appear in the
      * data-model. {@link BeansWrapper} will pass in all Java methods here that
      * it intends to expose in the data-model as methods (so you can do
      * <tt>obj.foo()</tt> in the template).
-     * With this method it you can do the following tweaks:
+     * With this method you can do the following tweaks:
      * <ul>
      *   <li>Hide a method that would be otherwise shown by calling
      *     {@link MethodAppearanceDecision#setExposeMethodAs(String)}


[24/24] incubator-freemarker git commit: Merge remote-tracking branch 'origin/2.3-gae' into 2.3

Posted by dd...@apache.org.
Merge remote-tracking branch 'origin/2.3-gae' into 2.3


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/44201a6d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/44201a6d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/44201a6d

Branch: refs/heads/2.3
Commit: 44201a6d1701ac66c2dfec8eb98e3f374a47496f
Parents: dd7a2aa 4b989f8
Author: ddekany <dd...@apache.org>
Authored: Tue Dec 6 23:27:36 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Dec 6 23:27:36 2016 +0100

----------------------------------------------------------------------
 .../freemarker/core/AddConcatExpression.java    |  58 ++-
 .../freemarker/core/BuiltInsForSequences.java   |  33 +-
 src/main/java/freemarker/core/EvalUtil.java     |  26 +-
 src/main/java/freemarker/core/NewBI.java        |   8 +-
 .../debug/impl/RmiDebuggedEnvironmentImpl.java  |   2 +-
 .../freemarker/ext/beans/ArgumentTypes.java     |  75 ++-
 .../java/freemarker/ext/beans/BeanModel.java    |  94 ++--
 .../java/freemarker/ext/beans/BeansWrapper.java |  89 ++--
 .../ext/beans/BeansWrapperBuilder.java          |  17 +-
 .../freemarker/ext/beans/ClassIntrospector.java | 157 ++++---
 .../ext/beans/MethodAppearanceFineTuner.java    |   3 +-
 .../java/freemarker/ext/beans/_BeansAPI.java    |  70 +--
 .../freemarker/ext/util/IdentityHashMap.java    |   9 +-
 .../java/freemarker/ext/util/ModelCache.java    |  19 +-
 .../template/AdapterTemplateModel.java          |   2 +-
 .../java/freemarker/template/Configuration.java |   3 +
 .../template/DefaultObjectWrapper.java          |  23 +-
 .../template/DefaultObjectWrapperBuilder.java   |  18 +-
 .../template/ObjectWrapperAndUnwrapper.java     |   2 +-
 .../freemarker/template/SimpleSequence.java     |   2 +-
 .../template/TemplateCollectionModelEx.java     |   2 +-
 .../java/freemarker/template/_TemplateAPI.java  |   3 +-
 .../resources/freemarker/version.properties     |   8 +-
 src/manual/en_US/book.xml                       | 459 +++++++++++--------
 src/manual/en_US/docgen.cjson                   |   2 +-
 src/test/java/freemarker/core/ASTTest.java      |   2 +-
 .../ext/beans/BeansAPINewInstanceTest.java      |   6 +-
 .../ext/beans/BeansWrapperSingletonsTest.java   |   3 +-
 .../template/DefaultObjectWrapperTest.java      |   1 +
 .../template/TemplateLanguageVersionTest.java   |   3 +-
 .../CopyrightCommentRemoverTemplateLoader.java  |   1 +
 src/test/java/freemarker/test/TemplateTest.java |   1 +
 src/test/java/freemarker/test/TestUtil.java     | 115 -----
 .../freemarker/test/servlet/WebAppTestCase.java |   2 +-
 .../test/templatesuite/TemplateTestCase.java    |  46 +-
 .../test/templatesuite/TemplateTestSuite.java   |   2 +-
 .../models/OverloadedMethods2.java              | 144 +++---
 .../freemarker/test/utility/FileTestCase.java   |   1 -
 .../java/freemarker/test/utility/Helpers.java   | 164 -------
 .../java/freemarker/test/utility/TestUtil.java  | 266 +++++++++++
 .../expected/sequence-builtins.txt              |   7 +
 .../templates/sequence-builtins.ftl             |   8 +-
 42 files changed, 1078 insertions(+), 878 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/44201a6d/src/main/resources/freemarker/version.properties
----------------------------------------------------------------------


[18/24] incubator-freemarker git commit: (Bit of test code cleanup.)

Posted by dd...@apache.org.
(Bit of test code cleanup.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/5be880de
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/5be880de
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/5be880de

Branch: refs/heads/2.3
Commit: 5be880de56fda5a5650d27376f05e87dc08829be
Parents: cded5be
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 3 15:28:02 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Dec 3 15:28:02 2016 +0100

----------------------------------------------------------------------
 src/test/java/freemarker/core/ASTTest.java      |   2 +-
 .../ext/beans/BeansAPINewInstanceTest.java      |   6 +-
 .../ext/beans/BeansWrapperSingletonsTest.java   |   2 +-
 .../template/TemplateLanguageVersionTest.java   |   2 +-
 .../CopyrightCommentRemoverTemplateLoader.java  |   1 +
 src/test/java/freemarker/test/TemplateTest.java |   1 +
 src/test/java/freemarker/test/TestUtil.java     | 126 ---------
 .../freemarker/test/servlet/WebAppTestCase.java |   2 +-
 .../models/OverloadedMethods2.java              | 144 +++++-----
 .../freemarker/test/utility/FileTestCase.java   |   1 -
 .../java/freemarker/test/utility/Helpers.java   | 164 ------------
 .../java/freemarker/test/utility/TestUtil.java  | 266 +++++++++++++++++++
 12 files changed, 347 insertions(+), 370 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/core/ASTTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ASTTest.java b/src/test/java/freemarker/core/ASTTest.java
index b1e1729..f31b53c 100644
--- a/src/test/java/freemarker/core/ASTTest.java
+++ b/src/test/java/freemarker/core/ASTTest.java
@@ -24,8 +24,8 @@ import java.io.IOException;
 
 import freemarker.core.ASTPrinter.Options;
 import freemarker.template.utility.StringUtil;
-import freemarker.test.TestUtil;
 import freemarker.test.utility.FileTestCase;
+import freemarker.test.utility.TestUtil;
 
 public class ASTTest extends FileTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/ext/beans/BeansAPINewInstanceTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/beans/BeansAPINewInstanceTest.java b/src/test/java/freemarker/ext/beans/BeansAPINewInstanceTest.java
index ebc679c..d8e5d3a 100644
--- a/src/test/java/freemarker/ext/beans/BeansAPINewInstanceTest.java
+++ b/src/test/java/freemarker/ext/beans/BeansAPINewInstanceTest.java
@@ -21,7 +21,7 @@ package freemarker.ext.beans;
 
 import junit.framework.TestCase;
 import freemarker.template.Configuration;
-import freemarker.test.utility.Helpers;
+import freemarker.test.utility.TestUtil;
 
 public class BeansAPINewInstanceTest extends TestCase {
 
@@ -110,8 +110,8 @@ public class BeansAPINewInstanceTest extends TestCase {
         public Constructors(Integer x, Integer y) { s = "Integer " + x + ", Integer " + y; }
         public Constructors(Object x, Object y) { s = "Object " + x + ", Object " + y; }
 
-        public Constructors(int... xs) { s = "int... " + Helpers.arrayToString(xs); }
-        public Constructors(Object x, int... ys) { s = "Object " + x + ", int... " + Helpers.arrayToString(ys); }
+        public Constructors(int... xs) { s = "int... " + TestUtil.arrayToString(xs); }
+        public Constructors(Object x, int... ys) { s = "Object " + x + ", int... " + TestUtil.arrayToString(ys); }
         
         @Override
         public String toString() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java b/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
index d4f762f..9eedd53 100644
--- a/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
+++ b/src/test/java/freemarker/ext/beans/BeansWrapperSingletonsTest.java
@@ -39,7 +39,7 @@ import freemarker.template.TemplateModelException;
 import freemarker.template.TemplateScalarModel;
 import freemarker.template.Version;
 import freemarker.template._TemplateAPI;
-import freemarker.test.TestUtil;
+import freemarker.test.utility.TestUtil;
 import junit.framework.TestCase;
 
 public class BeansWrapperSingletonsTest extends TestCase {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/TemplateLanguageVersionTest.java b/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
index 7d60c30..490c3c0 100644
--- a/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
+++ b/src/test/java/freemarker/template/TemplateLanguageVersionTest.java
@@ -27,7 +27,7 @@ import java.io.IOException;
 import org.junit.Test;
 
 import freemarker.cache.StringTemplateLoader;
-import freemarker.test.TestUtil;
+import freemarker.test.utility.TestUtil;
 public class TemplateLanguageVersionTest {
 
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java b/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
index 0b5ca05..8c4a48d 100644
--- a/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
+++ b/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
@@ -25,6 +25,7 @@ import java.io.StringReader;
 import org.apache.commons.io.IOUtils;
 
 import freemarker.cache.TemplateLoader;
+import freemarker.test.utility.TestUtil;
 
 public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader {
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/TemplateTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/TemplateTest.java b/src/test/java/freemarker/test/TemplateTest.java
index c4d4e59..5a1cdec 100644
--- a/src/test/java/freemarker/test/TemplateTest.java
+++ b/src/test/java/freemarker/test/TemplateTest.java
@@ -42,6 +42,7 @@ import freemarker.template.Template;
 import freemarker.template.TemplateException;
 import freemarker.template.utility.StringUtil;
 import freemarker.test.templatesuite.TemplateTestSuite;
+import freemarker.test.utility.TestUtil;
 
 /**
  * Superclass of JUnit tests that process templates but aren't practical to implement via {@link TemplateTestSuite}. 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/TestUtil.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/TestUtil.java b/src/test/java/freemarker/test/TestUtil.java
deleted file mode 100644
index 23669c0..0000000
--- a/src/test/java/freemarker/test/TestUtil.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package freemarker.test;
-
-import freemarker.template.Configuration;
-import freemarker.template.Version;
-
-public final class TestUtil {
-    
-    private TestUtil() {
-        // Not meant to be instantiated
-    }
-
-    public static String removeTxtCopyrightComment(String s) {
-        if (!s.startsWith("/*")) {
-            return s;
-        }
-        
-        int commentEnd = s.indexOf("*/");
-        if (commentEnd == -1) {
-            return s;
-        }
-        commentEnd += 2;
-        if (commentEnd < s.length()) {
-            char c = s.charAt(commentEnd);
-            if (c == '\n' || c == '\r') {
-                commentEnd++;
-                if (c == '\r' && commentEnd < s.length()) {
-                    if (s.charAt(commentEnd) == '\n') {
-                        commentEnd++;
-                    }
-                }
-            }
-        }
-        
-        String comment = s.substring(0, commentEnd);
-        int copyrightIdx = comment.indexOf("copyright");
-        if (copyrightIdx == -1) {
-            copyrightIdx = comment.indexOf("Copyright");
-        }
-        if (copyrightIdx == -1) {
-            return s;
-        }
-        
-        return s.substring(commentEnd);
-    }
-    
-    public static String removeFTLCopyrightComment(String ftl) {
-        if (ftl.contains("<#ftl ns_prefixes = {\"D\" : \"http://example.com/eBook\"}>")) {
-            System.out.println();
-        }
-        
-        int copyrightIdx = ftl.indexOf("copyright");
-        if (copyrightIdx == -1) {
-            copyrightIdx = ftl.indexOf("Copyright");
-        }
-        if (copyrightIdx == -1) {
-            return ftl;
-        }
-        
-        final int commentFirstIdx;
-        final boolean squareBracketTagSyntax;
-        {
-            String ftlBeforeCopyright = ftl.substring(0, copyrightIdx);
-            int abCommentStart = ftlBeforeCopyright.lastIndexOf("<#--");
-            int sbCommentStart = ftlBeforeCopyright.lastIndexOf("[#--");
-            squareBracketTagSyntax = sbCommentStart > abCommentStart;
-            commentFirstIdx = squareBracketTagSyntax ? sbCommentStart : abCommentStart;
-            if (commentFirstIdx == -1) {
-                throw new AssertionError("Can't find copyright comment start");
-            }
-        }
-        
-        final int commentLastIdx;
-        {
-            int commentEndStart = ftl.indexOf(squareBracketTagSyntax ? "--]" : "-->", copyrightIdx);
-            if (commentEndStart == -1) {
-                throw new AssertionError("Can't find copyright comment end");
-            }
-            commentLastIdx = commentEndStart + 2;
-        }
-        
-        final int afterCommentNLChars;
-        if (commentLastIdx + 1 < ftl.length()) {
-            char afterCommentChar = ftl.charAt(commentLastIdx + 1);
-            if (afterCommentChar == '\n' || afterCommentChar == '\r') {
-                if (afterCommentChar == '\r' && commentLastIdx + 2 < ftl.length() && ftl.charAt(commentLastIdx + 2) == '\n') {
-                    afterCommentNLChars = 2;
-                } else {
-                    afterCommentNLChars = 1;
-                }
-            } else {
-                afterCommentNLChars = 0;
-            }
-        } else {
-            afterCommentNLChars = 0;
-        }
-            
-        return ftl.substring(0, commentFirstIdx) + ftl.substring(commentLastIdx + afterCommentNLChars + 1);
-    }
-
-    /**
-     * Returns the closes FreeMarker version number that doesn't exit yet (so it's illegal).
-     */
-    public static Version getClosestFutureVersion() {
-        Version v = Configuration.getVersion();
-        return new Version(v.getMajor(), v.getMinor(), v.getMicro() + 1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/servlet/WebAppTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/servlet/WebAppTestCase.java b/src/test/java/freemarker/test/servlet/WebAppTestCase.java
index 6bd7f44..0df5d54 100644
--- a/src/test/java/freemarker/test/servlet/WebAppTestCase.java
+++ b/src/test/java/freemarker/test/servlet/WebAppTestCase.java
@@ -44,7 +44,7 @@ import org.slf4j.LoggerFactory;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import freemarker.test.ResourcesExtractor;
-import freemarker.test.TestUtil;
+import freemarker.test.utility.TestUtil;
 
 public class WebAppTestCase {
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/templatesuite/models/OverloadedMethods2.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/models/OverloadedMethods2.java b/src/test/java/freemarker/test/templatesuite/models/OverloadedMethods2.java
index 9f8e055..833e590 100644
--- a/src/test/java/freemarker/test/templatesuite/models/OverloadedMethods2.java
+++ b/src/test/java/freemarker/test/templatesuite/models/OverloadedMethods2.java
@@ -39,7 +39,7 @@ import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelException;
 import freemarker.template.TemplateNumberModel;
 import freemarker.template.utility.StringUtil;
-import freemarker.test.utility.Helpers;
+import freemarker.test.utility.TestUtil;
 
 public class OverloadedMethods2 {
 
@@ -321,80 +321,80 @@ public class OverloadedMethods2 {
     }
 
     public String varargs1(String s, int... xs) {
-        return "varargs1(String s = " + StringUtil.jQuote(s) + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs1(String s = " + StringUtil.jQuote(s) + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs1(String s, double... xs) {
-        return "varargs1(String s = " + StringUtil.jQuote(s) + ", double... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs1(String s = " + StringUtil.jQuote(s) + ", double... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs1(String s, Object... xs) {
-        return "varargs1(String s = " + StringUtil.jQuote(s) + ", Object... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs1(String s = " + StringUtil.jQuote(s) + ", Object... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs1(Object s, Object... xs) {
-        return "varargs1(Object s = " + s + ", Object... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs1(Object s = " + s + ", Object... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs2(int... xs) {
-        return "varargs2(int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs2(int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs2(double... xs) {
-        return "varargs2(double... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs2(double... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs3(String... xs) {
-        return "varargs3(String... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs3(String... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs3(Comparable... xs) {
-        return "varargs3(Comparable... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs3(Comparable... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs3(Object... xs) {
-        return "varargs3(Object... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs3(Object... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs4(Integer... xs) {
-        return "varargs4(Integer... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs4(Integer... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs4(int... xs) {
-        return "varargs4(int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs4(int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs5(int... xs) {
-        return "varargs5(int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs5(int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs5(int a1, int... xs) {
-        return "varargs5(int a1 = " + a1 + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs5(int a1 = " + a1 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs5(int a1, int a2, int... xs) {
-        return "varargs5(int a1 = " + a1 + ", int a2 = " + a2 + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs5(int a1 = " + a1 + ", int a2 = " + a2 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs5(int a1, int a2, int a3, int... xs) {
         return "varargs5(int a1 = " + a1 + ", int a2 = " + a2 + ", int a3 = " + a3
-                + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+                + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
 
     public String varargs6(String a1, int... xs) {
-        return "varargs6(String a1 = " + a1 + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs6(String a1 = " + a1 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs6(Object a1, int a2, int... xs) {
-        return "varargs6(Object a1 = " + a1 + ", int a2 = " + a2 + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs6(Object a1 = " + a1 + ", int a2 = " + a2 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs7(int... xs) {
-        return "varargs7(int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs7(int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String varargs7(short a1, int... xs) {
-        return "varargs7(short a1 = " + a1 + ", int... xs = " + Helpers.arrayToString(xs) + ")";
+        return "varargs7(short a1 = " + a1 + ", int... xs = " + TestUtil.arrayToString(xs) + ")";
     }
     
     public String mNullAmbiguous(String s) {
@@ -430,11 +430,11 @@ public class OverloadedMethods2 {
     }
     
     public String mVarargsIgnoredTail(int i, double... ds) {
-        return "mVarargsIgnoredTail(int i = " + i + ", double... ds = " + Helpers.arrayToString(ds) + ")"; 
+        return "mVarargsIgnoredTail(int i = " + i + ", double... ds = " + TestUtil.arrayToString(ds) + ")"; 
     }
     
     public String mVarargsIgnoredTail(int... is) {
-        return "mVarargsIgnoredTail(int... is = " + Helpers.arrayToString(is) + ")"; 
+        return "mVarargsIgnoredTail(int... is = " + TestUtil.arrayToString(is) + ")"; 
     }
     
     public String mLowRankWins(int x, int y, Object o) {
@@ -473,19 +473,19 @@ public class OverloadedMethods2 {
     }
 
     public String mSeqToArrayNonOverloaded(String[] items, String s) {
-        return "mSeqToArrayNonOverloaded(String[] " + Helpers.arrayToString(items) + ", String " + s + ")";
+        return "mSeqToArrayNonOverloaded(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
     }
     
     public String mSeqToArrayGoodHint(String[] items, String s) {
-        return "mSeqToArrayGoodHint(String[] " + Helpers.arrayToString(items) + ", String " + s + ")";
+        return "mSeqToArrayGoodHint(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
     }
 
     public String mSeqToArrayGoodHint(String[] items, int i) {
-        return "mSeqToArrayGoodHint(String[] " + Helpers.arrayToString(items) + ", int " + i + ")";
+        return "mSeqToArrayGoodHint(String[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
     }
 
     public String mSeqToArrayGoodHint2(String[] items, String s) {
-        return "mSeqToArrayGoodHint2(String[] " + Helpers.arrayToString(items) + ", String " + s + ")";
+        return "mSeqToArrayGoodHint2(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
     }
 
     public String mSeqToArrayGoodHint2(String item) {
@@ -493,7 +493,7 @@ public class OverloadedMethods2 {
     }
     
     public String mSeqToArrayPoorHint(String[] items, String s) {
-        return "mSeqToArrayPoorHint(String[] " + Helpers.arrayToString(items) + ", String " + s + ")";
+        return "mSeqToArrayPoorHint(String[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
     }
 
     public String mSeqToArrayPoorHint(String item, int i) {
@@ -501,7 +501,7 @@ public class OverloadedMethods2 {
     }
 
     public String mSeqToArrayPoorHint2(String[] items) {
-        return "mSeqToArrayPoorHint2(String[] " + Helpers.arrayToString(items) + ")";
+        return "mSeqToArrayPoorHint2(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mSeqToArrayPoorHint2(String item) {
@@ -509,43 +509,43 @@ public class OverloadedMethods2 {
     }
     
     public String mSeqToArrayPoorHint3(String[] items) {
-        return "mSeqToArrayPoorHint3(String[] " + Helpers.arrayToString(items) + ")";
+        return "mSeqToArrayPoorHint3(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mSeqToArrayPoorHint3(int[] items) {
-        return "mSeqToArrayPoorHint3(int[] " + Helpers.arrayToString(items) + ")";
+        return "mSeqToArrayPoorHint3(int[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVsListPreference(String[] items) {
-        return "mStringArrayVsListPreference(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVsListPreference(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVsListPreference(List items) {
-        return "mStringArrayVsListPreference(List " + Helpers.listToString(items) + ")";
+        return "mStringArrayVsListPreference(List " + TestUtil.listToString(items) + ")";
     }
 
     public String mStringArrayVsObjectArrayPreference(String[] items) {
-        return "mStringArrayVsObjectArrayPreference(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVsObjectArrayPreference(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVsObjectArrayPreference(Object[] items) {
-        return "mStringArrayVsObjectArrayPreference(Object[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVsObjectArrayPreference(Object[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mIntArrayVsIntegerArrayPreference(int[] items) {
-        return "mIntArrayVsIntegerArrayPreference(int[] " + Helpers.arrayToString(items) + ")";
+        return "mIntArrayVsIntegerArrayPreference(int[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mIntArrayVsIntegerArrayPreference(Integer[] items) {
-        return "mIntArrayVsIntegerArrayPreference(Integer[] " + Helpers.arrayToString(items) + ")";
+        return "mIntArrayVsIntegerArrayPreference(Integer[] " + TestUtil.arrayToString(items) + ")";
     }
     
     public String mIntArrayNonOverloaded(int[] items) {
-        return "mIntArrayNonOverloaded(int[] " + Helpers.arrayToString(items) + ")";
+        return "mIntArrayNonOverloaded(int[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mIntegerArrayNonOverloaded(Integer[] items) {
-        return "mIntegerArrayNonOverloaded(Integer[] " + Helpers.arrayToString(items) + ")";
+        return "mIntegerArrayNonOverloaded(Integer[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mIntegerListNonOverloaded(List<Integer> items) {
@@ -557,7 +557,7 @@ public class OverloadedMethods2 {
     }
 
     public String mStringArrayNonOverloaded(String[] items) {
-        return "mStringArrayNonOverloaded(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayNonOverloaded(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mObjectListNonOverloaded(List<Object> items) {
@@ -565,11 +565,11 @@ public class OverloadedMethods2 {
     }
 
     public String mObjectArrayNonOverloaded(Object[] items) {
-        return "mObjectArrayNonOverloaded(Object[] " + Helpers.arrayToString(items) + ")";
+        return "mObjectArrayNonOverloaded(Object[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mIntegerArrayOverloaded(Integer[] items, int i) {
-        return "mIntegerArrayOverloaded(Integer[] " + Helpers.arrayToString(items) + ", int " + i + ")";
+        return "mIntegerArrayOverloaded(Integer[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
     }
 
     public String mIntegerArrayOverloaded(Object obj, boolean b) {
@@ -577,7 +577,7 @@ public class OverloadedMethods2 {
     }
 
     public String mStringArrayOverloaded(String[] items, int i) {
-        return "mStringArrayOverloaded(String[] " + Helpers.arrayToString(items) + ", int " + i + ")";
+        return "mStringArrayOverloaded(String[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
     }
 
     public String mStringArrayOverloaded(Object obj, boolean b) {
@@ -585,11 +585,11 @@ public class OverloadedMethods2 {
     }
 
     public String mCharArrayOverloaded(char[] items, int i) {
-        return "mCharArrayOverloaded(char[] " + Helpers.arrayToString(items) + ", int " + i + ")";
+        return "mCharArrayOverloaded(char[] " + TestUtil.arrayToString(items) + ", int " + i + ")";
     }
 
     public String mCharArrayOverloaded(Character[] items, String s) {
-        return "mCharArrayOverloaded(Character[] " + Helpers.arrayToString(items) + ", String " + s + ")";
+        return "mCharArrayOverloaded(Character[] " + TestUtil.arrayToString(items) + ", String " + s + ")";
     }
     
     public String mCharArrayOverloaded(Object obj, boolean b) {
@@ -597,7 +597,7 @@ public class OverloadedMethods2 {
     }
 
     public String mStringArrayArrayOverloaded(String[][] arrayArray, int i) {
-        return "mStringArrayArrayOverloaded(String[][] " + Helpers.arrayToString(arrayArray) + ", int " + i + ")";
+        return "mStringArrayArrayOverloaded(String[][] " + TestUtil.arrayToString(arrayArray) + ", int " + i + ")";
     }
     
     public String mStringArrayArrayOverloaded(Object obj, boolean b) {
@@ -605,7 +605,7 @@ public class OverloadedMethods2 {
     }
     
     public String mIntArrayArrayOverloaded(int[][] xss) {
-        return "mIntArrayArrayOverloaded(" + Helpers.arrayToString(xss) + ")";
+        return "mIntArrayArrayOverloaded(" + TestUtil.arrayToString(xss) + ")";
     }
 
     public String mIntArrayArrayOverloaded(String s) {
@@ -613,7 +613,7 @@ public class OverloadedMethods2 {
     }
     
     public String mArrayOfListsOverloaded(List[] xss) {
-        return "mArrayOfListsOverloaded(" + Helpers.arrayToString(xss) + ")";
+        return "mArrayOfListsOverloaded(" + TestUtil.arrayToString(xss) + ")";
     }
 
     public String mArrayOfListsOverloaded(String x) {
@@ -621,31 +621,31 @@ public class OverloadedMethods2 {
     }
     
     public String mIntArrayArrayNonOverloaded(int[][] xss) {
-        return "mIntArrayArrayNonOverloaded(" + Helpers.arrayToString(xss) + ")";
+        return "mIntArrayArrayNonOverloaded(" + TestUtil.arrayToString(xss) + ")";
     }
 
     public String mArrayOfListsNonOverloaded(List[] xss) {
-        return "mArrayOfListsNonOverloaded(" + Helpers.arrayToString(xss) + ")";
+        return "mArrayOfListsNonOverloaded(" + TestUtil.arrayToString(xss) + ")";
     }
     
     public String mStringArrayVarargsNonOverloaded(String... items) {
-        return "mStringArrayVarargsNonOverloaded(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsNonOverloaded(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded(String... items) {
-        return "mStringArrayVarargsNonOverloaded(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsNonOverloaded(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded1(String... items) {
-        return "mStringArrayVarargsOverloaded1(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsOverloaded1(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded1(List<String> items) {
-        return "mStringArrayVarargsOverloaded1(List " + Helpers.listToString(items) + ")";
+        return "mStringArrayVarargsOverloaded1(List " + TestUtil.listToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded2(String... items) {
-        return "mStringArrayVarargsOverloaded2(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsOverloaded2(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded2(String item) {
@@ -653,7 +653,7 @@ public class OverloadedMethods2 {
     }
     
     public String mStringArrayVarargsOverloaded3(String... items) {
-        return "mStringArrayVarargsOverloaded3(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsOverloaded3(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded3(String item1, String item2) {
@@ -661,15 +661,15 @@ public class OverloadedMethods2 {
     }
     
     public String mStringArrayVarargsOverloaded4(String... items) {
-        return "mStringArrayVarargsOverloaded4(String[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsOverloaded4(String[] " + TestUtil.arrayToString(items) + ")";
     }
 
     public String mStringArrayVarargsOverloaded4(List... items) {
-        return "mStringArrayVarargsOverloaded4(List[] " + Helpers.arrayToString(items) + ")";
+        return "mStringArrayVarargsOverloaded4(List[] " + TestUtil.arrayToString(items) + ")";
     }
     
     public String mListOrString(List<String> items) {
-        return "mListOrString(List " + Helpers.listToString(items) + ")";
+        return "mListOrString(List " + TestUtil.listToString(items) + ")";
     }
 
     public String mListOrString(String item) {
@@ -677,7 +677,7 @@ public class OverloadedMethods2 {
     }
 
     public String mListListOrString(List<List<Object>> items) {
-        return "mListListOrString(List " + Helpers.listToString(items) + ")";
+        return "mListListOrString(List " + TestUtil.listToString(items) + ")";
     }
 
     public String mListListOrString(String item) {
@@ -693,11 +693,11 @@ public class OverloadedMethods2 {
     }
 
     public String mMapOrBooleanVarargs(Map... v) {
-        return "mMapOrBooleanVarargs(Map... " + Helpers.arrayToString(v) + ")";
+        return "mMapOrBooleanVarargs(Map... " + TestUtil.arrayToString(v) + ")";
     }
 
     public String mMapOrBooleanVarargs(boolean... v) {
-        return "mMapOrBooleanVarargs(boolean... " + Helpers.arrayToString(v) + ")";
+        return "mMapOrBooleanVarargs(boolean... " + TestUtil.arrayToString(v) + ")";
     }
 
     public String mMapOrBooleanFixedAndVarargs(Map v) {
@@ -709,11 +709,11 @@ public class OverloadedMethods2 {
     }
 
     public String mMapOrBooleanFixedAndVarargs(Map... v) {
-        return "mMapOrBooleanFixedAndVarargs(Map... " + Helpers.arrayToString(v) + ")";
+        return "mMapOrBooleanFixedAndVarargs(Map... " + TestUtil.arrayToString(v) + ")";
     }
 
     public String mMapOrBooleanFixedAndVarargs(boolean... v) {
-        return "mMapOrBooleanFixedAndVarargs(boolean... " + Helpers.arrayToString(v) + ")";
+        return "mMapOrBooleanFixedAndVarargs(boolean... " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mNumberOrArray(Number v) {
@@ -721,7 +721,7 @@ public class OverloadedMethods2 {
     }
 
     public String mNumberOrArray(Object[] v) {
-        return "mNumberOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mNumberOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mIntOrArray(int v) {
@@ -729,7 +729,7 @@ public class OverloadedMethods2 {
     }
 
     public String mIntOrArray(Object[] v) {
-        return "mIntOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mIntOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
 
     public String mDateOrArray(Date v) {
@@ -737,7 +737,7 @@ public class OverloadedMethods2 {
     }
 
     public String mDateOrArray(Object[] v) {
-        return "mDateOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mDateOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mStringOrArray(String v) {
@@ -745,7 +745,7 @@ public class OverloadedMethods2 {
     }
 
     public String mStringOrArray(Object[] v) {
-        return "mStringOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mStringOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mBooleanOrArray(boolean v) {
@@ -753,7 +753,7 @@ public class OverloadedMethods2 {
     }
 
     public String mBooleanOrArray(Object[] v) {
-        return "mBooleanOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mBooleanOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mMapOrArray(Map v) {
@@ -761,7 +761,7 @@ public class OverloadedMethods2 {
     }
 
     public String mMapOrArray(Object[] v) {
-        return "mMapOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mMapOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mListOrArray(List v) {
@@ -769,7 +769,7 @@ public class OverloadedMethods2 {
     }
 
     public String mListOrArray(Object[] v) {
-        return "mListOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mListOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mSetOrArray(Set v) {
@@ -777,7 +777,7 @@ public class OverloadedMethods2 {
     }
 
     public String mSetOrArray(Object[] v) {
-        return "mSetOrArray(Object[] " + Helpers.arrayToString(v) + ")";
+        return "mSetOrArray(Object[] " + TestUtil.arrayToString(v) + ")";
     }
     
     public String mCharNonOverloaded(char c) {
@@ -1010,7 +1010,7 @@ public class OverloadedMethods2 {
     }
 
     public String bugReport363(Object... fields) {
-        return "Executed: testMethod(Object... fields) on input: fields=" + Helpers.arrayToString(fields);
+        return "Executed: testMethod(Object... fields) on input: fields=" + TestUtil.arrayToString(fields);
     }
     
     private static class MyAdapterNumberModel implements TemplateNumberModel, AdapterTemplateModel {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/utility/FileTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/utility/FileTestCase.java b/src/test/java/freemarker/test/utility/FileTestCase.java
index 4989fb7..c85496c 100644
--- a/src/test/java/freemarker/test/utility/FileTestCase.java
+++ b/src/test/java/freemarker/test/utility/FileTestCase.java
@@ -33,7 +33,6 @@ import java.net.URL;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import freemarker.template.utility.StringUtil;
-import freemarker.test.TestUtil;
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/utility/Helpers.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/utility/Helpers.java b/src/test/java/freemarker/test/utility/Helpers.java
deleted file mode 100644
index 7f06f7d..0000000
--- a/src/test/java/freemarker/test/utility/Helpers.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package freemarker.test.utility;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-public class Helpers {
-
-    private Helpers() { }
-
-    public static String arrayToString(double[] xs) {
-        StringBuilder sb = new StringBuilder();
-        
-        sb.append('[');
-        for (double x : xs) {
-            if (sb.length() != 1) sb.append(", ");
-            sb.append(x);
-        }
-        sb.append(']');
-        
-        return sb.toString();
-    }
-
-    public static String arrayToString(Object[] array) {
-        if (array == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        for (int i = 0; i < array.length; i++) {
-            if (i != 0) {
-                sb.append(", ");
-            }
-            sb.append(array[i]);
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-
-    public static String arrayToString(Object[][] arrayArray) {
-        if (arrayArray == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        boolean first = true;
-        for (Object[] array : arrayArray) {
-            if (!first) {
-                sb.append(", ");
-            } else {
-                first = false;
-            }
-            sb.append(arrayToString(array));
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-    
-    public static String arrayToString(int[] array) {
-        if (array == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        for (int i = 0; i < array.length; i++) {
-            if (i != 0) {
-                sb.append(", ");
-            }
-            sb.append(array[i]);
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-    
-    public static String arrayToString(int[][] xss) {
-        if (xss == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        for (int i = 0; i < xss.length; i++) {
-            if (i != 0) {
-                sb.append(", ");
-            }
-            sb.append(arrayToString(xss[i]));
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-
-    public static String arrayToString(char[] array) {
-        if (array == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        for (int i = 0; i < array.length; i++) {
-            if (i != 0) {
-                sb.append(", ");
-            }
-            sb.append(array[i]);
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-    
-    public static String arrayToString(boolean[] array) {
-        if (array == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        for (int i = 0; i < array.length; i++) {
-            if (i != 0) {
-                sb.append(", ");
-            }
-            sb.append(array[i]);
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-
-    public static String listToString(List<?> list) {
-        return collectionToString("", list);
-    }
-    
-    
-    public static String setToString(Set<?> list) {
-        return collectionToString("Set", list);
-    }
-    
-    private static String collectionToString(String prefix, Collection<?> list) {
-        if (list == null) return "null";
-        
-        StringBuilder sb = new StringBuilder();
-        sb.append(prefix);
-        sb.append('[');
-        boolean first = true;
-        for (Object item : list) {
-            if (!first) {
-                sb.append(", ");
-            } else {
-                first = false;
-            }
-            sb.append(item instanceof Object[] ? arrayToString((Object[]) item) : item);
-        }
-        sb.append(']');
-        return sb.toString();
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5be880de/src/test/java/freemarker/test/utility/TestUtil.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/utility/TestUtil.java b/src/test/java/freemarker/test/utility/TestUtil.java
new file mode 100644
index 0000000..e12a9fa
--- /dev/null
+++ b/src/test/java/freemarker/test/utility/TestUtil.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package freemarker.test.utility;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import freemarker.template.Configuration;
+import freemarker.template.Version;
+
+/**
+ * Testing related helper methods that didn't fit esewhere.
+ */
+public class TestUtil {
+
+    private TestUtil() { }
+
+    public static String arrayToString(double[] xs) {
+        StringBuilder sb = new StringBuilder();
+        
+        sb.append('[');
+        for (double x : xs) {
+            if (sb.length() != 1) sb.append(", ");
+            sb.append(x);
+        }
+        sb.append(']');
+        
+        return sb.toString();
+    }
+
+    public static String arrayToString(Object[] array) {
+        if (array == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        for (int i = 0; i < array.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(array[i]);
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    public static String arrayToString(Object[][] arrayArray) {
+        if (arrayArray == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        boolean first = true;
+        for (Object[] array : arrayArray) {
+            if (!first) {
+                sb.append(", ");
+            } else {
+                first = false;
+            }
+            sb.append(arrayToString(array));
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+    
+    public static String arrayToString(int[] array) {
+        if (array == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        for (int i = 0; i < array.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(array[i]);
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+    
+    public static String arrayToString(int[][] xss) {
+        if (xss == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        for (int i = 0; i < xss.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(arrayToString(xss[i]));
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    public static String arrayToString(char[] array) {
+        if (array == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        for (int i = 0; i < array.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(array[i]);
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+    
+    public static String arrayToString(boolean[] array) {
+        if (array == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append('[');
+        for (int i = 0; i < array.length; i++) {
+            if (i != 0) {
+                sb.append(", ");
+            }
+            sb.append(array[i]);
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    public static String listToString(List<?> list) {
+        return collectionToString("", list);
+    }
+    
+    
+    public static String setToString(Set<?> list) {
+        return collectionToString("Set", list);
+    }
+    
+    private static String collectionToString(String prefix, Collection<?> list) {
+        if (list == null) return "null";
+        
+        StringBuilder sb = new StringBuilder();
+        sb.append(prefix);
+        sb.append('[');
+        boolean first = true;
+        for (Object item : list) {
+            if (!first) {
+                sb.append(", ");
+            } else {
+                first = false;
+            }
+            sb.append(item instanceof Object[] ? arrayToString((Object[]) item) : item);
+        }
+        sb.append(']');
+        return sb.toString();
+    }
+
+    public static String removeTxtCopyrightComment(String s) {
+        if (!s.startsWith("/*")) {
+            return s;
+        }
+        
+        int commentEnd = s.indexOf("*/");
+        if (commentEnd == -1) {
+            return s;
+        }
+        commentEnd += 2;
+        if (commentEnd < s.length()) {
+            char c = s.charAt(commentEnd);
+            if (c == '\n' || c == '\r') {
+                commentEnd++;
+                if (c == '\r' && commentEnd < s.length()) {
+                    if (s.charAt(commentEnd) == '\n') {
+                        commentEnd++;
+                    }
+                }
+            }
+        }
+        
+        String comment = s.substring(0, commentEnd);
+        int copyrightIdx = comment.indexOf("copyright");
+        if (copyrightIdx == -1) {
+            copyrightIdx = comment.indexOf("Copyright");
+        }
+        if (copyrightIdx == -1) {
+            return s;
+        }
+        
+        return s.substring(commentEnd);
+    }
+
+    public static String removeFTLCopyrightComment(String ftl) {
+        if (ftl.contains("<#ftl ns_prefixes = {\"D\" : \"http://example.com/eBook\"}>")) {
+            System.out.println();
+        }
+        
+        int copyrightIdx = ftl.indexOf("copyright");
+        if (copyrightIdx == -1) {
+            copyrightIdx = ftl.indexOf("Copyright");
+        }
+        if (copyrightIdx == -1) {
+            return ftl;
+        }
+        
+        final int commentFirstIdx;
+        final boolean squareBracketTagSyntax;
+        {
+            String ftlBeforeCopyright = ftl.substring(0, copyrightIdx);
+            int abCommentStart = ftlBeforeCopyright.lastIndexOf("<#--");
+            int sbCommentStart = ftlBeforeCopyright.lastIndexOf("[#--");
+            squareBracketTagSyntax = sbCommentStart > abCommentStart;
+            commentFirstIdx = squareBracketTagSyntax ? sbCommentStart : abCommentStart;
+            if (commentFirstIdx == -1) {
+                throw new AssertionError("Can't find copyright comment start");
+            }
+        }
+        
+        final int commentLastIdx;
+        {
+            int commentEndStart = ftl.indexOf(squareBracketTagSyntax ? "--]" : "-->", copyrightIdx);
+            if (commentEndStart == -1) {
+                throw new AssertionError("Can't find copyright comment end");
+            }
+            commentLastIdx = commentEndStart + 2;
+        }
+        
+        final int afterCommentNLChars;
+        if (commentLastIdx + 1 < ftl.length()) {
+            char afterCommentChar = ftl.charAt(commentLastIdx + 1);
+            if (afterCommentChar == '\n' || afterCommentChar == '\r') {
+                if (afterCommentChar == '\r' && commentLastIdx + 2 < ftl.length() && ftl.charAt(commentLastIdx + 2) == '\n') {
+                    afterCommentNLChars = 2;
+                } else {
+                    afterCommentNLChars = 1;
+                }
+            } else {
+                afterCommentNLChars = 0;
+            }
+        } else {
+            afterCommentNLChars = 0;
+        }
+            
+        return ftl.substring(0, commentFirstIdx) + ftl.substring(commentLastIdx + afterCommentNLChars + 1);
+    }
+
+    /**
+     * Returns the closes FreeMarker version number that doesn't exit yet (so it's illegal).
+     */
+    public static Version getClosestFutureVersion() {
+        Version v = Configuration.getVersion();
+        return new Version(v.getMajor(), v.getMinor(), v.getMicro() + 1);
+    }
+    
+}


[21/24] incubator-freemarker git commit: Utilizing Java 5 generics at some places where it doesn't break backward compatibility.

Posted by dd...@apache.org.
Utilizing Java 5 generics at some places where it doesn't break backward compatibility.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/ed403c83
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/ed403c83
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/ed403c83

Branch: refs/heads/2.3
Commit: ed403c83cb0acd0b221ecc6a1daa1ccd3597c291
Parents: c253e33
Author: ddekany <dd...@apache.org>
Authored: Sun Dec 4 21:48:42 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 4 21:57:29 2016 +0100

----------------------------------------------------------------------
 .../test/templatesuite/TemplateTestCase.java    | 45 +++++++++++---------
 .../test/templatesuite/TemplateTestSuite.java   |  2 +-
 2 files changed, 25 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ed403c83/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
index 9e9b4ff..dfac6b3 100644
--- a/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
+++ b/src/test/java/freemarker/test/templatesuite/TemplateTestCase.java
@@ -52,6 +52,7 @@ import com.google.common.collect.ImmutableSet;
 import freemarker.cache.FileTemplateLoader;
 import freemarker.core.ASTPrinter;
 import freemarker.ext.beans.BeansWrapper;
+import freemarker.ext.beans.BeansWrapperBuilder;
 import freemarker.ext.beans.BooleanModel;
 import freemarker.ext.beans.Java7MembersOnlyBeansWrapper;
 import freemarker.ext.beans.ResourceBundleModel;
@@ -117,7 +118,7 @@ public class TemplateTestCase extends FileTestCase {
     private final boolean noOutput;
     
     private final Configuration conf;
-    private final HashMap dataModel = new HashMap();
+    private final HashMap<String, Object> dataModel = new HashMap<String, Object>();
     
     public TemplateTestCase(String testName, String simpleTestName, String templateName, String expectedFileName, boolean noOutput,
             Version incompatibleImprovements) {
@@ -181,6 +182,8 @@ public class TemplateTestCase extends FileTestCase {
         conf.setTemplateLoader(new CopyrightCommentRemoverTemplateLoader(
                 new FileTemplateLoader(new File(getTestClassDirectory(), "templates"))));
         
+        BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_0).build();
+        
         dataModel.put(ASSERT_VAR_NAME, AssertDirective.INSTANCE);
         dataModel.put(ASSERT_EQUALS_VAR_NAME, AssertEqualsDirective.INSTANCE);
         dataModel.put(ASSERT_FAILS_VAR_NAME, AssertFailsDirective.INSTANCE);
@@ -239,7 +242,7 @@ public class TemplateTestCase extends FileTestCase {
         } else if (simpleTestName.equals("beans")) {
             dataModel.put("array", new String[] { "array-0", "array-1"});
             dataModel.put("list", Arrays.asList(new String[] { "list-0", "list-1", "list-2"}));
-            Map tmap = new HashMap();
+            Map<Object, Object> tmap = new HashMap<Object, Object>();
             tmap.put("key", "value");
             Object objKey = new Object();
             tmap.put(objKey, "objValue");
@@ -248,8 +251,8 @@ public class TemplateTestCase extends FileTestCase {
             dataModel.put("obj", new freemarker.test.templatesuite.models.BeanTestClass());
             dataModel.put("resourceBundle", new ResourceBundleModel(ResourceBundle.getBundle("freemarker.test.templatesuite.models.BeansTestResources"), BeansWrapper.getDefaultInstance()));
             dataModel.put("date", new GregorianCalendar(1974, 10, 14).getTime());
-            dataModel.put("statics", BeansWrapper.getDefaultInstance().getStaticModels());
-            dataModel.put("enums", BeansWrapper.getDefaultInstance().getEnumModels());
+            dataModel.put("statics", beansWrapper.getStaticModels());
+            dataModel.put("enums", beansWrapper.getEnumModels());
         } else if (simpleTestName.equals("boolean")) {
             dataModel.put( "boolean1", TemplateBooleanModel.FALSE);
             dataModel.put( "boolean2", TemplateBooleanModel.TRUE);
@@ -290,23 +293,23 @@ public class TemplateTestCase extends FileTestCase {
             dataModel.put("bigDecimal", new SimpleNumber(java.math.BigDecimal.valueOf(1)));
             dataModel.put("bigDecimal2", new SimpleNumber(java.math.BigDecimal.valueOf(1, 16)));
         } else if (simpleTestName.equals("simplehash-char-key")) {
-            HashMap mStringC = new HashMap();
+            HashMap<String, String> mStringC = new HashMap<String, String>();
             mStringC.put("c", "string");
             dataModel.put("mStringC", mStringC);
             
-            HashMap mStringCNull = new HashMap();
+            HashMap<String, String> mStringCNull = new HashMap<String, String>();
             mStringCNull.put("c", null);
             dataModel.put("mStringCNull", mStringCNull);
             
-            HashMap mCharC = new HashMap();
+            HashMap<Character, String> mCharC = new HashMap<Character, String>();
             mCharC.put(Character.valueOf('c'), "char");
             dataModel.put("mCharC", mCharC);
             
-            HashMap mCharCNull = new HashMap();
+            HashMap<String, String> mCharCNull = new HashMap<String, String>();
             mCharCNull.put("c", null);
             dataModel.put("mCharCNull", mCharCNull);
             
-            HashMap mMixed = new HashMap();
+            HashMap<Object, String> mMixed = new HashMap<Object, String>();
             mMixed.put(Character.valueOf('c'), "char");
             mMixed.put("s", "string");
             mMixed.put("s2", "string2");
@@ -326,8 +329,8 @@ public class TemplateTestCase extends FileTestCase {
         } else if (simpleTestName.startsWith("type-builtins")) {
             dataModel.put("testmethod", new TestMethod());
             dataModel.put("testnode", new TestNode());
-            dataModel.put("testcollection", new SimpleCollection(new ArrayList()));
-            dataModel.put("testcollectionEx", DefaultNonListCollectionAdapter.adapt(new HashSet(), null));
+            dataModel.put("testcollection", new SimpleCollection(new ArrayList<Object>()));
+            dataModel.put("testcollectionEx", DefaultNonListCollectionAdapter.adapt(new HashSet<Object>(), null));
             dataModel.put("bean", new TestBean());
         } else if (simpleTestName.equals("date-type-builtins")) {
             GregorianCalendar cal = new GregorianCalendar(2003, 4 - 1, 5, 6, 7, 8);
@@ -369,19 +372,19 @@ public class TemplateTestCase extends FileTestCase {
             NodeModel nm = NodeModel.parse(is);
             dataModel.put("doc", nm);
         } else if (simpleTestName.startsWith("sequence-builtins")) {
-            Set abcSet = new TreeSet();
+            Set<String> abcSet = new TreeSet<String>();
             abcSet.add("a");
             abcSet.add("b");
             abcSet.add("c");
             dataModel.put("abcSet", abcSet);
             
-            List listWithNull = new ArrayList();
+            List<String> listWithNull = new ArrayList<String>();
             listWithNull.add("a");
             listWithNull.add(null);
             listWithNull.add("c");
             dataModel.put("listWithNull", listWithNull);
             
-            List listWithNullsOnly = new ArrayList();
+            List<String> listWithNullsOnly = new ArrayList<String>();
             listWithNull.add(null);
             listWithNull.add(null);
             listWithNull.add(null);
@@ -389,7 +392,7 @@ public class TemplateTestCase extends FileTestCase {
             
             dataModel.put("abcCollection", new SimpleCollection(abcSet));
             
-            Set set = new HashSet();
+            Set<String> set = new HashSet<String>();
             set.add("a");
             set.add("b");
             set.add("c");
@@ -430,9 +433,9 @@ public class TemplateTestCase extends FileTestCase {
             dataModel.put("bdp", BigDecimal.valueOf(0.05));
           } else if (simpleTestName.startsWith("classic-compatible")) {
             dataModel.put("array", new String[] { "a", "b", "c" });
-            dataModel.put("beansArray", new BeansWrapper().wrap(new String[] { "a", "b", "c" }));
-            dataModel.put("beanTrue", new BeansWrapper().wrap(Boolean.TRUE));
-            dataModel.put("beanFalse", new BeansWrapper().wrap(Boolean.FALSE));
+            dataModel.put("beansArray", beansWrapper.wrap(new String[] { "a", "b", "c" }));
+            dataModel.put("beanTrue", beansWrapper.wrap(Boolean.TRUE));
+            dataModel.put("beanFalse", beansWrapper.wrap(Boolean.FALSE));
         } else if (simpleTestName.startsWith("overloaded-methods-2-")) {
             dataModel.put("obj", new OverloadedMethods2());
             final boolean dow = conf.getObjectWrapper() instanceof DefaultObjectWrapper;
@@ -499,7 +502,7 @@ public class TemplateTestCase extends FileTestCase {
     }
     
     static class TestMethod implements TemplateMethodModel {
-      public Object exec(java.util.List arguments) {
+      public Object exec(List arguments) {
           return "x";
       }
     }
@@ -528,14 +531,14 @@ public class TemplateTestCase extends FileTestCase {
     }
 
    public Object getTestMapBean() {
-        Map testBean = new TestMapBean();
+        Map<String, Object> testBean = new TestMapBean();
         testBean.put("name", "Chris");
         testBean.put("location", "San Francisco");
         testBean.put("age", Integer.valueOf(27));
         return testBean;
     }
 
-    public static class TestMapBean extends HashMap {
+    public static class TestMapBean extends HashMap<String, Object> {
         public String getName() {
             return "Christopher";
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ed403c83/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java b/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
index dd0a74c..2ba6dac 100644
--- a/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
+++ b/src/test/java/freemarker/test/templatesuite/TemplateTestSuite.java
@@ -82,7 +82,7 @@ public class TemplateTestSuite extends TestSuite {
     public static final String INCOMPATIBLE_IMPROVEMENTS_PROPERTY_NAME
             = "freemareker.templateTestSuite.incompatibleImprovements";
     
-    private final Map<String, String> testSuiteSettings = new LinkedHashMap();
+    private final Map<String, String> testSuiteSettings = new LinkedHashMap<String, String>();
 
     private final ArrayList<Version> testSuiteIcis;
 


[19/24] incubator-freemarker git commit: Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Replaceding freemarker.ext.util.IdentityHashMap usages with java.util.IdentityHashMap. Some internal naming cleanup.

Posted by dd...@apache.org.
Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Replaceding freemarker.ext.util.IdentityHashMap usages with java.util.IdentityHashMap. Some internal naming cleanup.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/277956d9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/277956d9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/277956d9

Branch: refs/heads/2.3
Commit: 277956d94a5e5972f47f24188ea1c48b13d6b70b
Parents: 5be880d
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 3 19:29:35 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 4 13:19:27 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/NewBI.java        |   8 +-
 .../debug/impl/RmiDebuggedEnvironmentImpl.java  |   2 +-
 .../freemarker/ext/beans/ArgumentTypes.java     |  75 +++++----
 .../java/freemarker/ext/beans/BeanModel.java    |   6 +-
 .../java/freemarker/ext/beans/BeansWrapper.java |  87 ++++++-----
 .../ext/beans/BeansWrapperBuilder.java          |  17 +-
 .../freemarker/ext/beans/ClassIntrospector.java | 156 ++++++++++---------
 .../java/freemarker/ext/beans/_BeansAPI.java    |  70 +++++----
 .../freemarker/ext/util/IdentityHashMap.java    |   9 +-
 .../java/freemarker/ext/util/ModelCache.java    |  19 ++-
 .../template/DefaultObjectWrapper.java          |  23 +--
 .../template/DefaultObjectWrapperBuilder.java   |  18 ++-
 .../template/ObjectWrapperAndUnwrapper.java     |   2 +-
 .../java/freemarker/template/_TemplateAPI.java  |   2 -
 14 files changed, 264 insertions(+), 230 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/core/NewBI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/NewBI.java b/src/main/java/freemarker/core/NewBI.java
index c7842de..eddd823 100644
--- a/src/main/java/freemarker/core/NewBI.java
+++ b/src/main/java/freemarker/core/NewBI.java
@@ -21,6 +21,7 @@ package freemarker.core;
 
 import java.util.List;
 
+import freemarker.ext.beans.BeanModel;
 import freemarker.ext.beans.BeansWrapper;
 import freemarker.template.ObjectWrapper;
 import freemarker.template.Template;
@@ -35,8 +36,7 @@ import freemarker.template.TemplateModelException;
  */
 class NewBI extends BuiltIn {
     
-    static final Class BEAN_MODEL_CLASS = freemarker.ext.beans.BeanModel.class;
-    static Class JYTHON_MODEL_CLASS;
+    static Class<?> JYTHON_MODEL_CLASS;
     static {
         try {
             JYTHON_MODEL_CLASS = Class.forName("freemarker.ext.jython.JythonModel");
@@ -53,7 +53,7 @@ class NewBI extends BuiltIn {
 
     class ConstructorFunction implements TemplateMethodModelEx {
 
-        private final Class cl;
+        private final Class<?> cl;
         private final Environment env;
         
         public ConstructorFunction(String classname, Environment env, Template template) throws TemplateException {
@@ -63,7 +63,7 @@ class NewBI extends BuiltIn {
                 throw new _MiscTemplateException(NewBI.this, env,
                         "Class ", cl.getName(), " does not implement freemarker.template.TemplateModel");
             }
-            if (BEAN_MODEL_CLASS.isAssignableFrom(cl)) {
+            if (BeanModel.class.isAssignableFrom(cl)) {
                 throw new _MiscTemplateException(NewBI.this, env,
                         "Bean Models cannot be instantiated using the ?", key, " built-in");
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java b/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
index 8bb1b3c..ec6e5a4 100644
--- a/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
+++ b/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
@@ -27,6 +27,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -38,7 +39,6 @@ import freemarker.core.Configurable;
 import freemarker.core.Environment;
 import freemarker.debug.DebugModel;
 import freemarker.debug.DebuggedEnvironment;
-import freemarker.ext.util.IdentityHashMap;
 import freemarker.template.Configuration;
 import freemarker.template.SimpleCollection;
 import freemarker.template.SimpleScalar;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/ArgumentTypes.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/ArgumentTypes.java b/src/main/java/freemarker/ext/beans/ArgumentTypes.java
index 11f1b77..e383259 100644
--- a/src/main/java/freemarker/ext/beans/ArgumentTypes.java
+++ b/src/main/java/freemarker/ext/beans/ArgumentTypes.java
@@ -54,7 +54,7 @@ final class ArgumentTypes {
     /**
      * The types of the arguments; for varags this contains the exploded list (not the array). 
      */
-    private final Class[] types;
+    private final Class<?>[] types;
     
     private final boolean bugfixed;
     
@@ -65,7 +65,7 @@ final class ArgumentTypes {
      */
     ArgumentTypes(Object[] args, boolean bugfixed) {
         int ln = args.length;
-        Class[] typesTmp = new Class[ln];
+        Class<?>[] typesTmp = new Class[ln];
         for (int i = 0; i < ln; ++i) {
             Object arg = args[i];
             typesTmp[i] = arg == null
@@ -109,22 +109,21 @@ final class ArgumentTypes {
      *         {@link EmptyCallableMemberDescriptor#AMBIGUOUS_METHOD}. 
      */
     MaybeEmptyCallableMemberDescriptor getMostSpecific(
-            List/*<ReflectionCallableMemberDescriptor>*/ memberDescs, boolean varArg) {
-        LinkedList/*<ReflectionCallableMemberDescriptor>*/ applicables = getApplicables(memberDescs, varArg);
+            List<ReflectionCallableMemberDescriptor> memberDescs, boolean varArg) {
+        LinkedList<CallableMemberDescriptor> applicables = getApplicables(memberDescs, varArg);
         if (applicables.isEmpty()) {
             return EmptyCallableMemberDescriptor.NO_SUCH_METHOD;
         }
         if (applicables.size() == 1) {
-            return (CallableMemberDescriptor) applicables.getFirst();
+            return applicables.getFirst();
         }
         
-        LinkedList/*<CallableMemberDescriptor>*/ maximals = new LinkedList();
-        for (Iterator applicablesIter = applicables.iterator(); applicablesIter.hasNext(); ) {
-            CallableMemberDescriptor applicable = (CallableMemberDescriptor) applicablesIter.next();
+        LinkedList<CallableMemberDescriptor> maximals = new LinkedList<CallableMemberDescriptor>();
+        for (CallableMemberDescriptor applicable : applicables) {
             boolean lessSpecific = false;
-            for (Iterator maximalsIter = maximals.iterator(); 
+            for (Iterator<CallableMemberDescriptor> maximalsIter = maximals.iterator(); 
                 maximalsIter.hasNext(); ) {
-                CallableMemberDescriptor maximal = (CallableMemberDescriptor) maximalsIter.next();
+                CallableMemberDescriptor maximal = maximalsIter.next();
                 final int cmpRes = compareParameterListPreferability(
                         applicable.getParamTypes(), maximal.getParamTypes(), varArg); 
                 if (cmpRes > 0) {
@@ -140,7 +139,7 @@ final class ArgumentTypes {
         if (maximals.size() > 1) {
             return EmptyCallableMemberDescriptor.AMBIGUOUS_METHOD;
         }
-        return (CallableMemberDescriptor) maximals.getFirst();
+        return maximals.getFirst();
     }
 
     /**
@@ -174,7 +173,7 @@ final class ArgumentTypes {
      * @return More than 0 if the first parameter list is preferred, less then 0 if the other is preferred,
      *        0 if there's no decision 
      */
-    int compareParameterListPreferability(Class[] paramTypes1, Class[] paramTypes2, boolean varArg) {
+    int compareParameterListPreferability(Class<?>[] paramTypes1, Class<?>[] paramTypes2, boolean varArg) {
         final int argTypesLen = types.length; 
         final int paramTypes1Len = paramTypes1.length;
         final int paramTypes2Len = paramTypes2.length;
@@ -191,19 +190,19 @@ final class ArgumentTypes {
             int paramList2VeryStrongWinCnt = 0;
             int firstWinerParamList = 0;
             for (int i = 0; i < argTypesLen; i++) {
-                final Class paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
-                final Class paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
+                final Class<?> paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
+                final Class<?> paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
                 
                 final int winerParam;  // 1 => paramType1; -1 => paramType2; 0 => draw
                 if (paramType1 == paramType2) {
                     winerParam = 0;
                 } else {
-                    final Class argType = types[i];
+                    final Class<?> argType = types[i];
                     final boolean argIsNum = Number.class.isAssignableFrom(argType);
                     
                     final int numConvPrice1;
                     if (argIsNum && ClassUtil.isNumerical(paramType1)) {
-                        final Class nonPrimParamType1 = paramType1.isPrimitive()
+                        final Class<?> nonPrimParamType1 = paramType1.isPrimitive()
                                 ? ClassUtil.primitiveClassToBoxingClass(paramType1) : paramType1; 
                         numConvPrice1 = OverloadedNumberUtil.getArgumentConversionPrice(argType, nonPrimParamType1);
                     } else {
@@ -215,7 +214,7 @@ final class ArgumentTypes {
                     
                     final int numConvPrice2;
                     if (argIsNum && ClassUtil.isNumerical(paramType2)) {
-                        final Class nonPrimParamType2 = paramType2.isPrimitive()
+                        final Class<?> nonPrimParamType2 = paramType2.isPrimitive()
                                 ? ClassUtil.primitiveClassToBoxingClass(paramType2) : paramType2; 
                         numConvPrice2 = OverloadedNumberUtil.getArgumentConversionPrice(argType, nonPrimParamType2);
                     } else {
@@ -357,8 +356,8 @@ final class ArgumentTypes {
                         // index of the varargs parameter, like if we had a single varargs argument. However, this
                         // time we don't have an argument type, so we can only decide based on type specificity:
                         if (argTypesLen == paramTypes1Len - 1) {
-                            Class paramType1 = getParamType(paramTypes1, paramTypes1Len, argTypesLen, true);
-                            Class paramType2 = getParamType(paramTypes2, paramTypes2Len, argTypesLen, true);
+                            Class<?> paramType1 = getParamType(paramTypes1, paramTypes1Len, argTypesLen, true);
+                            Class<?> paramType2 = getParamType(paramTypes2, paramTypes2Len, argTypesLen, true);
                             if (ClassUtil.isNumerical(paramType1) && ClassUtil.isNumerical(paramType2)) {
                                 int r = OverloadedNumberUtil.compareNumberTypeSpecificity(paramType1, paramType2);
                                 if (r != 0) return r;
@@ -380,8 +379,8 @@ final class ArgumentTypes {
             boolean paramTypes1HasAMoreSpecific = false;
             boolean paramTypes2HasAMoreSpecific = false;
             for (int i = 0; i < paramTypes1Len; ++i) {
-                Class paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
-                Class paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
+                Class<?> paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
+                Class<?> paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
                 if (paramType1 != paramType2) {
                     paramTypes1HasAMoreSpecific = 
                         paramTypes1HasAMoreSpecific
@@ -408,12 +407,13 @@ final class ArgumentTypes {
      * @return Less-than-0, 0, or more-than-0 depending on which side is more specific. The absolute value is 1 if
      *     the difference is only in primitive VS non-primitive, more otherwise.
      */
-    private int compareParameterListPreferability_cmpTypeSpecificty(final Class paramType1, final Class paramType2) {
+    private int compareParameterListPreferability_cmpTypeSpecificty(
+            final Class<?> paramType1, final Class<?> paramType2) {
         // The more specific (smaller) type wins.
         
-        final Class nonPrimParamType1 = paramType1.isPrimitive()
+        final Class<?> nonPrimParamType1 = paramType1.isPrimitive()
                 ? ClassUtil.primitiveClassToBoxingClass(paramType1) : paramType1; 
-        final Class nonPrimParamType2 = paramType2.isPrimitive()
+        final Class<?> nonPrimParamType2 = paramType2.isPrimitive()
                 ? ClassUtil.primitiveClassToBoxingClass(paramType2) : paramType2;
                 
         if (nonPrimParamType1 == nonPrimParamType2) {
@@ -441,7 +441,7 @@ final class ArgumentTypes {
         }
     }
 
-    private static Class getParamType(Class[] paramTypes, int paramTypesLen, int i, boolean varArg) {
+    private static Class<?> getParamType(Class<?>[] paramTypes, int paramTypesLen, int i, boolean varArg) {
         return varArg && i >= paramTypesLen - 1
                 ? paramTypes[paramTypesLen - 1].getComponentType()
                 : paramTypes[i];
@@ -451,11 +451,10 @@ final class ArgumentTypes {
      * Returns all methods that are applicable to actual
      * parameter types represented by this ArgumentTypes object.
      */
-    LinkedList/*<ReflectionCallableMemberDescriptor>*/ getApplicables(
-            List/*<ReflectionCallableMemberDescriptor>*/ memberDescs, boolean varArg) {
-        LinkedList applicables = new LinkedList();
-        for (Iterator it = memberDescs.iterator(); it.hasNext(); ) {
-            ReflectionCallableMemberDescriptor memberDesc = (ReflectionCallableMemberDescriptor) it.next();
+    LinkedList<CallableMemberDescriptor> getApplicables(
+            List<ReflectionCallableMemberDescriptor> memberDescs, boolean varArg) {
+        LinkedList<CallableMemberDescriptor> applicables = new LinkedList<CallableMemberDescriptor>();
+        for (ReflectionCallableMemberDescriptor memberDesc : memberDescs) {
             int difficulty = isApplicable(memberDesc, varArg);
             if (difficulty != CONVERSION_DIFFICULTY_IMPOSSIBLE) {
                 if (difficulty == CONVERSION_DIFFICULTY_REFLECTION) {
@@ -478,7 +477,7 @@ final class ArgumentTypes {
      * @return One of the <tt>CONVERSION_DIFFICULTY_...</tt> constants.
      */
     private int isApplicable(ReflectionCallableMemberDescriptor memberDesc, boolean varArg) {
-        final Class[] paramTypes = memberDesc.getParamTypes(); 
+        final Class<?>[] paramTypes = memberDesc.getParamTypes(); 
         final int cl = types.length;
         final int fl = paramTypes.length - (varArg ? 1 : 0);
         if (varArg) {
@@ -502,7 +501,7 @@ final class ArgumentTypes {
             }
         }
         if (varArg) {
-            Class varArgParamType = paramTypes[fl].getComponentType();
+            Class<?> varArgParamType = paramTypes[fl].getComponentType();
             for (int i = fl; i < cl; ++i) {
                 int difficulty = isMethodInvocationConvertible(varArgParamType, types[i]); 
                 if (difficulty == CONVERSION_DIFFICULTY_IMPOSSIBLE) {
@@ -530,12 +529,12 @@ final class ArgumentTypes {
      * 
      * @return One of the <tt>CONVERSION_DIFFICULTY_...</tt> constants.
      */
-    private int isMethodInvocationConvertible(final Class formal, final Class actual) {
+    private int isMethodInvocationConvertible(final Class<?> formal, final Class<?> actual) {
         // Check for identity or widening reference conversion
         if (formal.isAssignableFrom(actual) && actual != CharacterOrString.class) {
             return CONVERSION_DIFFICULTY_REFLECTION;
         } else if (bugfixed) {
-            final Class formalNP;
+            final Class<?> formalNP;
             if (formal.isPrimitive()) {
                 if (actual == Null.class) {
                     return CONVERSION_DIFFICULTY_IMPOSSIBLE;
@@ -684,7 +683,7 @@ final class ArgumentTypes {
         }
 
         @Override
-        Class[] getParamTypes() {
+        Class<?>[] getParamTypes() {
             return callableMemberDesc.getParamTypes();
         }
         
@@ -694,10 +693,10 @@ final class ArgumentTypes {
         }
 
         private void convertArgsToReflectionCompatible(BeansWrapper bw, Object[] args) throws TemplateModelException {
-            Class[] paramTypes = callableMemberDesc.getParamTypes();
+            Class<?>[] paramTypes = callableMemberDesc.getParamTypes();
             int ln = paramTypes.length;
             for (int i = 0; i < ln; i++) {
-                Class paramType = paramTypes[i];
+                Class<?> paramType = paramTypes[i];
                 final Object arg = args[i];
                 if (arg == null) continue;
                 
@@ -712,7 +711,7 @@ final class ArgumentTypes {
                 // parameter, and that an array argument is applicable to a List parameter, so we end up with this
                 // situation.
                 if (paramType.isArray() && arg instanceof List) {
-                   args[i] = bw.listToArray((List) arg, paramType, null);
+                   args[i] = bw.listToArray((List<?>) arg, paramType, null);
                 }
                 if (arg.getClass().isArray() && paramType.isAssignableFrom(List.class)) {
                     args[i] = bw.arrayToList(arg);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/BeanModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeanModel.java b/src/main/java/freemarker/ext/beans/BeanModel.java
index 794a66b..ba3dc62 100644
--- a/src/main/java/freemarker/ext/beans/BeanModel.java
+++ b/src/main/java/freemarker/ext/beans/BeanModel.java
@@ -143,8 +143,8 @@ implements
      */
     public TemplateModel get(String key)
         throws TemplateModelException {
-        Class clazz = object.getClass();
-        Map classInfo = wrapper.getClassIntrospector().get(clazz);
+        Class<?> clazz = object.getClass();
+        Map<Object, Object> classInfo = wrapper.getClassIntrospector().get(clazz);
         TemplateModel retval = null;
         
         try {
@@ -206,7 +206,7 @@ implements
         return wrapper.getClassIntrospector().get(object.getClass()).get(ClassIntrospector.GENERIC_GET_KEY) != null;
     }
     
-    private TemplateModel invokeThroughDescriptor(Object desc, Map classInfo)
+    private TemplateModel invokeThroughDescriptor(Object desc, Map<Object, Object> classInfo)
         throws IllegalAccessException,
         InvocationTargetException,
         TemplateModelException {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/BeansWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeansWrapper.java b/src/main/java/freemarker/ext/beans/BeansWrapper.java
index cf2d0c4..8b51238 100644
--- a/src/main/java/freemarker/ext/beans/BeansWrapper.java
+++ b/src/main/java/freemarker/ext/beans/BeansWrapper.java
@@ -31,6 +31,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.Enumeration;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -41,7 +42,6 @@ import freemarker.core.BugException;
 import freemarker.core._DelayedFTLTypeDescription;
 import freemarker.core._DelayedShortClassName;
 import freemarker.core._TemplateModelException;
-import freemarker.ext.util.IdentityHashMap;
 import freemarker.ext.util.ModelCache;
 import freemarker.ext.util.ModelFactory;
 import freemarker.ext.util.WrapperTemplateModel;
@@ -94,9 +94,9 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     @Deprecated
     static final Object CAN_NOT_UNWRAP = ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
     
-    private static final Class ITERABLE_CLASS;
+    private static final Class<?> ITERABLE_CLASS;
     static {
-        Class iterable;
+        Class<?> iterable;
         try {
             iterable = Class.forName("java.lang.Iterable");
         } catch (ClassNotFoundException e) {
@@ -106,7 +106,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
         ITERABLE_CLASS = iterable;
     }
     
-    private static final Constructor ENUMS_MODEL_CTOR = enumsModelCtor();
+    private static final Constructor<?> ENUMS_MODEL_CTOR = enumsModelCtor();
     
     /**
      * At this level of exposure, all methods and properties of the
@@ -296,7 +296,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     protected BeansWrapper(BeansWrapperConfiguration bwConf, boolean writeProtected, boolean finalizeConstruction) {
         // Backward-compatibility hack for "finetuneMethodAppearance" overrides to work:
         if (bwConf.getMethodAppearanceFineTuner() == null) {
-            Class thisClass = this.getClass();
+            Class<?> thisClass = this.getClass();
             boolean overridden = false;
             boolean testFailed = false;
             try {
@@ -306,7 +306,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                         && thisClass != SimpleObjectWrapper.class) {
                     try {
                         thisClass.getDeclaredMethod("finetuneMethodAppearance",
-                                new Class[] { Class.class, Method.class, MethodAppearanceDecision.class });
+                                new Class<?>[] { Class.class, Method.class, MethodAppearanceDecision.class });
                         overridden = true;
                     } catch (NoSuchMethodException e) {
                         thisClass = thisClass.getSuperclass();
@@ -912,17 +912,17 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
 
     private static final ModelFactory ITERATOR_FACTORY = new ModelFactory() {
         public TemplateModel create(Object object, ObjectWrapper wrapper) {
-            return new IteratorModel((Iterator) object, (BeansWrapper) wrapper); 
+            return new IteratorModel((Iterator<?>) object, (BeansWrapper) wrapper); 
         }
     };
 
     private static final ModelFactory ENUMERATION_FACTORY = new ModelFactory() {
         public TemplateModel create(Object object, ObjectWrapper wrapper) {
-            return new EnumerationModel((Enumeration) object, (BeansWrapper) wrapper); 
+            return new EnumerationModel((Enumeration<?>) object, (BeansWrapper) wrapper); 
         }
     };
 
-    protected ModelFactory getModelFactory(Class clazz) {
+    protected ModelFactory getModelFactory(Class<?> clazz) {
         if (Map.class.isAssignableFrom(clazz)) {
             return simpleMapWrapper ? SimpleMapModel.FACTORY : MapModel.FACTORY;
         }
@@ -983,7 +983,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * 
      * @see #tryUnwrapTo(TemplateModel, Class)
      */
-    public Object unwrap(TemplateModel model, Class targetClass) 
+    public Object unwrap(TemplateModel model, Class<?> targetClass) 
     throws TemplateModelException {
         final Object obj = tryUnwrapTo(model, targetClass);
         if (obj == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
@@ -996,7 +996,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     /**
      * @since 2.3.22
      */
-    public Object tryUnwrapTo(TemplateModel model, Class targetClass) throws TemplateModelException {
+    public Object tryUnwrapTo(TemplateModel model, Class<?> targetClass) throws TemplateModelException {
         return tryUnwrapTo(model, targetClass, 0);
     }
     
@@ -1007,7 +1007,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      *            {@link #is2321Bugfixed()} is {@code false}.
      * @return {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} or the unwrapped object.
      */
-    Object tryUnwrapTo(TemplateModel model, Class targetClass, int typeFlags) 
+    Object tryUnwrapTo(TemplateModel model, Class<?> targetClass, int typeFlags) 
     throws TemplateModelException {
         Object res = tryUnwrapTo(model, targetClass, typeFlags, null);
         if ((typeFlags & TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT) != 0
@@ -1021,7 +1021,8 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     /**
      * See {@try #tryUnwrap(TemplateModel, Class, int, boolean)}.
      */
-    private Object tryUnwrapTo(final TemplateModel model, Class targetClass, final int typeFlags, final Map recursionStops) 
+    private Object tryUnwrapTo(final TemplateModel model, Class<?> targetClass, final int typeFlags,
+            final Map<Object, Object> recursionStops) 
     throws TemplateModelException {
         if (model == null || model == nullModel) {
             return null;
@@ -1249,7 +1250,8 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      *            {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} instead of throwing a
      *            {@link TemplateModelException}.
      */
-    Object unwrapSequenceToArray(TemplateSequenceModel seq, Class arrayClass, boolean tryOnly, Map recursionStops)
+    Object unwrapSequenceToArray(
+            TemplateSequenceModel seq, Class<?> arrayClass, boolean tryOnly, Map<Object, Object> recursionStops)
             throws TemplateModelException {
         if (recursionStops != null) {
             Object retval = recursionStops.get(seq);
@@ -1257,9 +1259,9 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                 return retval;
             }
         } else {
-            recursionStops = new IdentityHashMap();
+            recursionStops = new IdentityHashMap<Object, Object>();
         }
-        Class componentType = arrayClass.getComponentType();
+        Class<?> componentType = arrayClass.getComponentType();
         Object array = Array.newInstance(componentType, seq.size());
         recursionStops.put(seq, array);
         try {
@@ -1287,7 +1289,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
         return array;
     }
     
-    Object listToArray(List list, Class arrayClass, Map recursionStops)
+    Object listToArray(List<?> list, Class<?> arrayClass, Map<Object, Object> recursionStops)
             throws TemplateModelException {
         if (list instanceof SequenceAdapter) {
             return unwrapSequenceToArray(
@@ -1302,9 +1304,9 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                 return retval;
             }
         } else {
-            recursionStops = new IdentityHashMap();
+            recursionStops = new IdentityHashMap<Object, Object>();
         }
-        Class componentType = arrayClass.getComponentType();
+        Class<?> componentType = arrayClass.getComponentType();
         Object array = Array.newInstance(componentType, list.size());
         recursionStops.put(list, array);
         try {
@@ -1312,7 +1314,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
             boolean isComponentTypeNumerical = false;  // will be filled on demand
             boolean isComponentTypeList = false;  // will be filled on demand
             int i = 0;
-            for (Iterator it = list.iterator(); it.hasNext(); ) {
+            for (Iterator<?> it = list.iterator(); it.hasNext(); ) {
                 Object listItem = it.next();
                 if (listItem != null && !componentType.isInstance(listItem)) {
                     // Type conversion is needed. If we can't do it, we just let it fail at Array.set later.
@@ -1333,7 +1335,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                         }
                     } else if (componentType.isArray()) {
                         if (listItem instanceof List) {
-                            listItem = listToArray((List) listItem, componentType, recursionStops);
+                            listItem = listToArray((List<?>) listItem, componentType, recursionStops);
                         } else if (listItem instanceof TemplateSequenceModel) {
                             listItem = unwrapSequenceToArray((TemplateSequenceModel) listItem, componentType, false, recursionStops);
                         }
@@ -1361,7 +1363,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     /**
      * @param array Must be an array (of either a reference or primitive type)
      */
-    List arrayToList(Object array) throws TemplateModelException {
+    List<?> arrayToList(Object array) throws TemplateModelException {
         if (array instanceof Object[]) {
             // Array of any non-primitive type.
             // Note that an array of non-primitive type is always instanceof Object[].
@@ -1378,7 +1380,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * @param n Non-{@code null}
      * @return {@code null} if the conversion has failed.
      */
-    static Number forceUnwrappedNumberToType(final Number n, final Class targetType, final boolean bugfixed) {
+    static Number forceUnwrappedNumberToType(final Number n, final Class<?> targetType, final boolean bugfixed) {
         // We try to order the conditions by decreasing probability.
         if (targetType == n.getClass()) {
             return n;
@@ -1516,7 +1518,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * @param arguments The list of {@link TemplateModel}-s to pass to the constructor after unwrapping them
      * @return The instance created; it's not wrapped into {@link TemplateModel}.
      */
-    public Object newInstance(Class clazz, List/*<TemplateModel>*/ arguments)
+    public Object newInstance(Class<?> clazz, List/*<? extends TemplateModel>*/ arguments)
     throws TemplateModelException {
         try {
             Object ctors = classIntrospector.get(clazz).get(ClassIntrospector.CONSTRUCTORS_KEY);
@@ -1524,11 +1526,11 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                 throw new TemplateModelException("Class " + clazz.getName() + 
                         " has no public constructors.");
             }
-            Constructor ctor = null;
+            Constructor<?> ctor = null;
             Object[] objargs;
             if (ctors instanceof SimpleMethod) {
                 SimpleMethod sm = (SimpleMethod) ctors;
-                ctor = (Constructor) sm.getMember();
+                ctor = (Constructor<?>) sm.getMember();
                 objargs = sm.unwrapArguments(arguments, this);
                 try {
                     return ctor.newInstance(objargs);
@@ -1565,7 +1567,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * 
      * @since 2.3.20
      */
-    public void removeFromClassIntrospectionCache(Class clazz) {
+    public void removeFromClassIntrospectionCache(Class<?> clazz) {
         classIntrospector.remove(clazz);
     }
     
@@ -1596,7 +1598,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      */
     @Deprecated
     protected void finetuneMethodAppearance(
-            Class clazz, Method m, MethodAppearanceDecision decision) {
+            Class<?> clazz, Method m, MethodAppearanceDecision decision) {
         // left everything on its default; do nothing
     }
     
@@ -1606,7 +1608,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      */
     // Unused?
     public static void coerceBigDecimals(AccessibleObject callable, Object[] args) {
-        Class[] formalTypes = null;
+        Class<?>[] formalTypes = null;
         for (int i = 0; i < args.length; ++i) {
             Object arg = args[i];
             if (arg instanceof BigDecimal) {
@@ -1614,7 +1616,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                     if (callable instanceof Method) {
                         formalTypes = ((Method) callable).getParameterTypes();
                     } else if (callable instanceof Constructor) {
-                        formalTypes = ((Constructor) callable).getParameterTypes();
+                        formalTypes = ((Constructor<?>) callable).getParameterTypes();
                     } else {
                         throw new IllegalArgumentException("Expected method or "
                                 + " constructor; callable is " + 
@@ -1627,10 +1629,10 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     }
     
     /**
-     * Converts any {@link BigDecimal}s in the passed array to the type of
-     * the corresponding formal argument of the method.
+     * Converts any {@link BigDecimal}-s in the passed array to the type of
+     * the corresponding formal argument of the method via {@link #coerceBigDecimal(BigDecimal, Class)}.
      */
-    public static void coerceBigDecimals(Class[] formalTypes, Object[] args) {
+    public static void coerceBigDecimals(Class<?>[] formalTypes, Object[] args) {
         int typeLen = formalTypes.length;
         int argsLen = args.length;
         int min = Math.min(typeLen, argsLen);
@@ -1641,7 +1643,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
             }
         }
         if (argsLen > typeLen) {
-            Class varArgType = formalTypes[typeLen - 1];
+            Class<?> varArgType = formalTypes[typeLen - 1];
             for (int i = typeLen; i < argsLen; ++i) {
                 Object arg = args[i];
                 if (arg instanceof BigDecimal) {
@@ -1651,7 +1653,12 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
         }
     }
 
-    public static Object coerceBigDecimal(BigDecimal bd, Class formalType) {
+    /**
+     * Converts {@link BigDecimal} to the class given in the {@code formalType} argument if that's a known numerical
+     * type, returns the {@link BigDecimal} as is otherwise. Overflow and precision loss are possible, similarly as
+     * with casting in Java.
+     */
+    public static Object coerceBigDecimal(BigDecimal bd, Class<?> formalType) {
         // int is expected in most situations, so we check it first
         if (formalType == int.class || formalType == Integer.class) {
             return Integer.valueOf(bd.intValue());
@@ -1774,19 +1781,17 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     }
     
     /**
-     * Used for
-     * {@link MethodAppearanceFineTuner#process}
-     * as input parameter; see there.
+     * Used for {@link MethodAppearanceFineTuner#process} as input parameter; see there.
      */
     static public final class MethodAppearanceDecisionInput {
         private Method method;
-        private Class containingClass;
+        private Class<?> containingClass;
         
         void setMethod(Method method) {
             this.method = method;
         }
         
-        void setContainingClass(Class containingClass) {
+        void setContainingClass(Class<?> containingClass) {
             this.containingClass = containingClass;
         }
 
@@ -1794,7 +1799,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
             return method;
         }
 
-        public Class getContainingClass() {
+        public Class/*<?>*/ getContainingClass() {
             return containingClass;
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java b/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
index 54090b9..f8cb545 100644
--- a/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
+++ b/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
@@ -20,6 +20,7 @@
 package freemarker.ext.beans;
 
 import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.util.Map;
 import java.util.WeakHashMap;
 
@@ -109,11 +110,13 @@ import freemarker.template.Version;
  */
 public class BeansWrapperBuilder extends BeansWrapperConfiguration {
 
-    private final static WeakHashMap/*<ClassLoader, Map<PropertyAssignments, WeakReference<BeansWrapper>>*/
-            INSTANCE_CACHE = new WeakHashMap();
-    private final static ReferenceQueue INSTANCE_CACHE_REF_QUEUE = new ReferenceQueue();
+    private final static Map<ClassLoader, Map<BeansWrapperConfiguration, WeakReference<BeansWrapper>>>
+            INSTANCE_CACHE = new WeakHashMap<
+                    ClassLoader, Map<BeansWrapperConfiguration, WeakReference<BeansWrapper>>>();
+    private final static ReferenceQueue<BeansWrapper> INSTANCE_CACHE_REF_QUEUE = new ReferenceQueue<BeansWrapper>();
    
-    private static class BeansWrapperFactory implements _BeansAPI._BeansWrapperSubclassFactory {
+    private static class BeansWrapperFactory
+            implements _BeansAPI._BeansWrapperSubclassFactory<BeansWrapper, BeansWrapperConfiguration> {
         
         private static final BeansWrapperFactory INSTANCE = new BeansWrapperFactory(); 
 
@@ -137,8 +140,10 @@ public class BeansWrapperBuilder extends BeansWrapperConfiguration {
         }
     }
 
-    /** For unit testing only */
-    static Map getInstanceCache() {
+    /**
+     * For unit testing only 
+     */
+    static Map<ClassLoader, Map<BeansWrapperConfiguration, WeakReference<BeansWrapper>>> getInstanceCache() {
         return INSTANCE_CACHE;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/ClassIntrospector.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/ClassIntrospector.java b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
index 6ccd872..c852636 100644
--- a/src/main/java/freemarker/ext/beans/ClassIntrospector.java
+++ b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
@@ -41,6 +41,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -120,8 +121,11 @@ class ClassIntrospector {
     // -----------------------------------------------------------------------------------------------------------------
     // Introspection info Map keys:
 
-    private static final Object ARGTYPES_KEY = new Object();
+    /** Key in the class info Map to the Map that maps method to argument type arrays */
+    private static final Object ARG_TYPES_BY_METHOD_KEY = new Object();
+    /** Key in the class info Map to the object that represents the constructors (one or multiple due to overloading) */
     static final Object CONSTRUCTORS_KEY = new Object();
+    /** Key in the class info Map to the get(String|Object) Method */
     static final Object GENERIC_GET_KEY = new Object();
 
     // -----------------------------------------------------------------------------------------------------------------
@@ -145,12 +149,14 @@ class ClassIntrospector {
     // State fields:
 
     private final Object sharedLock;
-    private final Map/* <Class, Map<String, Object>> */cache = new ConcurrentHashMap(0, 0.75f, 16);
-    private final Set/* <String> */cacheClassNames = new HashSet(0);
-    private final Set/* <Class> */classIntrospectionsInProgress = new HashSet(0);
+    private final Map<Class<?>, Map<Object, Object>> cache
+            = new ConcurrentHashMap<Class<?>, Map<Object, Object>>(0, 0.75f, 16);
+    private final Set<String> cacheClassNames = new HashSet<String>(0);
+    private final Set<Class<?>> classIntrospectionsInProgress = new HashSet<Class<?>>(0);
 
-    private final List/* <WeakReference<ClassBasedModelFactory|ModelCache>> */modelFactories = new LinkedList();
-    private final ReferenceQueue modelFactoriesRefQueue = new ReferenceQueue();
+    private final List<WeakReference<Object/*ClassBasedModelFactory|ModelCache>*/>> modelFactories
+            = new LinkedList<WeakReference<Object>>();
+    private final ReferenceQueue<Object> modelFactoriesRefQueue = new ReferenceQueue<Object>();
 
     private int clearingCounter;
 
@@ -210,15 +216,15 @@ class ClassIntrospector {
      *         {@link #CONSTRUCTORS_KEY}), each value is a {@link PropertyDescriptor} or {@link Method} or
      *         {@link OverloadedMethods} or {@link Field} (but better check the source code...).
      */
-    Map get(Class clazz) {
+    Map<Object, Object> get(Class<?> clazz) {
         {
-            Map introspData = (Map) cache.get(clazz);
+            Map<Object, Object> introspData = cache.get(clazz);
             if (introspData != null) return introspData;
         }
 
         String className;
         synchronized (sharedLock) {
-            Map introspData = (Map) cache.get(clazz);
+            Map<Object, Object> introspData = cache.get(clazz);
             if (introspData != null) return introspData;
 
             className = clazz.getName();
@@ -231,7 +237,7 @@ class ClassIntrospector {
                 // waiting for its result.
                 try {
                     sharedLock.wait();
-                    introspData = (Map) cache.get(clazz);
+                    introspData = cache.get(clazz);
                 } catch (InterruptedException e) {
                     throw new RuntimeException(
                             "Class inrospection data lookup aborded: " + e);
@@ -243,7 +249,7 @@ class ClassIntrospector {
             classIntrospectionsInProgress.add(clazz);
         }
         try {
-            Map introspData = createClassIntrospectionData(clazz);
+            Map<Object, Object> introspData = createClassIntrospectionData(clazz);
             synchronized (sharedLock) {
                 cache.put(clazz, introspData);
                 cacheClassNames.add(className);
@@ -260,14 +266,14 @@ class ClassIntrospector {
     /**
      * Creates a {@link Map} with the content as described for the return value of {@link #get(Class)}.
      */
-    private Map createClassIntrospectionData(Class clazz) {
-        final Map introspData = new HashMap();
+    private Map<Object, Object> createClassIntrospectionData(Class<?> clazz) {
+        final Map<Object, Object> introspData = new HashMap<Object, Object>();
 
         if (exposeFields) {
             addFieldsToClassIntrospectionData(introspData, clazz);
         }
 
-        final Map accessibleMethods = discoverAccessibleMethods(clazz);
+        final Map<MethodSignature, List<Method>> accessibleMethods = discoverAccessibleMethods(clazz);
 
         addGenericGetToClassIntrospectionData(introspData, accessibleMethods);
 
@@ -285,14 +291,14 @@ class ClassIntrospector {
         if (introspData.size() > 1) {
             return introspData;
         } else if (introspData.size() == 0) {
-            return Collections.EMPTY_MAP;
+            return Collections.emptyMap();
         } else { // map.size() == 1
-            Map.Entry e = (Map.Entry) introspData.entrySet().iterator().next();
+            Entry<Object, Object> e = introspData.entrySet().iterator().next();
             return Collections.singletonMap(e.getKey(), e.getValue());
         }
     }
 
-    private void addFieldsToClassIntrospectionData(Map introspData, Class clazz)
+    private void addFieldsToClassIntrospectionData(Map<Object, Object> introspData, Class<?> clazz)
             throws SecurityException {
         Field[] fields = clazz.getFields();
         for (int i = 0; i < fields.length; i++) {
@@ -303,7 +309,8 @@ class ClassIntrospector {
         }
     }
 
-    private void addBeanInfoToClassIntrospectionData(Map introspData, Class clazz, Map accessibleMethods)
+    private void addBeanInfoToClassIntrospectionData(
+            Map<Object, Object> introspData, Class<?> clazz, Map<MethodSignature, List<Method>> accessibleMethods)
             throws IntrospectionException {
         BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
 
@@ -354,7 +361,7 @@ class ClassIntrospector {
                                 overloadedMethods.addMethod(method);
                                 introspData.put(methodKey, overloadedMethods);
                                 // Remove parameter type information
-                                getArgTypes(introspData).remove(previous);
+                                getArgTypesByMethod(introspData).remove(previous);
                             } else if (previous instanceof OverloadedMethods) {
                                 // Already overloaded method - add new overload
                                 ((OverloadedMethods) previous).addMethod(method);
@@ -362,7 +369,7 @@ class ClassIntrospector {
                                     || !(previous instanceof PropertyDescriptor)) {
                                 // Simple method (this far)
                                 introspData.put(methodKey, method);
-                                getArgTypes(introspData).put(method,
+                                getArgTypesByMethod(introspData).put(method,
                                         method.getParameterTypes());
                             }
                         }
@@ -372,8 +379,8 @@ class ClassIntrospector {
         } // end if (exposureLevel < EXPOSE_PROPERTIES_ONLY)
     }
 
-    private void addPropertyDescriptorToClassIntrospectionData(Map introspData,
-            PropertyDescriptor pd, Class clazz, Map accessibleMethods) {
+    private void addPropertyDescriptorToClassIntrospectionData(Map<Object, Object> introspData,
+            PropertyDescriptor pd, Class<?> clazz, Map<MethodSignature, List<Method>> accessibleMethods) {
         if (pd instanceof IndexedPropertyDescriptor) {
             IndexedPropertyDescriptor ipd =
                     (IndexedPropertyDescriptor) pd;
@@ -388,7 +395,7 @@ class ClassIntrospector {
                                 null);
                     }
                     introspData.put(ipd.getName(), ipd);
-                    getArgTypes(introspData).put(publicReadMethod, publicReadMethod.getParameterTypes());
+                    getArgTypesByMethod(introspData).put(publicReadMethod, publicReadMethod.getParameterTypes());
                 } catch (IntrospectionException e) {
                     LOG.warn("Failed creating a publicly-accessible " +
                             "property descriptor for " + clazz.getName() +
@@ -417,8 +424,8 @@ class ClassIntrospector {
         }
     }
 
-    private void addGenericGetToClassIntrospectionData(Map introspData,
-            Map accessibleMethods) {
+    private void addGenericGetToClassIntrospectionData(Map<Object, Object> introspData,
+            Map<MethodSignature, List<Method>> accessibleMethods) {
         Method genericGet = getFirstAccessibleMethod(
                 MethodSignature.GET_STRING_SIGNATURE, accessibleMethods);
         if (genericGet == null) {
@@ -430,19 +437,19 @@ class ClassIntrospector {
         }
     }
 
-    private void addConstructorsToClassIntrospectionData(final Map introspData,
-            Class clazz) {
+    private void addConstructorsToClassIntrospectionData(final Map<Object, Object> introspData,
+            Class<?> clazz) {
         try {
-            Constructor[] ctors = clazz.getConstructors();
+            Constructor<?>[] ctors = clazz.getConstructors();
             if (ctors.length == 1) {
-                Constructor ctor = ctors[0];
+                Constructor<?> ctor = ctors[0];
                 introspData.put(CONSTRUCTORS_KEY, new SimpleMethod(ctor, ctor.getParameterTypes()));
             } else if (ctors.length > 1) {
-                OverloadedMethods ctorMap = new OverloadedMethods(bugfixed);
+                OverloadedMethods overloadedCtors = new OverloadedMethods(bugfixed);
                 for (int i = 0; i < ctors.length; i++) {
-                    ctorMap.addConstructor(ctors[i]);
+                    overloadedCtors.addConstructor(ctors[i]);
                 }
-                introspData.put(CONSTRUCTORS_KEY, ctorMap);
+                introspData.put(CONSTRUCTORS_KEY, overloadedCtors);
             }
         } catch (SecurityException e) {
             LOG.warn("Can't discover constructors for class " + clazz.getName(), e);
@@ -454,13 +461,13 @@ class ClassIntrospector {
      * class is not public, retrieves methods with same signature as its public methods from public superclasses and
      * interfaces. Basically upcasts every method to the nearest accessible method.
      */
-    private static Map discoverAccessibleMethods(Class clazz) {
-        Map accessibles = new HashMap();
+    private static Map<MethodSignature, List<Method>> discoverAccessibleMethods(Class<?> clazz) {
+        Map<MethodSignature, List<Method>> accessibles = new HashMap<MethodSignature, List<Method>>();
         discoverAccessibleMethods(clazz, accessibles);
         return accessibles;
     }
 
-    private static void discoverAccessibleMethods(Class clazz, Map accessibles) {
+    private static void discoverAccessibleMethods(Class<?> clazz, Map<MethodSignature, List<Method>> accessibles) {
         if (Modifier.isPublic(clazz.getModifiers())) {
             try {
                 Method[] methods = clazz.getMethods();
@@ -478,9 +485,10 @@ class ClassIntrospector {
                     // public interface I<T> { T m(); }
                     // public class C implements I<Integer> { Integer m() { return 42; } }
                     // C.class will have both "Object m()" and "Integer m()" methods.
-                    List methodList = (List) accessibles.get(sig);
+                    List<Method> methodList = accessibles.get(sig);
                     if (methodList == null) {
-                        methodList = new LinkedList();
+                     // TODO Collection.singletonList is more efficient, though read only.
+                        methodList = new LinkedList<Method>();
                         accessibles.put(sig, methodList);
                     }
                     methodList.add(method);
@@ -494,27 +502,26 @@ class ClassIntrospector {
             }
         }
 
-        Class[] interfaces = clazz.getInterfaces();
+        Class<?>[] interfaces = clazz.getInterfaces();
         for (int i = 0; i < interfaces.length; i++) {
             discoverAccessibleMethods(interfaces[i], accessibles);
         }
-        Class superclass = clazz.getSuperclass();
+        Class<?> superclass = clazz.getSuperclass();
         if (superclass != null) {
             discoverAccessibleMethods(superclass, accessibles);
         }
     }
 
-    private static Method getMatchingAccessibleMethod(Method m, Map accessibles) {
+    private static Method getMatchingAccessibleMethod(Method m, Map<MethodSignature, List<Method>> accessibles) {
         if (m == null) {
             return null;
         }
         MethodSignature sig = new MethodSignature(m);
-        List l = (List) accessibles.get(sig);
-        if (l == null) {
+        List<Method> ams = accessibles.get(sig);
+        if (ams == null) {
             return null;
         }
-        for (Iterator iterator = l.iterator(); iterator.hasNext(); ) {
-            Method am = (Method) iterator.next();
+        for (Method am : ams) {
             if (am.getReturnType() == m.getReturnType()) {
                 return am;
             }
@@ -522,12 +529,12 @@ class ClassIntrospector {
         return null;
     }
 
-    private static Method getFirstAccessibleMethod(MethodSignature sig, Map accessibles) {
-        List l = (List) accessibles.get(sig);
-        if (l == null || l.isEmpty()) {
+    private static Method getFirstAccessibleMethod(MethodSignature sig, Map<MethodSignature, List<Method>> accessibles) {
+        List<Method> ams = accessibles.get(sig);
+        if (ams == null || ams.isEmpty()) {
             return null;
         }
-        return (Method) l.iterator().next();
+        return ams.get(0);
     }
 
     /**
@@ -541,11 +548,12 @@ class ClassIntrospector {
         return exposureLevel < BeansWrapper.EXPOSE_SAFE || !UnsafeMethods.isUnsafeMethod(method);
     }
 
-    private static Map getArgTypes(Map classMap) {
-        Map argTypes = (Map) classMap.get(ARGTYPES_KEY);
+    private static Map<Method, Class<?>[]> getArgTypesByMethod(Map<Object, Object> classInfo) {
+        @SuppressWarnings("unchecked")
+        Map<Method, Class<?>[]> argTypes = (Map<Method, Class<?>[]>) classInfo.get(ARG_TYPES_BY_METHOD_KEY);
         if (argTypes == null) {
-            argTypes = new HashMap();
-            classMap.put(ARGTYPES_KEY, argTypes);
+            argTypes = new HashMap<Method, Class<?>[]>();
+            classInfo.put(ARG_TYPES_BY_METHOD_KEY, argTypes);
         }
         return argTypes;
     }
@@ -557,9 +565,9 @@ class ClassIntrospector {
                 new MethodSignature("get", new Class[] { Object.class });
 
         private final String name;
-        private final Class[] args;
+        private final Class<?>[] args;
 
-        private MethodSignature(String name, Class[] args) {
+        private MethodSignature(String name, Class<?>[] args) {
             this.name = name;
             this.args = args;
         }
@@ -606,8 +614,8 @@ class ClassIntrospector {
             cacheClassNames.clear();
             clearingCounter++;
 
-            for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = ((WeakReference) it.next()).get();
+            for (WeakReference<Object> regedMfREf : modelFactories) {
+                Object regedMf = regedMfREf.get();
                 if (regedMf != null) {
                     if (regedMf instanceof ClassBasedModelFactory) {
                         ((ClassBasedModelFactory) regedMf).clearCache();
@@ -628,14 +636,14 @@ class ClassIntrospector {
      * 
      * @since 2.3.20
      */
-    void remove(Class clazz) {
+    void remove(Class<?> clazz) {
         synchronized (sharedLock) {
             cache.remove(clazz);
             cacheClassNames.remove(clazz.getName());
             clearingCounter++;
 
-            for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = ((WeakReference) it.next()).get();
+            for (WeakReference<Object> regedMfREf : modelFactories) {
+                Object regedMf = regedMfREf.get();
                 if (regedMf != null) {
                     if (regedMf instanceof ClassBasedModelFactory) {
                         ((ClassBasedModelFactory) regedMf).removeFromCache(clazz);
@@ -688,7 +696,7 @@ class ClassIntrospector {
     private void registerModelFactory(Object mf) {
         // Note that this `synchronized (sharedLock)` is also need for the BeansWrapper constructor to work safely.
         synchronized (sharedLock) {
-            modelFactories.add(new WeakReference(mf, modelFactoriesRefQueue));
+            modelFactories.add(new WeakReference<Object>(mf, modelFactoriesRefQueue));
             removeClearedModelFactoryReferences();
         }
     }
@@ -703,8 +711,8 @@ class ClassIntrospector {
 
     void unregisterModelFactory(Object mf) {
         synchronized (sharedLock) {
-            for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = ((Reference) it.next()).get();
+            for (Iterator<WeakReference<Object>> it = modelFactories.iterator(); it.hasNext(); ) {
+                Object regedMf = it.next().get();
                 if (regedMf == mf) {
                     it.remove();
                 }
@@ -714,13 +722,13 @@ class ClassIntrospector {
     }
 
     private void removeClearedModelFactoryReferences() {
-        Reference cleardRef;
+        Reference<?> cleardRef;
         while ((cleardRef = modelFactoriesRefQueue.poll()) != null) {
             synchronized (sharedLock) {
-                findCleardRef: for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
+                findClearedRef: for (Iterator<WeakReference<Object>> it = modelFactories.iterator(); it.hasNext(); ) {
                     if (it.next() == cleardRef) {
                         it.remove();
-                        break findCleardRef;
+                        break findClearedRef;
                     }
                 }
             }
@@ -730,20 +738,22 @@ class ClassIntrospector {
     // -----------------------------------------------------------------------------------------------------------------
     // Extracting from introspection info:
 
-    static Class[] getArgTypes(Map classMap, AccessibleObject methodOrCtor) {
-        return (Class[]) ((Map) classMap.get(ARGTYPES_KEY)).get(methodOrCtor);
+    static Class<?>[] getArgTypes(Map<Object, Object> classInfo, Method method) {
+        @SuppressWarnings("unchecked")
+        Map<Method, Class<?>[]> argTypesByMethod = (Map<Method, Class<?>[]>) classInfo.get(ARG_TYPES_BY_METHOD_KEY);
+        return argTypesByMethod.get(method);
     }
 
     /**
      * Returns the number of introspected methods/properties that should be available via the TemplateHashModel
      * interface.
      */
-    int keyCount(Class clazz) {
-        Map map = get(clazz);
+    int keyCount(Class<?> clazz) {
+        Map<Object, Object> map = get(clazz);
         int count = map.size();
         if (map.containsKey(CONSTRUCTORS_KEY)) count--;
         if (map.containsKey(GENERIC_GET_KEY)) count--;
-        if (map.containsKey(ARGTYPES_KEY)) count--;
+        if (map.containsKey(ARG_TYPES_BY_METHOD_KEY)) count--;
         return count;
     }
 
@@ -751,11 +761,11 @@ class ClassIntrospector {
      * Returns the Set of names of introspected methods/properties that should be available via the TemplateHashModel
      * interface.
      */
-    Set keySet(Class clazz) {
-        Set set = new HashSet(get(clazz).keySet());
+    Set<Object> keySet(Class<?> clazz) {
+        Set<Object> set = new HashSet<Object>(get(clazz).keySet());
         set.remove(CONSTRUCTORS_KEY);
         set.remove(GENERIC_GET_KEY);
-        set.remove(ARGTYPES_KEY);
+        set.remove(ARG_TYPES_BY_METHOD_KEY);
         return set;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/_BeansAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/_BeansAPI.java b/src/main/java/freemarker/ext/beans/_BeansAPI.java
index f469508..a2c648d 100644
--- a/src/main/java/freemarker/ext/beans/_BeansAPI.java
+++ b/src/main/java/freemarker/ext/beans/_BeansAPI.java
@@ -49,7 +49,7 @@ public class _BeansAPI {
         return bm.getAsClassicCompatibleString();
     }
     
-    public static Object newInstance(Class pClass, Object[] args, BeansWrapper bw)
+    public static Object newInstance(Class<?> pClass, Object[] args, BeansWrapper bw)
             throws NoSuchMethodException, IllegalArgumentException, InstantiationException,
             IllegalAccessException, InvocationTargetException, TemplateModelException {
         return newInstance(getConstructorDescriptor(pClass, args), args, bw);
@@ -60,15 +60,18 @@ public class _BeansAPI {
      * than what the Java reflection API provides in that it can handle overloaded constructors. This re-uses the
      * overloaded method selection logic of {@link BeansWrapper}.
      */
-    private static CallableMemberDescriptor getConstructorDescriptor(Class pClass, Object[] args) throws NoSuchMethodException {
+    private static CallableMemberDescriptor getConstructorDescriptor(Class<?> pClass, Object[] args)
+            throws NoSuchMethodException {
         if (args == null) args = CollectionUtils.EMPTY_OBJECT_ARRAY;
         
         final ArgumentTypes argTypes = new ArgumentTypes(args, true);
-        final List fixedArgMemberDescs = new ArrayList();
-        final List varArgsMemberDescs = new ArrayList();
-        final Constructor[] constrs = pClass.getConstructors();
+        final List<ReflectionCallableMemberDescriptor> fixedArgMemberDescs
+                = new ArrayList<ReflectionCallableMemberDescriptor>();
+        final List<ReflectionCallableMemberDescriptor> varArgsMemberDescs
+                = new ArrayList<ReflectionCallableMemberDescriptor>();
+        final Constructor<?>[] constrs = pClass.getConstructors();
         for (int i = 0; i < constrs.length; i++) {
-            Constructor constr = constrs[i];
+            Constructor<?> constr = constrs[i];
             ReflectionCallableMemberDescriptor memberDesc = new ReflectionCallableMemberDescriptor(constr, constr.getParameterTypes());
             if (!_MethodUtil.isVarargs(constr)) {
                 fixedArgMemberDescs.add(memberDesc);
@@ -108,7 +111,7 @@ public class _BeansAPI {
         if (constrDesc.isVarargs()) {
             // We have to put all the varargs arguments into a single array argument.
 
-            final Class[] paramTypes = constrDesc.getParamTypes();
+            final Class<?>[] paramTypes = constrDesc.getParamTypes();
             final int fixedArgCnt = paramTypes.length - 1;
             
             packedArgs = new Object[fixedArgCnt + 1]; 
@@ -116,7 +119,7 @@ public class _BeansAPI {
                 packedArgs[i] = args[i];
             }
             
-            final Class compType = paramTypes[fixedArgCnt].getComponentType();
+            final Class<?> compType = paramTypes[fixedArgCnt].getComponentType();
             final int varArgCnt = args.length - fixedArgCnt;
             final Object varArgsArray = Array.newInstance(compType, varArgCnt);
             for (int i = 0; i < varArgCnt; i++) {
@@ -136,47 +139,47 @@ public class _BeansAPI {
      * @param beansWrapperSubclassFactory Creates a <em>new</em> read-only object wrapper of the desired
      *     {@link BeansWrapper} subclass. 
      */
-    public static BeansWrapper getBeansWrapperSubclassSingleton(
-            BeansWrapperConfiguration settings,
-            Map instanceCache,
-            ReferenceQueue instanceCacheRefQue,
-            _BeansWrapperSubclassFactory beansWrapperSubclassFactory) {
+    public static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> BW getBeansWrapperSubclassSingleton(
+            BWC settings,
+            Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache,
+            ReferenceQueue<BW> instanceCacheRefQue,
+            _BeansWrapperSubclassFactory<BW, BWC> beansWrapperSubclassFactory) {
         // BeansWrapper can't be cached across different Thread Context Class Loaders (TCCL), because the result of
         // a class name (String) to Class mappings depends on it, and the staticModels and enumModels need that.
         // (The ClassIntrospector doesn't have to consider the TCCL, as it only works with Class-es, not class
         // names.)
         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
         
-        Reference instanceRef;
-        Map/*<PropertyAssignments, WeakReference<BeansWrapper>>*/ tcclScopedCache;
+        Reference<BW> instanceRef;
+        Map<BWC, WeakReference<BW>> tcclScopedCache;
         synchronized (instanceCache) {
-            tcclScopedCache = (Map) instanceCache.get(tccl);
+            tcclScopedCache = instanceCache.get(tccl);
             if (tcclScopedCache == null) {
-                tcclScopedCache = new HashMap();
+                tcclScopedCache = new HashMap<BWC, WeakReference<BW>>();
                 instanceCache.put(tccl, tcclScopedCache);
                 instanceRef = null;
             } else {
-                instanceRef = (Reference) tcclScopedCache.get(settings);
+                instanceRef = tcclScopedCache.get(settings);
             }
         }
 
-        BeansWrapper instance = instanceRef != null ? (BeansWrapper) instanceRef.get() : null;
+        BW instance = instanceRef != null ? instanceRef.get() : null;
         if (instance != null) {  // cache hit
             return instance;
         }
         // cache miss
         
-        settings = (BeansWrapperConfiguration) settings.clone(true);  // prevent any aliasing issues 
+        settings = clone(settings);  // prevent any aliasing issues 
         instance = beansWrapperSubclassFactory.create(settings);
         if (!instance.isWriteProtected()) {
             throw new BugException();
         }
         
         synchronized (instanceCache) {
-            instanceRef = (Reference) tcclScopedCache.get(settings);
-            BeansWrapper concurrentInstance = instanceRef != null ? (BeansWrapper) instanceRef.get() : null;
+            instanceRef = tcclScopedCache.get(settings);
+            BW concurrentInstance = instanceRef != null ? instanceRef.get() : null;
             if (concurrentInstance == null) {
-                tcclScopedCache.put(settings, new WeakReference(instance, instanceCacheRefQue));
+                tcclScopedCache.put(settings, new WeakReference<BW>(instance, instanceCacheRefQue));
             } else {
                 instance = concurrentInstance;
             }
@@ -186,14 +189,21 @@ public class _BeansAPI {
         
         return instance;
     }
+
+    @SuppressWarnings("unchecked")
+    private static <BWC extends BeansWrapperConfiguration> BWC clone(BWC settings) {
+        return (BWC) settings.clone(true);
+    }
     
-    private static void removeClearedReferencesFromCache(Map instanceCache, ReferenceQueue instanceCacheRefQue) {
-        Reference clearedRef;
+    private static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration>
+            void removeClearedReferencesFromCache(
+                    Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache,
+                    ReferenceQueue<BW> instanceCacheRefQue) {
+        Reference<? extends BW> clearedRef;
         while ((clearedRef = instanceCacheRefQue.poll()) != null) {
             synchronized (instanceCache) {
-                findClearedRef: for (Iterator it1 = instanceCache.values().iterator(); it1.hasNext(); ) {
-                    Map tcclScopedCache = (Map) it1.next();
-                    for (Iterator it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) {
+                findClearedRef: for (Map<BWC, WeakReference<BW>> tcclScopedCache : instanceCache.values()) {
+                    for (Iterator<WeakReference<BW>> it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) {
                         if (it2.next() == clearedRef) {
                             it2.remove();
                             break findClearedRef;
@@ -207,10 +217,10 @@ public class _BeansAPI {
     /**
      * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
      */
-    public interface _BeansWrapperSubclassFactory {
+    public interface _BeansWrapperSubclassFactory<BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> {
         
         /** Creates a new read-only {@link BeansWrapper}; used for {@link BeansWrapperBuilder} and such. */
-        BeansWrapper create(BeansWrapperConfiguration sa);
+        BW create(BWC sa);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/util/IdentityHashMap.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/util/IdentityHashMap.java b/src/main/java/freemarker/ext/util/IdentityHashMap.java
index 57bb9db..13e140f 100644
--- a/src/main/java/freemarker/ext/util/IdentityHashMap.java
+++ b/src/main/java/freemarker/ext/util/IdentityHashMap.java
@@ -30,11 +30,12 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
- * A variant of {@link java.util.HashMap} that uses
- * {@link System#identityHashCode(Object)} for hashing, and reference comparison
- * instead of {@link Object#equals(Object)}. Note that this applies only to keys,
- * and not to values, i.e. {@link #containsValue(Object)} still uses {@link Object#equals(Object)}.
+ * Was used instead of {@link java.util.IdentityHashMap} before that was added to Java itself in Java 1.4. 
+ * 
+ * @deprecated Use {@link java.util.IdentityHashMap} instead.
  */
+@SuppressWarnings("rawtypes")
+@Deprecated
 public class IdentityHashMap
     extends AbstractMap
     implements Map, Cloneable, java.io.Serializable {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/util/ModelCache.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/util/ModelCache.java b/src/main/java/freemarker/ext/util/ModelCache.java
index 5a4b3ad..52ac7d1 100644
--- a/src/main/java/freemarker/ext/util/ModelCache.java
+++ b/src/main/java/freemarker/ext/util/ModelCache.java
@@ -23,6 +23,8 @@ import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.util.Map;
 
+import java.util.IdentityHashMap;
+
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelAdapter;
 
@@ -32,8 +34,8 @@ import freemarker.template.TemplateModelAdapter;
  */
 public abstract class ModelCache {
     private boolean useCache = false;
-    private Map modelCache = null;
-    private ReferenceQueue refQueue = null;
+    private Map<Object, ModelReference> modelCache = null;
+    private ReferenceQueue<TemplateModel> refQueue = null;
     
     protected ModelCache() {
     }
@@ -46,8 +48,8 @@ public abstract class ModelCache {
     public synchronized void setUseCache(boolean useCache) {
         this.useCache = useCache;
         if (useCache) {
-            modelCache = new IdentityHashMap();
-            refQueue = new ReferenceQueue();
+            modelCache = new IdentityHashMap<Object, ModelReference>();
+            refQueue = new ReferenceQueue<TemplateModel>();
         } else {
             modelCache = null;
             refQueue = null;
@@ -97,7 +99,7 @@ public abstract class ModelCache {
         // duplicate wrapper creation. However, this has no harmful side-effects and
         // is a lesser performance hit.
         synchronized (modelCache) {
-            ref = (ModelReference) modelCache.get(object);
+            ref = modelCache.get(object);
         }
 
         if (ref != null)
@@ -111,8 +113,9 @@ public abstract class ModelCache {
             // Remove cleared references
             for (; ; ) {
                 ModelReference queuedRef = (ModelReference) refQueue.poll();
-                if (queuedRef == null)
+                if (queuedRef == null) {
                     break;
+                }
                 modelCache.remove(queuedRef.object);
             }
             // Register new reference
@@ -125,10 +128,10 @@ public abstract class ModelCache {
      * When it gets cleared (that is, the model became unreachable)
      * it will remove itself from the model cache.
      */
-    private static final class ModelReference extends SoftReference {
+    private static final class ModelReference extends SoftReference<TemplateModel> {
         Object object;
 
-        ModelReference(TemplateModel ref, Object object, ReferenceQueue refQueue) {
+        ModelReference(TemplateModel ref, Object object, ReferenceQueue<TemplateModel> refQueue) {
             super(ref, refQueue);
             this.object = object;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/DefaultObjectWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/DefaultObjectWrapper.java b/src/main/java/freemarker/template/DefaultObjectWrapper.java
index b2f5820..323e1dd 100644
--- a/src/main/java/freemarker/template/DefaultObjectWrapper.java
+++ b/src/main/java/freemarker/template/DefaultObjectWrapper.java
@@ -61,7 +61,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
     @Deprecated
     static final DefaultObjectWrapper instance = new DefaultObjectWrapper();
     
-    static final private Class JYTHON_OBJ_CLASS;
+    static final private Class<?> JYTHON_OBJ_CLASS;
     
     static final private ObjectWrapper JYTHON_WRAPPER;
     
@@ -133,7 +133,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
     }
     
     static {
-        Class cl;
+        Class<?> cl;
         ObjectWrapper ow;
         try {
             cl = Class.forName("org.python.core.PyObject");
@@ -191,7 +191,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
             }
             return new SimpleDate((java.util.Date) obj, getDefaultDateType());
         }
-        final Class objClass = obj.getClass();
+        final Class<?> objClass = obj.getClass();
         if (objClass.isArray()) {
             if (useAdaptersForContainers) {
                 return DefaultArrayAdapter.adapt(obj, this);
@@ -203,28 +203,28 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
         if (obj instanceof Collection) {
             if (useAdaptersForContainers) {
                 if (obj instanceof List) {
-                    return DefaultListAdapter.adapt((List) obj, this);
+                    return DefaultListAdapter.adapt((List<?>) obj, this);
                 } else {
                     return forceLegacyNonListCollections
-                            ? (TemplateModel) new SimpleSequence((Collection) obj, this)
-                            : (TemplateModel) DefaultNonListCollectionAdapter.adapt((Collection) obj, this);
+                            ? (TemplateModel) new SimpleSequence((Collection<?>) obj, this)
+                            : (TemplateModel) DefaultNonListCollectionAdapter.adapt((Collection<?>) obj, this);
                 }
             } else {
-                return new SimpleSequence((Collection) obj, this);
+                return new SimpleSequence((Collection<?>) obj, this);
             }
         }
         if (obj instanceof Map) {
             return useAdaptersForContainers
-                    ? (TemplateModel) DefaultMapAdapter.adapt((Map) obj, this)
-                    : (TemplateModel) new SimpleHash((Map) obj, this);
+                    ? (TemplateModel) DefaultMapAdapter.adapt((Map<?, ?>) obj, this)
+                    : (TemplateModel) new SimpleHash((Map<?, ?>) obj, this);
         }
         if (obj instanceof Boolean) {
             return obj.equals(Boolean.TRUE) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
         }
         if (obj instanceof Iterator) {
             return useAdaptersForContainers
-                    ? (TemplateModel) DefaultIteratorAdapter.adapt((Iterator) obj, this)
-                    : (TemplateModel) new SimpleCollection((Iterator) obj, this);
+                    ? (TemplateModel) DefaultIteratorAdapter.adapt((Iterator<?>) obj, this)
+                    : (TemplateModel) new SimpleCollection((Iterator<?>) obj, this);
         }
         if (iterableSupport && obj instanceof Iterable) {
             return DefaultIterableAdapter.adapt((Iterable<?>) obj, this);
@@ -261,6 +261,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
      * Converts an array to a java.util.List.
      */
     protected Object convertArray(Object arr) {
+        // FM 2.4: Use Arrays.asList instead
         final int size = Array.getLength(arr);
         ArrayList list = new ArrayList(size);
         for (int i = 0; i < size; i++) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java b/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
index b8f89ba..7a6a027 100644
--- a/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
+++ b/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
@@ -20,11 +20,11 @@
 package freemarker.template;
 
 import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Map;
 import java.util.WeakHashMap;
 
-import freemarker.ext.beans.BeansWrapper;
 import freemarker.ext.beans.BeansWrapperBuilder;
-import freemarker.ext.beans.BeansWrapperConfiguration;
 import freemarker.ext.beans._BeansAPI;
 
 /**
@@ -38,9 +38,11 @@ import freemarker.ext.beans._BeansAPI;
  */
 public class DefaultObjectWrapperBuilder extends DefaultObjectWrapperConfiguration {
 
-    private final static WeakHashMap/*<ClassLoader, Map<BeansWrapperSettings, WeakReference<DefaultObjectWrapper>>*/
-            INSTANCE_CACHE = new WeakHashMap();
-    private final static ReferenceQueue INSTANCE_CACHE_REF_QUEUE = new ReferenceQueue();
+    private final static Map<ClassLoader, Map<DefaultObjectWrapperConfiguration, WeakReference<DefaultObjectWrapper>>>
+            INSTANCE_CACHE = new WeakHashMap<
+                    ClassLoader, Map<DefaultObjectWrapperConfiguration, WeakReference<DefaultObjectWrapper>>>();
+    private final static ReferenceQueue<DefaultObjectWrapper> INSTANCE_CACHE_REF_QUEUE
+            = new ReferenceQueue<DefaultObjectWrapper>();
     
     /**
      * Creates a builder that creates a {@link DefaultObjectWrapper} with the given {@code incompatibleImprovements};
@@ -63,16 +65,16 @@ public class DefaultObjectWrapperBuilder extends DefaultObjectWrapperConfigurati
      * a singleton that is also in use elsewhere. 
      */
     public DefaultObjectWrapper build() {
-        return (DefaultObjectWrapper) _BeansAPI.getBeansWrapperSubclassSingleton(
+        return _BeansAPI.getBeansWrapperSubclassSingleton(
                 this, INSTANCE_CACHE, INSTANCE_CACHE_REF_QUEUE, DefaultObjectWrapperFactory.INSTANCE);
     }
     
     private static class DefaultObjectWrapperFactory
-        implements _BeansAPI._BeansWrapperSubclassFactory {
+        implements _BeansAPI._BeansWrapperSubclassFactory<DefaultObjectWrapper, DefaultObjectWrapperConfiguration> {
     
         private static final DefaultObjectWrapperFactory INSTANCE = new DefaultObjectWrapperFactory(); 
         
-        public BeansWrapper create(BeansWrapperConfiguration bwConf) {
+        public DefaultObjectWrapper create(DefaultObjectWrapperConfiguration bwConf) {
             return new DefaultObjectWrapper(bwConf, true);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java b/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
index b48fa5f..7ec4461 100644
--- a/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
+++ b/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
@@ -87,6 +87,6 @@ public interface ObjectWrapperAndUnwrapper extends ObjectWrapper {
      * 
      * @since 2.3.22
      */
-    Object tryUnwrapTo(TemplateModel tm, Class targetClass) throws TemplateModelException;
+    Object tryUnwrapTo(TemplateModel tm, Class<?> targetClass) throws TemplateModelException;
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/_TemplateAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/_TemplateAPI.java b/src/main/java/freemarker/template/_TemplateAPI.java
index 0fc702a..c55a113 100644
--- a/src/main/java/freemarker/template/_TemplateAPI.java
+++ b/src/main/java/freemarker/template/_TemplateAPI.java
@@ -19,8 +19,6 @@
 
 package freemarker.template;
 
-import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import freemarker.cache.CacheStorage;


[10/24] incubator-freemarker git commit: (Typo fix)

Posted by dd...@apache.org.
(Typo fix)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/479ea6c5
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/479ea6c5
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/479ea6c5

Branch: refs/heads/2.3
Commit: 479ea6c538f32bd74f770b1aff63a0bf25329210
Parents: 32c8879
Author: ddekany <dd...@apache.org>
Authored: Thu Aug 11 20:41:24 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Thu Aug 11 20:41:24 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/479ea6c5/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index bd5ba49..ce9b08f 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -9145,7 +9145,7 @@ cfg.setTemplateConfigurations(
         <para>The output format associated to a template decides if and what
         kind of auto-escaping is used in that template (unless the template
         <link linkend="dgui_misc_autoescaping_overrideoformat">overrides that
-        with directives</link>). By default, templates has
+        with directives</link>). By default, templates have
         <quote>undefined</quote> output format associated, which does no
         escaping, and in general gives the behavior that you would expect from
         a template engine that doesn't care about output formats and escaping.


[12/24] incubator-freemarker git commit: Removed experimental status warning from MethodAppearanceFineTuner-related API-s. (These are in use at many places by now, so we can't change them anymore anyway.)

Posted by dd...@apache.org.
Removed experimental status warning from MethodAppearanceFineTuner-related API-s. (These are in use at many places by now, so we can't change them anymore anyway.)


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/ed653168
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/ed653168
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/ed653168

Branch: refs/heads/2.3
Commit: ed65316898dc57e79b9f45d1feee894bc75f5f53
Parents: 84c26cc
Author: ddekany <dd...@apache.org>
Authored: Wed Sep 28 20:10:49 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Wed Sep 28 20:10:49 2016 +0200

----------------------------------------------------------------------
 src/main/java/freemarker/ext/beans/BeansWrapper.java | 2 --
 1 file changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ed653168/src/main/java/freemarker/ext/beans/BeansWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeansWrapper.java b/src/main/java/freemarker/ext/beans/BeansWrapper.java
index c809fe7..cf2d0c4 100644
--- a/src/main/java/freemarker/ext/beans/BeansWrapper.java
+++ b/src/main/java/freemarker/ext/beans/BeansWrapper.java
@@ -1732,7 +1732,6 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     }
 
     /**
-     * <b>Experimental class; subject to change!</b>
      * Used for
      * {@link MethodAppearanceFineTuner#process}
      * to store the results; see there.
@@ -1775,7 +1774,6 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     }
     
     /**
-     * <b>Experimental class; subject to change!</b>
      * Used for
      * {@link MethodAppearanceFineTuner#process}
      * as input parameter; see there.


[07/24] incubator-freemarker git commit: Added more information about configuring FreeMarker with string-string key-value pairs.

Posted by dd...@apache.org.
Added more information about configuring FreeMarker with string-string key-value pairs.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/58cba5b9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/58cba5b9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/58cba5b9

Branch: refs/heads/2.3
Commit: 58cba5b961154f374989c6eab49e8560623db9de
Parents: 0815e14
Author: ddekany <dd...@apache.org>
Authored: Thu Aug 11 20:29:46 2016 +0200
Committer: ddekany <dd...@apache.org>
Committed: Thu Aug 11 20:29:46 2016 +0200

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 37 +++++++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/58cba5b9/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index b93691a..c6b0c38 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -8083,7 +8083,11 @@ cfg.setSharedVariable("company", "Foo Inc.");</programlisting>
 
             <programlisting role="unspecified">Configuration myCfg = new Configuration(Configuration.VERSION_2_3_25);
 myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
-myCfg.setDefaultEncoding("UTF-8");</programlisting>
+myCfg.setDefaultEncoding("UTF-8");
+DefaultObjectWrapperBuilder owb = new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_25);
+owb.setForceLegacyNonListCollections(false);
+owb.setDefaultDateType(TemplateDateModel.DATETIME);
+myCfg.setObjectWrapper(owb.build());</programlisting>
 
             <para>You do this before you start to actually use the
             <literal>Configuration</literal> object (typically, when you
@@ -8109,14 +8113,35 @@ myCfg.setDefaultEncoding("UTF-8");</programlisting>
       &lt;prop key="incompatible_improvements"&gt;2.3.25&lt;/prop&gt;
       &lt;prop key="template_exception_handler"&gt;rethrow&lt;/prop&gt;
       &lt;prop key="default_encoding"&gt;UTF-8&lt;/prop&gt;
+      &lt;prop key="object_wrapper"&gt;
+        DefaultObjectWrapper(
+                2.3.25,
+                forceLegacyNonListCollections = false,
+                defaultDateType = freemarker.template.TemplateDateModel.DATETIME)
+      &lt;/prop&gt;
     &lt;/props&gt;
   &lt;/property&gt;
 &lt;/bean&gt;</programlisting>
 
-            <para>Note that this kind of configuring
-            (<literal>String</literal> key-value pairs) is somewhat limited
-            compared to directly using Java API, so in some cases you have to
-            find a way to do this in Java.</para>
+            <para>Here's the same when configuring FreeMarker for Struts,
+            which looks for a <literal>freemarker.properties</literal> in the
+            classpath:</para>
+
+            <programlisting role="unspecified">incompatible_improvements=2.3.25
+template_exception_handler=rethrow
+default_encoding=UTF-8
+object_wrapper=DefaultObjectWrapper( \
+        2.3.25, \
+        forceLegacyNonListCollections = false, \
+        defaultDateType = freemarker.template.TemplateDateModel.DATETIME)</programlisting>
+
+            <para>As demonstrated above with
+            <literal>object_wrapper</literal>, some settings can accept quite
+            complex values, which can be used to instantiate objects of
+            arbitrary classes and set their properties. Still, configuring
+            with <literal>String</literal> key-value pairs is limited compared
+            to directly using the Java API, so in some cases you have to find
+            a way to do this in Java.</para>
           </listitem>
 
           <listitem>
@@ -8153,7 +8178,7 @@ myCfg.setDefaultEncoding("UTF-8");</programlisting>
               should set <link
               linkend="pgui_config_incompatible_improvements">the
               <literal>incompatible_improvements</literal> setting</link> to
-              2.3.22 or higher, to avoid soe confusing legacy bugs.</para>
+              2.3.22 or higher, to avoid some confusing legacy bugs.</para>
             </note>
           </listitem>
 


[04/24] incubator-freemarker git commit: couple grammar fixes, rephrase some things

Posted by dd...@apache.org.
couple grammar fixes, rephrase some things


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/a3fa4d2f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/a3fa4d2f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/a3fa4d2f

Branch: refs/heads/2.3
Commit: a3fa4d2f631e1e9d15e8587034413e779dc52c07
Parents: f83161b
Author: ratherblue <ra...@gmail.com>
Authored: Mon Jul 25 22:57:30 2016 -0700
Committer: ratherblue <ra...@gmail.com>
Committed: Mon Jul 25 22:57:30 2016 -0700

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a3fa4d2f/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index b46e1ea..18c486d 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -58,15 +58,15 @@
 
     <para>This approach is often referred to as the <link
     linkend="gloss.MVC">MVC (Model View Controller) pattern</link>, and is
-    particularly popular for dynamic Web pages. It helps in separating the Web
-    page designers (HTML authors) from the developers (Java programmers
+    particularly popular for dynamic web pages. It helps in separating web
+    page designers (HTML authors) from developers (Java programmers
     usually). Designers won't face complicated logic in templates, and can
     change the appearance of a page without programmers having to change or
     recompile code.</para>
 
     <para>While FreeMarker was originally created for generating HTML pages in
     MVC web application frameworks, it isn't bound to servlets or HTML or
-    anything Web-related. It's used in non-web application environments as
+    anything web-related. It's used in non-web application environments as
     well.</para>
 
     <para>FreeMarker is <link
@@ -100,7 +100,7 @@
       <section xml:id="dgui_quickstart_basics">
         <title>Template + data-model = output</title>
 
-        <para>Let's assume that you need a HTML page in a Web shop, similar to
+        <para>Let's assume that you need a HTML page on a website, similar to
         this:</para>
 
         <programlisting role="output">&lt;html&gt;
@@ -114,10 +114,9 @@
 &lt;/body&gt;
 &lt;/html&gt;</programlisting>
 
-        <para>But the user name ("John Doe" above) should depend on who the
-        logged in Web page visitor is, and the latest product should come from
-        a database and thus it potentially changes too. Thus you can't enter
-        these into the HTML directly, you can't use static HTML. Instead, you
+        <para>But the user's name ("John Doe" above) depends on who the
+        logged-in user is, and the latest product information should come from
+        a database. Because this data changes, you cannot you cannot use static HTML. Instead, you
         can use a <emphasis role="term">template</emphasis> of the desired
         output. The template is the same as the static HTML would be, except
         that it contains some instructions to FreeMarker that makes it


[20/24] incubator-freemarker git commit: Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Some code cleanup.

Posted by dd...@apache.org.
Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Some code cleanup.


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/c253e33d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/c253e33d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/c253e33d

Branch: refs/heads/2.3
Commit: c253e33d22db9365e3c134f59110bf20c0872670
Parents: 277956d
Author: ddekany <dd...@apache.org>
Authored: Sun Dec 4 17:55:56 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 4 21:31:17 2016 +0100

----------------------------------------------------------------------
 .../java/freemarker/ext/beans/BeanModel.java    | 88 +++++++++-----------
 .../freemarker/ext/beans/ClassIntrospector.java |  1 -
 .../template/AdapterTemplateModel.java          |  2 +-
 .../freemarker/template/SimpleSequence.java     |  2 +-
 4 files changed, 42 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/ext/beans/BeanModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeanModel.java b/src/main/java/freemarker/ext/beans/BeanModel.java
index ba3dc62..24f8590 100644
--- a/src/main/java/freemarker/ext/beans/BeanModel.java
+++ b/src/main/java/freemarker/ext/beans/BeanModel.java
@@ -80,10 +80,9 @@ implements
             }
         };
 
-    // Cached template models that implement member properties and methods for this
-    // instance. Keys are FeatureDescriptor instances (from classCache values),
-    // values are either ReflectionMethodModels/ReflectionScalarModels
-    private HashMap memberMap;
+    // I've tried to use a volatile ConcurrentHashMap field instead of HashMap + synchronized(this), but oddly it was
+    // a bit slower, at least on Java 8 u66. 
+    private HashMap<Object, TemplateModel> memberCache;
 
     /**
      * Creates a new model that wraps the specified object. Note that there are
@@ -192,7 +191,7 @@ implements
         }
     }
 
-    private void logNoSuchKey(String key, Map keyMap) {
+    private void logNoSuchKey(String key, Map<?, ?> keyMap) {
         LOG.debug("Key " + StringUtil.jQuoteNoXSS(key) + " was not found on instance of " + 
             object.getClass().getName() + ". Introspection information for " +
             "the class is: " + keyMap);
@@ -207,71 +206,64 @@ implements
     }
     
     private TemplateModel invokeThroughDescriptor(Object desc, Map<Object, Object> classInfo)
-        throws IllegalAccessException,
-        InvocationTargetException,
-        TemplateModelException {
-        // See if this particular instance has a cached implementation
-        // for the requested feature descriptor
-        TemplateModel member;
+            throws IllegalAccessException, InvocationTargetException, TemplateModelException {
+        // See if this particular instance has a cached implementation for the requested feature descriptor
+        TemplateModel cachedModel;
         synchronized (this) {
-            if (memberMap != null) {
-                member = (TemplateModel) memberMap.get(desc);
-            } else {
-                member = null;
-            }
+            cachedModel = memberCache != null ? memberCache.get(desc) : null;
         }
 
-        if (member != null)
-            return member;
+        if (cachedModel != null) {
+            return cachedModel;
+        }
 
-        TemplateModel retval = UNKNOWN;
+        TemplateModel resultModel = UNKNOWN;
         if (desc instanceof IndexedPropertyDescriptor) {
-            Method readMethod = 
-                ((IndexedPropertyDescriptor) desc).getIndexedReadMethod(); 
-            retval = member = 
+            Method readMethod = ((IndexedPropertyDescriptor) desc).getIndexedReadMethod(); 
+            resultModel = cachedModel = 
                 new SimpleMethodModel(object, readMethod, 
                         ClassIntrospector.getArgTypes(classInfo, readMethod), wrapper);
         } else if (desc instanceof PropertyDescriptor) {
             PropertyDescriptor pd = (PropertyDescriptor) desc;
-            retval = wrapper.invokeMethod(object, pd.getReadMethod(), null);
-            // (member == null) condition remains, as we don't cache these
+            resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
+            // cachedModel remains null, as we don't cache these
         } else if (desc instanceof Field) {
-            retval = wrapper.wrap(((Field) desc).get(object));
-            // (member == null) condition remains, as we don't cache these
+            resultModel = wrapper.wrap(((Field) desc).get(object));
+            // cachedModel remains null, as we don't cache these
         } else if (desc instanceof Method) {
             Method method = (Method) desc;
-            retval = member = new SimpleMethodModel(object, method, 
-                    ClassIntrospector.getArgTypes(classInfo, method), wrapper);
+            resultModel = cachedModel = new SimpleMethodModel(
+                    object, method, ClassIntrospector.getArgTypes(classInfo, method), wrapper);
         } else if (desc instanceof OverloadedMethods) {
-            retval = member = 
-                new OverloadedMethodsModel(object, (OverloadedMethods) desc, wrapper);
+            resultModel = cachedModel = new OverloadedMethodsModel(
+                    object, (OverloadedMethods) desc, wrapper);
         }
         
-        // If new cacheable member was created, cache it
-        if (member != null) {
+        // If new cachedModel was created, cache it
+        if (cachedModel != null) {
             synchronized (this) {
-                if (memberMap == null) {
-                    memberMap = new HashMap();
+                if (memberCache == null) {
+                    memberCache = new HashMap<Object, TemplateModel>();
                 }
-                memberMap.put(desc, member);
+                memberCache.put(desc, cachedModel);
             }
         }
-        return retval;
+        return resultModel;
     }
     
     void clearMemberCache() {
         synchronized (this) {
-            memberMap = null;
+            memberCache = null;
         }
     }
 
-    protected TemplateModel invokeGenericGet(Map keyMap, Class clazz, String key)
-    throws IllegalAccessException,
-        InvocationTargetException,
+    protected TemplateModel invokeGenericGet(Map/*<Object, Object>*/ classInfo, Class<?> clazz, String key)
+            throws IllegalAccessException, InvocationTargetException,
         TemplateModelException {
-        Method genericGet = (Method) keyMap.get(ClassIntrospector.GENERIC_GET_KEY);
-        if (genericGet == null)
+        Method genericGet = (Method) classInfo.get(ClassIntrospector.GENERIC_GET_KEY);
+        if (genericGet == null) {
             return UNKNOWN;
+        }
 
         return wrapper.invokeMethod(object, genericGet, new Object[] { key });
     }
@@ -295,13 +287,13 @@ implements
             return ((String) object).length() == 0;
         }
         if (object instanceof Collection) {
-            return ((Collection) object).isEmpty();
+            return ((Collection<?>) object).isEmpty();
         }
         if (object instanceof Iterator && wrapper.is2324Bugfixed()) {
-            return !((Iterator) object).hasNext();
+            return !((Iterator<?>) object).hasNext();
         }
         if (object instanceof Map) {
-            return ((Map) object).isEmpty();
+            return ((Map<?,?>) object).isEmpty();
         }
         return object == null || Boolean.FALSE.equals(object);
     }
@@ -310,7 +302,7 @@ implements
      * Returns the same as {@link #getWrappedObject()}; to ensure that, this method will be final starting from 2.4.
      * This behavior of {@link BeanModel} is assumed by some FreeMarker code. 
      */
-    public Object getAdaptedObject(Class hint) {
+    public Object getAdaptedObject(Class<?> hint) {
         return object;  // return getWrappedObject(); starting from 2.4
     }
 
@@ -327,7 +319,7 @@ implements
     }
 
     public TemplateCollectionModel values() throws TemplateModelException {
-        List values = new ArrayList(size());
+        List<Object> values = new ArrayList<Object>(size());
         TemplateModelIterator it = keys().iterator();
         while (it.hasNext()) {
             String key = ((TemplateScalarModel) it.next()).getAsString();
@@ -363,7 +355,7 @@ implements
      * interface. Subclasses that override <tt>invokeGenericGet</tt> to
      * provide additional hash keys should also override this method.
      */
-    protected Set keySet() {
+    protected Set/*<Object>*/ keySet() {
         return wrapper.getClassIntrospector().keySet(object.getClass());
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/ext/beans/ClassIntrospector.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/ClassIntrospector.java b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
index c852636..7c08e49 100644
--- a/src/main/java/freemarker/ext/beans/ClassIntrospector.java
+++ b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
@@ -28,7 +28,6 @@ import java.beans.PropertyDescriptor;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
-import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/template/AdapterTemplateModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/AdapterTemplateModel.java b/src/main/java/freemarker/template/AdapterTemplateModel.java
index fb76d22..2f32cae 100644
--- a/src/main/java/freemarker/template/AdapterTemplateModel.java
+++ b/src/main/java/freemarker/template/AdapterTemplateModel.java
@@ -45,5 +45,5 @@ public interface AdapterTemplateModel extends TemplateModel {
      * @return the underlying object, or its value accommodated for the hint
      * class.
      */
-    public Object getAdaptedObject(Class hint);
+    public Object getAdaptedObject(Class<?> hint);
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/template/SimpleSequence.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/SimpleSequence.java b/src/main/java/freemarker/template/SimpleSequence.java
index 0cc9411..e0ea945 100644
--- a/src/main/java/freemarker/template/SimpleSequence.java
+++ b/src/main/java/freemarker/template/SimpleSequence.java
@@ -161,7 +161,7 @@ public class SimpleSequence extends WrappingTemplateModel implements TemplateSeq
      * using {@link DefaultListAdapter} instead.
      * 
      * @param collection
-     *            The collection containing the initial items of this sequence. A shalow copy of this collection is made
+     *            The collection containing the initial items of the sequence. A shallow copy of this collection is made
      *            immediately for internal use (thus, later modification on the parameter collection won't be visible in
      *            the resulting sequence). The items however, will be only wrapped with the {@link ObjectWrapper}
      *            lazily, when first needed.


[03/24] incubator-freemarker git commit: grammar fix

Posted by dd...@apache.org.
grammar fix


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/f83161be
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/f83161be
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/f83161be

Branch: refs/heads/2.3
Commit: f83161be9472e493fd21dd6a0c1dd458cf111cab
Parents: 6032411
Author: ratherblue <ra...@gmail.com>
Authored: Mon Jul 25 22:49:47 2016 -0700
Committer: ratherblue <ra...@gmail.com>
Committed: Mon Jul 25 22:49:47 2016 -0700

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 216 ++++++++++++++++++++---------------------
 1 file changed, 108 insertions(+), 108 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/f83161be/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 14732b5..b46e1ea 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -7,9 +7,9 @@
   to you under the Apache License, Version 2.0 (the
   "License"); you may not use this file except in compliance
   with the License.  You may obtain a copy of the License at
-  
+
     http://www.apache.org/licenses/LICENSE-2.0
-  
+
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -44,7 +44,7 @@
 
     <para>Templates are written in the FreeMarker Template Language (FTL).
     It's a simple, specialized language, <emphasis>not</emphasis> a full-blown
-    programming language like PHP. You meant to prepare the data to display in
+    programming language like PHP. You are meant to prepare the data to display in
     a real programming language, like issue database queries and do business
     calculations, and then the template displays that already prepared data.
     In the template you are focusing on how to present the data, and outside
@@ -220,21 +220,21 @@
   +- animals
   |   |
   |   +- mouse
-  |   |   |   
+  |   |   |
   |   |   +- size = "small"
-  |   |   |   
+  |   |   |
   |   |   +- price = 50
   |   |
   |   +- elephant
-  |   |   |   
+  |   |   |
   |   |   +- size = "large"
-  |   |   |   
+  |   |   |
   |   |   +- price = 5000
   |   |
   |   +- python
-  |       |   
+  |       |
   |       +- size = "medium"
-  |       |   
+  |       |
   |       +- price = 4999
   |
   +- message = "It is a test"
@@ -5867,7 +5867,7 @@ To prove that "s" didn't contain the value in escaped form:
 <phrase role="markedInvisibleText">[BR]</phrase>
   <phrase role="markedInvisibleText">[BR]</phrase>
 <phrase role="markedInvisibleText">[BR]</phrase>
-  <phrase role="markedInvisibleText">[BR]</phrase>  
+  <phrase role="markedInvisibleText">[BR]</phrase>
   &lt;li&gt;</phrase>Julia<phrase role="markedText"><phrase
               role="markedInvisibleText">[BR]</phrase>
   <phrase role="markedInvisibleText">[BR]</phrase>
@@ -6508,10 +6508,10 @@ import java.io.*;
 public class Test {
 
     public static void main(String[] args) throws Exception {
-        
-        /* ------------------------------------------------------------------------ */    
-        /* You should do this ONLY ONCE in the whole application life-cycle:        */    
-    
+
+        /* ------------------------------------------------------------------------ */
+        /* You should do this ONLY ONCE in the whole application life-cycle:        */
+
         /* Create and adjust the configuration singleton */
         Configuration cfg = new Configuration(Configuration.VERSION_2_3_25);
         cfg.setDirectoryForTemplateLoading(new File("<replaceable>/where/you/store/templates</replaceable>"));
@@ -6519,8 +6519,8 @@ public class Test {
         cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
         cfg.setLogTemplateExceptions(false);
 
-        /* ------------------------------------------------------------------------ */    
-        /* You usually do these for MULTIPLE TIMES in the application life-cycle:   */    
+        /* ------------------------------------------------------------------------ */
+        /* You usually do these for MULTIPLE TIMES in the application life-cycle:   */
 
         /* Create a data-model */
         Map root = new HashMap();
@@ -6966,7 +6966,7 @@ public class Product {
         the second string doesn't contains the first.</para>
 
         <programlisting role="unspecified">public class IndexOfMethod implements TemplateMethodModel {
-    
+
     public TemplateModel exec(List args) throws TemplateModelException {
         if (args.size() != 2) {
             throw new TemplateModelException("Wrong arguments");
@@ -7060,16 +7060,16 @@ import freemarker.template.TemplateModelException;
 /**
  *  FreeMarker user-defined directive that progressively transforms
  *  the output of its nested content to upper-case.
- *  
- *  
+ *
+ *
  *  &lt;p&gt;&lt;b&gt;Directive info&lt;/b&gt;&lt;/p&gt;
- * 
+ *
  *  &lt;p&gt;Directive parameters: None
  *  &lt;p&gt;Loop variables: None
  *  &lt;p&gt;Directive nested content: Yes
  */
 public class UpperDirective implements TemplateDirectiveModel {
-    
+
     public void execute(Environment env,
             Map params, TemplateModel[] loopVars,
             TemplateDirectiveBody body)
@@ -7083,7 +7083,7 @@ public class UpperDirective implements TemplateDirectiveModel {
                 throw new TemplateModelException(
                     "This directive doesn't allow loop variables.");
         }
-        
+
         // If there is non-empty nested content:
         if (body != null) {
             // Executes the nested body. Same as &lt;#nested&gt; in FTL, except
@@ -7093,15 +7093,15 @@ public class UpperDirective implements TemplateDirectiveModel {
             throw new RuntimeException("missing body");
         }
     }
-    
+
     /**
      * A {@link Writer} that transforms the character stream to upper case
      * and forwards it to another {@link Writer}.
-     */ 
+     */
     private static class UpperCaseFilterWriter extends Writer {
-       
+
         private final Writer out;
-           
+
         UpperCaseFilterWriter (Writer out) {
             this.out = out;
         }
@@ -7218,47 +7218,47 @@ import freemarker.template.TemplateNumberModel;
  * optionally with separating the output of the repetations with
  * &lt;tt&gt;&amp;lt;hr&gt;&lt;/tt&gt;-s.
  *
- * 
+ *
  * &lt;p&gt;&lt;b&gt;Directive info&lt;/b&gt;&lt;/p&gt;
- * 
+ *
  * &lt;p&gt;Parameters:
  * &lt;ul&gt;
  *   &lt;li&gt;&lt;code&gt;count&lt;/code&gt;: The number of repetations. Required!
  *       Must be a non-negative number. If it is not a whole number then it will
  *       be rounded &lt;em&gt;down&lt;/em&gt;.
  *   &lt;li&gt;&lt;code&gt;hr&lt;/code&gt;: Tells if a HTML "hr" element could be printed between
- *       repetations. Boolean. Optional, defaults to &lt;code&gt;false&lt;/code&gt;. 
+ *       repetations. Boolean. Optional, defaults to &lt;code&gt;false&lt;/code&gt;.
  * &lt;/ul&gt;
  *
  * &lt;p&gt;Loop variables: One, optional. It gives the number of the current
  *    repetation, starting from 1.
- * 
+ *
  * &lt;p&gt;Nested content: Yes
  */
 public class RepeatDirective implements TemplateDirectiveModel {
-    
+
     private static final String PARAM_NAME_COUNT = "count";
     private static final String PARAM_NAME_HR = "hr";
-    
+
     public void execute(Environment env,
             Map params, TemplateModel[] loopVars,
             TemplateDirectiveBody body)
             throws TemplateException, IOException {
-        
+
         // ---------------------------------------------------------------------
         // Processing the parameters:
-        
+
         int countParam = 0;
         boolean countParamSet = false;
         boolean hrParam = false;
-        
+
         Iterator paramIter = params.entrySet().iterator();
         while (paramIter.hasNext()) {
             Map.Entry ent = (Map.Entry) paramIter.next();
-            
+
             String paramName = (String) ent.getKey();
             TemplateModel paramValue = (TemplateModel) ent.getValue();
-            
+
             if (paramName.equals(PARAM_NAME_COUNT)) {
                 if (!(paramValue instanceof TemplateNumberModel)) {
                     throw new TemplateModelException(
@@ -7291,17 +7291,17 @@ public class RepeatDirective implements TemplateDirectiveModel {
                         "The required \"" + PARAM_NAME_COUNT + "\" paramter"
                         + "is missing.");
         }
-        
+
         if (loopVars.length &gt; 1) {
                 throw new TemplateModelException(
                         "At most one loop variable is allowed.");
         }
-        
+
         // Yeah, it was long and boring...
-        
+
         // ---------------------------------------------------------------------
         // Do the actual directive execution:
-        
+
         Writer out = env.getOut();
         if (body != null) {
             for (int i = 0; i &lt; countParam; i++) {
@@ -7310,12 +7310,12 @@ public class RepeatDirective implements TemplateDirectiveModel {
                 if (hrParam &amp;&amp; i != 0) {
                     out.write("&lt;hr&gt;");
                 }
-                
+
                 // Set the loop variable, if there is one:
                 if (loopVars.length &gt; 0) {
                     loopVars[0] = new SimpleNumber(i + 1);
                 }
-                
+
                 // Executes the nested body (same as &lt;#nested&gt; in FTL). In this
                 // case we don't provide a special writer as the parameter:
                 body.render(env.getOut());
@@ -7724,9 +7724,9 @@ public class Tupple&lt;E1, E2&gt; {
 
 public class TuppleAdapter extends WrappingTemplateModel implements TemplateSequenceModel,
         AdapterTemplateModel {
-    
+
     private final Tupple&lt;?, ?&gt; tupple;
-    
+
     public TuppleAdapter(Tupple&lt;?, ?&gt; tupple, ObjectWrapper ow) {
         super(ow);  // coming from WrappingTemplateModel
         this.tupple = tupple;
@@ -7736,7 +7736,7 @@ public class TuppleAdapter extends WrappingTemplateModel implements TemplateSequ
     public int size() throws TemplateModelException {
         return 2;
     }
-    
+
     @Override  // coming from TemplateSequenceModel
     public TemplateModel get(int index) throws TemplateModelException {
         switch (index) {
@@ -7750,7 +7750,7 @@ public class TuppleAdapter extends WrappingTemplateModel implements TemplateSequ
     public Object getAdaptedObject(Class hint) {
         return tupple;
     }
-    
+
 }</programlisting>
 
           <para>Regarding the classes and interfaces:</para>
@@ -7792,16 +7792,16 @@ public class MyAppObjectWrapper extends DefaultObjectWrapper {
     public MyAppObjectWrapper(Version incompatibleImprovements) {
         super(incompatibleImprovements);
     }
-    
+
     @Override
     protected TemplateModel handleUnknownType(final Object obj) throws TemplateModelException {
         if (obj instanceof Tupple) {
             return new TuppleAdapter((Tupple&lt;?, ?&gt;) obj, this);
         }
-        
+
         return super.handleUnknownType(obj);
     }
-    
+
 }</programlisting>
 
           <para>and then where you configure FreeMarker (<link
@@ -8694,7 +8694,7 @@ cfg.setTemplateLoader(mtl);</programlisting>
           <literal>TemplateExceptionHandler</literal> by implementing that
           interface, which contains this method:</para>
 
-          <programlisting role="unspecified">void handleTemplateException(TemplateException te, Environment env, Writer out) 
+          <programlisting role="unspecified">void handleTemplateException(TemplateException te, Environment env, Writer out)
         throws TemplateException;</programlisting>
 
           <para>Whenever a <literal>TemplateException</literal> occurs, this
@@ -9390,11 +9390,11 @@ public class HexTemplateNumberFormatFactory extends TemplateNumberFormatFactory
 
     public static final HexTemplateNumberFormatFactory INSTANCE
             = new HexTemplateNumberFormatFactory();
-    
+
     private HexTemplateNumberFormatFactory() {
         // Defined to decrease visibility
     }
-    
+
     @Override
     public TemplateNumberFormat get(String params, Locale locale, Environment env)
             throws InvalidFormatParametersException {
@@ -9405,9 +9405,9 @@ public class HexTemplateNumberFormatFactory extends TemplateNumberFormatFactory
     private static class HexTemplateNumberFormat extends TemplateNumberFormat {
 
         private static final HexTemplateNumberFormat INSTANCE = new HexTemplateNumberFormat();
-        
+
         private HexTemplateNumberFormat() { }
-        
+
         @Override
         public String formatToPlainText(TemplateNumberModel numberModel)
                 throws UnformattableValueException, TemplateModelException {
@@ -9428,7 +9428,7 @@ public class HexTemplateNumberFormatFactory extends TemplateNumberFormatFactory
         public String getDescription() {
             return "hexadecimal int";
         }
-        
+
     }
 
 }</programlisting>
@@ -9479,11 +9479,11 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
 
     public static final BaseNTemplateNumberFormatFactory INSTANCE
             = new BaseNTemplateNumberFormatFactory();
-    
+
     private BaseNTemplateNumberFormatFactory() {
         // Defined to decrease visibility
     }
-    
+
     @Override
     public TemplateNumberFormat get(String params, Locale locale, Environment env)
             throws InvalidFormatParametersException {
@@ -9505,7 +9505,7 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
                 fallbackFormat = null;
             }
         }
-        
+
         int base;
         try {
             base = Integer.parseInt(params);
@@ -9528,12 +9528,12 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
 
         private final int base;
         private final TemplateNumberFormat fallbackFormat;
-        
+
         private BaseNTemplateNumberFormat(int base, TemplateNumberFormat fallbackFormat) {
             this.base = base;
             this.fallbackFormat = fallbackFormat;
         }
-        
+
         @Override
         public String formatToPlainText(TemplateNumberModel numberModel)
                 throws TemplateModelException, TemplateValueFormatException {
@@ -9560,7 +9560,7 @@ public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactor
         public String getDescription() {
             return "base " + base;
         }
-        
+
     }
 
 }</programlisting>
@@ -9622,11 +9622,11 @@ public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFact
 
     public static final EpochMillisTemplateDateFormatFactory INSTANCE
             = new EpochMillisTemplateDateFormatFactory();
-    
+
     private EpochMillisTemplateDateFormatFactory() {
         // Defined to decrease visibility
     }
-    
+
     @Override
     public TemplateDateFormat get(String params, int dateType,
             Locale locale, TimeZone timeZone, boolean zonelessInput,
@@ -9640,9 +9640,9 @@ public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFact
 
         private static final EpochMillisTemplateDateFormat INSTANCE
                 = new EpochMillisTemplateDateFormat();
-        
+
         private EpochMillisTemplateDateFormat() { }
-        
+
         @Override
         public String formatToPlainText(TemplateDateModel dateModel)
                 throws UnformattableValueException, TemplateModelException {
@@ -9672,7 +9672,7 @@ public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFact
         public String getDescription() {
             return "millis since the epoch";
         }
-        
+
     }
 
 }</programlisting>
@@ -9766,7 +9766,7 @@ public class UnitAwareTemplateNumberModel implements TemplateNumberModel {
 
     private final Number value;
     private final String unit;
-    
+
     public UnitAwareTemplateNumberModel(Number value, String unit) {
         this.value = value;
         this.unit = unit;
@@ -11146,12 +11146,12 @@ TemplateHashModel roundingModeEnums =
           <programlisting role="unspecified">&lt;servlet&gt;
   &lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
   &lt;servlet-class&gt;<emphasis>freemarker.ext.servlet.FreemarkerServlet</emphasis>&lt;/servlet-class&gt;
-  
+
   &lt;!--
     Init-param documentation:
     <link xlink:href="http://freemarker.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">http://freemarker.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html</link>
   --&gt;
-    
+
   &lt;!-- FreemarkerServlet settings: --&gt;
   &lt;init-param&gt;
     &lt;param-name&gt;TemplatePath&lt;/param-name&gt;
@@ -11719,7 +11719,7 @@ ${bar?trim}</programlisting>
         your security policy file for
         <literal>freemarker.jar</literal>:</para>
 
-        <programlisting role="unspecified">grant codeBase "file:/path/to/freemarker.jar" 
+        <programlisting role="unspecified">grant codeBase "file:/path/to/freemarker.jar"
 {
   permission java.util.PropertyPermission "file.encoding", "read";
   permission java.util.PropertyPermission "freemarker.*", "read";
@@ -11729,7 +11729,7 @@ ${bar?trim}</programlisting>
         need to give FreeMarker permissions to read files from that directory
         using the following permission:</para>
 
-        <programlisting role="unspecified">grant codeBase "file:/path/to/freemarker.jar" 
+        <programlisting role="unspecified">grant codeBase "file:/path/to/freemarker.jar"
 {
   ...
   permission java.io.FilePermission "/path/to/templates/-", "read";
@@ -11743,7 +11743,7 @@ ${bar?trim}</programlisting>
         template)</para>
 
         <programlisting role="unspecified">
-grant codeBase "file:/path/to/freemarker.jar" 
+grant codeBase "file:/path/to/freemarker.jar"
 {
   ...
   permission java.util.PropertyPermission "user.dir", "read";
@@ -15130,16 +15130,16 @@ rif: foo XYr baar</programlisting>
 
           <para>Prints:</para>
 
-          <programlisting role="output">    0 ?floor=0 ?ceiling=0 ?round=0            
-    1 ?floor=1 ?ceiling=1 ?round=1        
-    -1 ?floor=-1 ?ceiling=-1 ?round=-1      
-    0.5 ?floor=0 ?ceiling=1 ?round=1      
-    1.5 ?floor=1 ?ceiling=2 ?round=2      
-    -0.5 ?floor=-1 ?ceiling=0 ?round=0     
-    -1.5 ?floor=-2 ?ceiling=-1 ?round=-1    
-    0.25 ?floor=0 ?ceiling=1 ?round=0     
-    -0.25 ?floor=-1 ?ceiling=0 ?round=0    
-    1.75 ?floor=1 ?ceiling=2 ?round=2     
+          <programlisting role="output">    0 ?floor=0 ?ceiling=0 ?round=0
+    1 ?floor=1 ?ceiling=1 ?round=1
+    -1 ?floor=-1 ?ceiling=-1 ?round=-1
+    0.5 ?floor=0 ?ceiling=1 ?round=1
+    1.5 ?floor=1 ?ceiling=2 ?round=2
+    -0.5 ?floor=-1 ?ceiling=0 ?round=0
+    -1.5 ?floor=-2 ?ceiling=-1 ?round=-1
+    0.25 ?floor=0 ?ceiling=1 ?round=0
+    -0.25 ?floor=-1 ?ceiling=0 ?round=0
+    1.75 ?floor=1 ?ceiling=2 ?round=2
     -1.75 ?floor=-2 ?ceiling=-1 ?round=-2</programlisting>
 
           <para>These built-ins may be useful in pagination operations and
@@ -16345,13 +16345,13 @@ N
           <para>The output will be:</para>
 
           <programlisting role="output">
-  a b c d 
-  e f g h 
-  i j 
+  a b c d
+  e f g h
+  i j
 
-  a b c d 
-  e f g h 
-  i j - - 
+  a b c d
+  e f g h
+  i j - -
  </programlisting>
 
           <para>This built in is mostly for outputting sequnces in
@@ -16752,14 +16752,14 @@ Order by weight:
     {"name": {"first": "Joe", "last": "Smith"}, "age": 40},
     {"name": {"first": "Fred", "last": "Crooger"}, "age": 35},
     {"name": {"first": "Amanda", "last": "Fox"}, "age": 25}]&gt;
-Sorted by name.last: 
+Sorted by name.last:
 &lt;#list members?sort_by(['name', 'last']) as m&gt;
 - ${m.name.last}, ${m.name.first}: ${m.age} years old
 &lt;/#list&gt;</programlisting>
 
           <para>will print (with US locale at least):</para>
 
-          <programlisting role="output">Sorted by name.last: 
+          <programlisting role="output">Sorted by name.last:
 - Crooger, Fred: 35 years old
 - Fox, Amanda: 25 years old
 - Smith, Joe: 40 years old</programlisting>
@@ -20948,7 +20948,7 @@ or
           parameters:</para>
 
           <programlisting role="template">&lt;#macro img src extra...&gt;
-  &lt;img src="/myapp${src?ensure_starts_with('/')}" 
+  &lt;img src="/myapp${src?ensure_starts_with('/')}"
     &lt;#list extra as attrName, attrVal&gt;
       ${attrName}="${attrVal}"
     &lt;/#list&gt;
@@ -22183,7 +22183,7 @@ or
 
           <programlisting role="metaTemplate">
 <literal>&lt;@<replaceable>user_def_dir_exp</replaceable> <replaceable>param1</replaceable>=<replaceable>val1</replaceable> <replaceable>param2</replaceable>=<replaceable>val2</replaceable> <replaceable>...</replaceable> <replaceable>paramN</replaceable>=<replaceable>valN</replaceable>/&gt;</literal>
-(Note the XML-style <literal>/</literal> before the <literal>&gt;</literal>)  
+(Note the XML-style <literal>/</literal> before the <literal>&gt;</literal>)
 or if you need loop variables (<link
               linkend="ref_directive_userDefined_loopVar">more details...</link>)
 <literal>&lt;@<replaceable>user_def_dir_exp</replaceable> <replaceable>param1</replaceable>=<replaceable>val1</replaceable> <replaceable>param2</replaceable>=<replaceable>val2</replaceable> <replaceable>...</replaceable> <replaceable>paramN</replaceable>=<replaceable>valN</replaceable> ; <replaceable>lv1</replaceable>, <replaceable>lv2</replaceable>, <replaceable>...</replaceable>, <replaceable>lvN</replaceable>/&gt;</literal>
@@ -22290,7 +22290,7 @@ Or all above but with positional parameter passing (<link
       &lt;li&gt;Elephant
       &lt;li&gt;Python
   &lt;/ul&gt;
-  
+
 <replaceable>...</replaceable></programlisting>
 
           <section xml:id="ref_directive_userDefined_entTag">
@@ -22615,7 +22615,7 @@ There was no specific handler for node ${node?node_name}
             <para>This would print:</para>
 
             <programlisting role="output">Handling node x
-  
+
 There was no specific handler for node y
 
  </programlisting>
@@ -23198,7 +23198,7 @@ There was no specific handler for node y
           <programlisting role="metaTemplate"><literal>&lt;#macro <replaceable>name</replaceable>(<replaceable>argName1</replaceable>, <replaceable>argName2</replaceable>, <replaceable>... argNameN</replaceable>)&gt;
   ...
 &lt;/#macro&gt;</literal>
- 
+
 <literal>&lt;#call <replaceable>name</replaceable>(<replaceable>argValue1</replaceable>, <replaceable>argValue2</replaceable>, <replaceable>... argValueN</replaceable>)&gt;</literal></programlisting>
 
           <para>Where:</para>
@@ -23705,19 +23705,19 @@ or
      |   |
      |   +- text "\n    "
      |   |
-     |   +- element para     
+     |   +- element para
      |   |   |
      |   |   +- text "p1.1"
      |   |
      |   +- text "\n    "
      |   |
-     |   +- element para     
+     |   +- element para
      |   |   |
      |   |   +- text "p1.2"
      |   |
      |   +- text "\n    "
      |   |
-     |   +- element para     
+     |   +- element para
      |      |
      |      +- text "p1.3"
      |
@@ -23731,13 +23731,13 @@ or
          |
          +- text "\n    "
          |
-         +- element para     
+         +- element para
          |   |
          |   +- text "p2.1"
          |
          +- text "\n    "
          |
-         +- element para     
+         +- element para
              |
              +- text "p2.2"</programlisting>
 
@@ -24957,25 +24957,25 @@ End book</programlisting>
     &lt;body&gt;
       &lt;h1&gt;Test Book&lt;/h1&gt;
 
-  
+
     &lt;h2&gt;Ch1&lt;/h2&gt;
 
-    
+
       &lt;p&gt;p1.1
 
       &lt;p&gt;p1.2
 
       &lt;p&gt;p1.3
 
-  
+
     &lt;h2&gt;Ch2&lt;/h2&gt;
 
-    
+
       &lt;p&gt;p2.1
 
       &lt;p&gt;p2.2
 
-  
+
     &lt;/body&gt;
   &lt;/html&gt;
 
@@ -26260,7 +26260,7 @@ End book</programlisting>
 
             <para>Example: Here I use UTF-8 charset in a servlet:</para>
 
-            <programlisting role="unspecified">...        
+            <programlisting role="unspecified">...
 resp.setContentType("text/html; charset=utf-8");
 Writer out = resp.getWriter();
 ...
@@ -37854,7 +37854,7 @@ FreeMarker, both in its source code and binary form (freemarker.jar)
 includes a number of files that are licensed by the Apache Software
 Foundation under the Apache License, Version 2.0. This is the same
 license as the license of FreeMaker. These files are:
-  
+
     freemarker/ext/jsp/web-app_2_2.dtd
     freemarker/ext/jsp/web-app_2_3.dtd
     freemarker/ext/jsp/web-jsptaglibrary_1_1.dtd


[15/24] incubator-freemarker git commit: FREEMARKER-30: Fixed outdated bug reporting links

Posted by dd...@apache.org.
FREEMARKER-30: Fixed outdated bug reporting links


Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/d70e8da6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/d70e8da6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/d70e8da6

Branch: refs/heads/2.3
Commit: d70e8da6fdf32bde0347ee5b6420d4a6580bc9f4
Parents: bc5f45b
Author: ddekany <dd...@apache.org>
Authored: Fri Nov 11 20:53:11 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Fri Nov 11 20:53:11 2016 +0100

----------------------------------------------------------------------
 src/manual/en_US/docgen.cjson | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/d70e8da6/src/manual/en_US/docgen.cjson
----------------------------------------------------------------------
diff --git a/src/manual/en_US/docgen.cjson b/src/manual/en_US/docgen.cjson
index bd41571..088469e 100644
--- a/src/manual/en_US/docgen.cjson
+++ b/src/manual/en_US/docgen.cjson
@@ -68,7 +68,7 @@ olinks: {
   twitter: "https://twitter.com/freemarker"
   sourceforgeProject: "https://sourceforge.net/projects/freemarker/"
   githubProject: "https://github.com/freemarker/freemarker"
-  newBugReport: "https://sourceforge.net/p/freemarker/bugs/new/"
+  newBugReport: "https://issues.apache.org/jira/browse/FREEMARKER/"
   newStackOverflowQuestion: "http://stackoverflow.com/questions/ask?tags=freemarker"
 }