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/03/26 16:41:15 UTC

[01/32] incubator-freemarker git commit: Lazy imports: With the new boolean Configuration-level settings, lazy_imports and lazy_auto_imports, you can request imports (as in <#import "lib/utils.ftl" as u>) and/or auto-imports to be lazy. When the import i

Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3 b9ca91dd5 -> 8eada2e9d


Lazy imports: With the new boolean Configuration-level settings, lazy_imports and lazy_auto_imports, you can request imports (as in <#import "lib/utils.ftl" as u>) and/or auto-imports to be lazy. When the import is lazy, the namespace variable (u in this example) will be created immediately, just like before, but the template will be imported and processed only when (and if ever) the content of the imported namespace is accessed. The main application of this is with auto-imports, where you don't want the overhead of importing templates that aren't actually used in a template. (Also, a new Environment.importLib method overload was added, where you can specify if you want a lazy or an eager import.)


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

Branch: refs/heads/2.3
Commit: 6bdb716e6191d8dc8edad70aed12172f6f4e1698
Parents: 6166efe
Author: ddekany <dd...@apache.org>
Authored: Sun Jan 10 15:00:16 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Jan 10 20:09:57 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/cache/_CacheAPI.java   |  11 +-
 src/main/java/freemarker/core/Configurable.java |  10 +
 src/main/java/freemarker/core/Environment.java  | 333 ++++++++++++++++---
 src/main/java/freemarker/core/LibraryLoad.java  |  16 +-
 .../java/freemarker/template/Configuration.java |  93 +++++-
 src/manual/en_US/book.xml                       |  42 ++-
 .../freemarker/core/IncludeAndImportTest.java   | 173 +++++++++-
 .../freemarker/template/ConfigurationTest.java  |  22 ++
 8 files changed, 632 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/main/java/freemarker/cache/_CacheAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/_CacheAPI.java b/src/main/java/freemarker/cache/_CacheAPI.java
index 2643e81..fee6531 100644
--- a/src/main/java/freemarker/cache/_CacheAPI.java
+++ b/src/main/java/freemarker/cache/_CacheAPI.java
@@ -26,10 +26,10 @@ import freemarker.template.MalformedTemplateNameException;
  * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
  * access things inside this package that users shouldn't. 
  */ 
-public class _CacheAPI {
+public final class _CacheAPI {
 
-    public _CacheAPI() {
-        // TODO Auto-generated constructor stub
+    private _CacheAPI() {
+        // Not meant to be instantiated
     }
     
     public static String toAbsoluteName(TemplateNameFormat templateNameFormat, String baseName, String targetName)
@@ -37,4 +37,9 @@ public class _CacheAPI {
         return templateNameFormat.toAbsoluteName(baseName, targetName);
     }
 
+    public static String normalizeAbsoluteName(TemplateNameFormat templateNameFormat, String name)
+            throws MalformedTemplateNameException {
+        return templateNameFormat.normalizeAbsoluteName(name);
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/main/java/freemarker/core/Configurable.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index 5594ba0..7be1e47 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -1724,6 +1724,16 @@ public class Configurable {
      *       <br>String value is something like:
      *       <br>{@code /include/common.ftl, "/include/evil name.ftl"}
      *       
+     *   <li><p>{@code "lazy_auto_imports"}:
+     *       See {@link Configuration#setLazyAutoImports(Boolean)}.
+     *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
+     *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive. Also can be {@code "null"}.
+
+     *   <li><p>{@code "lazy_imports"}:
+     *       See {@link Configuration#setLazyImports(boolean)}.
+     *       <br>String value: {@code "true"}, {@code "false"} (also the equivalents: {@code "yes"}, {@code "no"},
+     *       {@code "t"}, {@code "f"}, {@code "y"}, {@code "n"}), case insensitive.
+     *       
      *   <li><p>{@code "default_encoding"}:
      *       See {@link Configuration#setDefaultEncoding(String)}.
      *       <br>As the default value is the system default, which can change

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 3d61aaa..20e910c 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -162,7 +162,7 @@ public final class Environment extends Configurable {
     private LocalContextStack localContextStack;
     private final Namespace mainNamespace;
     private Namespace currentNamespace, globalNamespace;
-    private HashMap loadedLibs;
+    private HashMap<String, Namespace> loadedLibs;
     private Configurable legacyParent;
 
     private boolean inAttemptBlock;
@@ -2170,7 +2170,7 @@ public final class Environment extends Configurable {
     public Namespace getNamespace(String name) {
         if (name.startsWith("/")) name = name.substring(1);
         if (loadedLibs != null) {
-            return (Namespace) loadedLibs.get(name);
+            return loadedLibs.get(name);
         } else {
             return null;
         }
@@ -2463,22 +2463,25 @@ public final class Environment extends Configurable {
      */
     public Template getTemplateForInclusion(String name, String encoding, boolean parseAsFTL, boolean ignoreMissing)
             throws IOException {
-        final Template inheritedTemplate = getTemplate();
+        return configuration.getTemplate(
+                name, getLocale(), getIncludedTemplateCustomLookupCondition(),
+                encoding != null ? encoding : getIncludedTemplateEncoding(),
+                parseAsFTL,
+                ignoreMissing);
+    }
+
+    private Object getIncludedTemplateCustomLookupCondition() {
+        return getTemplate().getCustomLookupCondition();
+    }
 
+    private String getIncludedTemplateEncoding() {
+        String encoding;
+        // This branch shouldn't exist, as it doesn't make much sense to inherit encoding. But we have to keep BC.
+        encoding = getTemplate().getEncoding();
         if (encoding == null) {
-            // This branch shouldn't exist, as it doesn't make much sense to inherit encoding. But we have to keep BC.
-            encoding = inheritedTemplate.getEncoding();
-            if (encoding == null) {
-                encoding = configuration.getEncoding(this.getLocale());
-            }
+            encoding = configuration.getEncoding(this.getLocale());
         }
-
-        Object customLookupCondition = inheritedTemplate.getCustomLookupCondition();
-
-        return configuration.getTemplate(
-                name, getLocale(), customLookupCondition,
-                encoding, parseAsFTL,
-                ignoreMissing);
+        return encoding;
     }
 
     /**
@@ -2513,22 +2516,63 @@ public final class Environment extends Configurable {
     }
 
     /**
-     * Emulates <code>import</code> directive, except that <code>name</code> must be tempate root relative.
+     * Emulates <code>import</code> directive, except that <code>templateName</code> must be template root relative.
      *
      * <p>
-     * It's the same as <code>importLib(getTemplateForImporting(name), namespace)</code>. But, you may want to
+     * It's the same as <code>importLib(getTemplateForImporting(templateName), namespace)</code>. But, you may want to
      * separately call these two methods, so you can determine the source of exceptions more precisely, and thus achieve
      * more intelligent error handling.
+     * 
+     * <p>
+     * If it will be a lazy or an eager import is decided by the value of {@link Configuration#getLazyImports()}. You
+     * can also directly control that aspect by using {@link #importLib(String, String, boolean)} instead.
+     *
+     * @return Not {@code null}. This is possibly a lazily self-initializing namespace, which means that it will only
+     *         try to get and process the imported template when you access its content.
+     *
+     * @see #getTemplateForImporting(String templateName)
+     * @see #importLib(Template includedTemplate, String namespaceVarName)
+     * @see #importLib(String, String, boolean)
+     */
+    public Namespace importLib(String templateName, String targetNsVarName)
+            throws IOException, TemplateException {
+        return importLib(templateName, targetNsVarName, configuration.getLazyImports());
+    }
+
+    /**
+     * Does what the <code>#import</code> directive does, but with an already loaded template.
      *
+     * @param loadedTemplate
+     *            The template to import. Note that it does <em>not</em> need to be a template returned by
+     *            {@link #getTemplateForImporting(String name)}.
+     * @param targetNsVarName
+     *            The name of the FTL variable that will store the namespace.
+     *            
      * @see #getTemplateForImporting(String name)
-     * @see #importLib(Template includedTemplate, String namespace)
+     * @see #importLib(Template includedTemplate, String namespaceVarName)
      */
-    public Namespace importLib(String name, String namespace)
+    public Namespace importLib(Template loadedTemplate, String targetNsVarName)
             throws IOException, TemplateException {
-        return importLib(getTemplateForImporting(name), namespace);
+        return importLib(null, loadedTemplate, targetNsVarName);
     }
 
     /**
+     * Like {@link #importLib(String, String)}, but you can specify if you want a
+     * {@linkplain Configuration#setLazyImports(boolean) lazy import} or not.
+     * 
+     * @return Not {@code null}. This is possibly a lazily self-initializing namespace, which mean that it will only try
+     *         to get and process the imported template when you access its content.
+     * 
+     * @since 2.3.25
+     */
+    public Namespace importLib(String templateName, String targetNsVarName, boolean lazy)
+            throws IOException, TemplateException {
+        return lazy
+                ? importLib(templateName, null, targetNsVarName)
+                : importLib(null, getTemplateForImporting(templateName), targetNsVarName);
+    }
+    
+    /**
      * Gets a template for importing; used with {@link #importLib(Template importedTemplate, String namespace)}. The
      * advantage over simply using <code>config.getTemplate(...)</code> is that it chooses the encoding as the
      * <code>import</code> directive does.
@@ -2544,53 +2588,83 @@ public final class Environment extends Configurable {
     }
 
     /**
-     * Emulates <code>import</code> directive.
-     *
+     * @param templateName
+     *            Ignored if {@code loadedTemaplate} is set (so we do eager import), otherwise it can't be {@code null}.
+     *            Assumed to be template root directory relative (not relative to the current template).
      * @param loadedTemplate
-     *            the template to import. Note that it does <em>not</em> need to be a template returned by
-     *            {@link #getTemplateForImporting(String name)}.
+     *            {@code null} exactly if we want a lazy import
      */
-    public Namespace importLib(Template loadedTemplate, String namespace)
+    private Namespace importLib(
+            String templateName, final Template loadedTemplate, final String targetNsVarName)
             throws IOException, TemplateException {
+        final boolean lazyImport;
+        if (loadedTemplate != null) {
+            lazyImport = false;
+            // As we have an already normalized name, we use it. 2.3.x note: We should use the template.sourceName as
+            // namespace key, but historically we use the looked up name (template.name); check what lazy import does if
+            // that will be fixed, as that can't do the template lookup, yet the keys must be the same.
+            templateName = loadedTemplate.getName();
+        } else {
+            lazyImport = true;
+            // We can't cause a template lookup here (see TemplateLookupStrategy), as that can be expensive. We exploit
+            // that (at least in 2.3.x) the name used for eager import namespace key isn't the template.sourceName, but
+            // the looked up name (template.name), which we can get quickly:
+            TemplateNameFormat tnf = getConfiguration().getTemplateNameFormat();
+            templateName = _CacheAPI.normalizeAbsoluteName(tnf, _CacheAPI.toAbsoluteName(tnf, null, templateName));
+        }
+        
         if (loadedLibs == null) {
             loadedLibs = new HashMap();
         }
-        String templateName = loadedTemplate.getName();
-        Namespace existingNamespace = (Namespace) loadedLibs.get(templateName);
+        final Namespace existingNamespace = loadedLibs.get(templateName);
         if (existingNamespace != null) {
-            if (namespace != null) {
-                setVariable(namespace, existingNamespace);
+            if (targetNsVarName != null) {
+                setVariable(targetNsVarName, existingNamespace);
                 if (isIcI2324OrLater() && currentNamespace == mainNamespace) {
-                    globalNamespace.put(namespace, existingNamespace);
+                    globalNamespace.put(targetNsVarName, existingNamespace);
                 }
             }
+            if (!lazyImport && existingNamespace instanceof LazilyInitializedNamespace) {
+                ((LazilyInitializedNamespace) existingNamespace).ensureInitializedTME();
+            }
         } else {
-            Namespace newNamespace = new Namespace(loadedTemplate);
-            if (namespace != null) {
-                setVariable(namespace, newNamespace);
+            final Namespace newNamespace
+                    = lazyImport ? new LazilyInitializedNamespace(templateName) : new Namespace(loadedTemplate);
+            loadedLibs.put(templateName, newNamespace);
+            
+            if (targetNsVarName != null) {
+                setVariable(targetNsVarName, newNamespace);
                 if (currentNamespace == mainNamespace) {
-                    globalNamespace.put(namespace, newNamespace);
+                    globalNamespace.put(targetNsVarName, newNamespace);
                 }
             }
-            Namespace prevNamespace = this.currentNamespace;
-            this.currentNamespace = newNamespace;
-            loadedLibs.put(templateName, currentNamespace);
-            Writer prevOut = out;
-            this.out = NullWriter.INSTANCE;
-            try {
-                include(loadedTemplate);
-            } finally {
-                this.out = prevOut;
-                this.currentNamespace = prevNamespace;
+            
+            if (!lazyImport) {
+                initializeImportLibNamespace(newNamespace, loadedTemplate);
             }
         }
-        return (Namespace) loadedLibs.get(templateName);
+        return loadedLibs.get(templateName);
+    }
+
+    private void initializeImportLibNamespace(final Namespace newNamespace, Template loadedTemplate)
+            throws TemplateException, IOException {
+        Namespace prevNamespace = this.currentNamespace;
+        this.currentNamespace = newNamespace;
+        Writer prevOut = out;
+        this.out = NullWriter.INSTANCE;
+        try {
+            include(loadedTemplate);
+        } finally {
+            this.out = prevOut;
+            this.currentNamespace = prevNamespace;
+        }
     }
 
     /**
      * Resolves a reference to a template (like the one used in {@code #include} or {@code #import}), assuming a base
      * name. This gives a full (that is, absolute), even if non-normalized template name, that could be used for
-     * {@link Configuration#getTemplate(String)}. This is mostly used when a template refers to another template.
+     * {@link Configuration#getTemplate(String)}. This is mostly used when a 
+     * template refers to another template.
      * 
      * @param baseName
      *            The name to which relative {@code targetName}-s are relative to. Maybe {@code null}, which usually
@@ -2738,7 +2812,7 @@ public final class Environment extends Configurable {
 
     public class Namespace extends SimpleHash {
 
-        private final Template template;
+        private Template template;
 
         Namespace() {
             this.template = Environment.this.getTemplate();
@@ -2754,6 +2828,171 @@ public final class Environment extends Configurable {
         public Template getTemplate() {
             return template == null ? Environment.this.getTemplate() : template;
         }
+        
+        void setTemplate(Template template) {
+            this.template = template; 
+        }
+        
+    }
+    
+    private enum InitializationStatus {
+        UNINITIALIZED, INITIALIZING, INITIALIZED, FAILED
+    }
+    
+    class LazilyInitializedNamespace extends Namespace {
+        
+        private final String templateName;
+        private final Locale locale;
+        private final String encoding;
+        private final Object customLookupCondition;
+        
+        private InitializationStatus status = InitializationStatus.UNINITIALIZED;
+        
+        /**
+         * @param templateName
+         *            Must be root relative
+         */
+        private LazilyInitializedNamespace(String templateName) {
+            super(null);
+            
+            this.templateName = templateName;
+            // Make snapshot of all settings that influence template resolution:
+            this.locale = getLocale();
+            this.encoding = getIncludedTemplateEncoding();
+            this.customLookupCondition = getIncludedTemplateCustomLookupCondition();
+        }
+
+        private void ensureInitializedTME() throws TemplateModelException {
+            if (status != InitializationStatus.INITIALIZED && status != InitializationStatus.INITIALIZING) {
+                if (status == InitializationStatus.FAILED) {
+                    throw new TemplateModelException(
+                            "Lazy initialization of the imported namespace for "
+                            + StringUtil.jQuote(templateName)
+                            + " has already failed earlier; won't retry it.");
+                }
+                try {
+                    status = InitializationStatus.INITIALIZING;
+                    initialize();
+                    status = InitializationStatus.INITIALIZED;
+                } catch (Exception e) {
+                    // [FM3] Rethrow TemplateException-s as is
+                    throw new TemplateModelException(
+                            "Lazy initialization of the imported namespace for "
+                            + StringUtil.jQuote(templateName)
+                            + " has failed; see cause exception", e);
+                } finally {
+                    if (status != InitializationStatus.INITIALIZED) {
+                        status = InitializationStatus.FAILED;
+                    }
+                }
+            }
+        }
+        
+        private void ensureInitializedRTE() {
+            try {
+                ensureInitializedTME();
+            } catch (TemplateModelException e) {
+                throw new RuntimeException(e.getMessage(), e.getCause());
+            }
+        }
+
+        private void initialize() throws IOException, TemplateException {
+            setTemplate(configuration.getTemplate(
+                    templateName, locale, customLookupCondition, encoding,
+                    true, false));
+            Locale lastLocale = getLocale();
+            try {
+                setLocale(locale);
+                initializeImportLibNamespace(this, getTemplate());
+            } finally {
+                setLocale(lastLocale);
+            }
+        }
+
+        @Override
+        protected Map copyMap(Map map) {
+            ensureInitializedRTE();
+            return super.copyMap(map);
+        }
+
+        @Override
+        public Template getTemplate() {
+            ensureInitializedRTE();
+            return super.getTemplate();
+        }
+
+        @Override
+        public void put(String key, Object value) {
+            ensureInitializedRTE();
+            super.put(key, value);
+        }
+
+        @Override
+        public void put(String key, boolean b) {
+            ensureInitializedRTE();
+            super.put(key, b);
+        }
+
+        @Override
+        public TemplateModel get(String key) throws TemplateModelException {
+            ensureInitializedTME();
+            return super.get(key);
+        }
+
+        @Override
+        public boolean containsKey(String key) {
+            ensureInitializedRTE();
+            return super.containsKey(key);
+        }
+
+        @Override
+        public void remove(String key) {
+            ensureInitializedRTE();
+            super.remove(key);
+        }
+
+        @Override
+        public void putAll(Map m) {
+            ensureInitializedRTE();
+            super.putAll(m);
+        }
+
+        @Override
+        public Map toMap() throws TemplateModelException {
+            ensureInitializedTME();
+            return super.toMap();
+        }
+
+        @Override
+        public String toString() {
+            ensureInitializedRTE();
+            return super.toString();
+        }
+
+        @Override
+        public int size() {
+            ensureInitializedRTE();
+            return super.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            ensureInitializedRTE();
+            return super.isEmpty();
+        }
+
+        @Override
+        public TemplateCollectionModel keys() {
+            ensureInitializedRTE();
+            return super.keys();
+        }
+
+        @Override
+        public TemplateCollectionModel values() {
+            ensureInitializedRTE();
+            return super.values();
+        }
+        
     }
 
     private static final Writer EMPTY_BODY_WRITER = new Writer() {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/main/java/freemarker/core/LibraryLoad.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/LibraryLoad.java b/src/main/java/freemarker/core/LibraryLoad.java
index 9305144..8d71b6a 100644
--- a/src/main/java/freemarker/core/LibraryLoad.java
+++ b/src/main/java/freemarker/core/LibraryLoad.java
@@ -35,17 +35,17 @@ import freemarker.template.TemplateException;
 public final class LibraryLoad extends TemplateElement {
 
     private Expression importedTemplateNameExp;
-    private String namespace;
+    private String targetNsVarName;
 
     /**
      * @param template the template that this <tt>Include</tt> is a part of.
      * @param templateName the name of the template to be included.
-     * @param namespace the namespace to assign this library to
+     * @param targetNsVarName the name of the  variable to assign this library's namespace to
      */
     LibraryLoad(Template template,
             Expression templateName,
-            String namespace) {
-        this.namespace = namespace;
+            String targetNsVarName) {
+        this.targetNsVarName = targetNsVarName;
         this.importedTemplateNameExp = templateName;
     }
 
@@ -61,16 +61,14 @@ public final class LibraryLoad extends TemplateElement {
                     e.getMalformednessDescription());
         }
         
-        final Template importedTemplate;
         try {
-            importedTemplate = env.getTemplateForImporting(fullImportedTemplateName);
+            env.importLib(fullImportedTemplateName, targetNsVarName);
         } catch (IOException e) {
             throw new _MiscTemplateException(e, env,
                     "Template importing failed (for parameter value ",
                     new _DelayedJQuote(importedTemplateName),
                     "):\n", new _DelayedGetMessage(e));
         }
-        env.importLib(importedTemplate, namespace);
         return null;
     }
 
@@ -82,7 +80,7 @@ public final class LibraryLoad extends TemplateElement {
         buf.append(' ');
         buf.append(importedTemplateNameExp.getCanonicalForm());
         buf.append(" as ");
-        buf.append(_CoreStringUtils.toFTLTopLevelTragetIdentifier(namespace));
+        buf.append(_CoreStringUtils.toFTLTopLevelTragetIdentifier(targetNsVarName));
         if (canonical) buf.append("/>");
         return buf.toString();
     }
@@ -101,7 +99,7 @@ public final class LibraryLoad extends TemplateElement {
     Object getParameterValue(int idx) {
         switch (idx) {
         case 0: return importedTemplateNameExp;
-        case 1: return namespace;
+        case 1: return targetNsVarName;
         default: throw new IndexOutOfBoundsException();
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/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 82c46b3..e756c3d 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -235,6 +235,20 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     public static final String AUTO_INCLUDE_KEY_CAMEL_CASE = "autoInclude";
     /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
     public static final String AUTO_INCLUDE_KEY = AUTO_INCLUDE_KEY_SNAKE_CASE;
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_IMPORTS_KEY_SNAKE_CASE = "lazy_imports";
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_IMPORTS_KEY_CAMEL_CASE = "lazyImports";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String LAZY_IMPORTS_KEY = LAZY_IMPORTS_KEY_SNAKE_CASE;
+
+    /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE = "lazy_auto_imports";
+    /** Modern, camel case ({@code likeThis}) variation of the setting name. @since 2.3.25 */
+    public static final String LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE = "lazyAutoImports";
+    /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
+    public static final String LAZY_AUTO_IMPORTS_KEY = LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE;
     
     /** Legacy, snake case ({@code like_this}) variation of the setting name. @since 2.3.23 */
     public static final String TAG_SYNTAX_KEY_SNAKE_CASE = "tag_syntax";
@@ -300,6 +314,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         CACHE_STORAGE_KEY_SNAKE_CASE,
         DEFAULT_ENCODING_KEY_SNAKE_CASE,
         INCOMPATIBLE_IMPROVEMENTS_KEY_SNAKE_CASE,
+        LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE,
+        LAZY_IMPORTS_KEY_SNAKE_CASE,
         LOCALIZED_LOOKUP_KEY_SNAKE_CASE,
         NAMING_CONVENTION_KEY_SNAKE_CASE,
         OUTPUT_FORMAT_KEY_SNAKE_CASE,
@@ -323,6 +339,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
         CACHE_STORAGE_KEY_CAMEL_CASE,
         DEFAULT_ENCODING_KEY_CAMEL_CASE,
         INCOMPATIBLE_IMPROVEMENTS_KEY_CAMEL_CASE,
+        LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE,
+        LAZY_IMPORTS_KEY_CAMEL_CASE,
         LOCALIZED_LOOKUP_KEY_CAMEL_CASE,
         NAMING_CONVENTION_KEY_CAMEL_CASE,
         OUTPUT_FORMAT_KEY_CAMEL_CASE,
@@ -504,6 +522,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     
     private LinkedHashMap<String, String> autoImports = new LinkedHashMap<String, String>(0);
     private ArrayList<String> autoIncludes = new ArrayList<String>(0);
+    private boolean lazyImpots;
+    private Boolean lazyAutoImport;
 
     /**
      * @deprecated Use {@link #Configuration(Version)} instead. Note that the version can be still modified later with
@@ -2876,6 +2896,10 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
                 setAutoIncludes(parseAsList(value));
             } else if (AUTO_IMPORT_KEY_SNAKE_CASE.equals(name) || AUTO_IMPORT_KEY_CAMEL_CASE.equals(name)) {
                 setAutoImports(parseAsImportList(value));
+            } else if (LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
+                setLazyAutoImports(value.equals(NULL) ? null : Boolean.valueOf(StringUtil.getYesNo(value)));
+            } else if (LAZY_IMPORTS_KEY_SNAKE_CASE.equals(name) || LAZY_IMPORTS_KEY_CAMEL_CASE.equals(name)) {
+                setLazyImports(StringUtil.getYesNo(value));
             } else if (TAG_SYNTAX_KEY_SNAKE_CASE.equals(name) || TAG_SYNTAX_KEY_CAMEL_CASE.equals(name)) {
                 if ("auto_detect".equals(value) || "autoDetect".equals(value)) {
                     setTagSyntax(AUTO_DETECT_TAG_SYNTAX);
@@ -2992,6 +3016,10 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * imports will be visible from the further imported templates too (though note that
      * {@link #getIncompatibleImprovements()} set to 2.3.24 fixes a rarely surfacing bug here).
      * 
+     * <p>It's recommended to set the {@code auto_impots_lazy} setting ({@link #setLazyAutoImports(Boolean)}) to
+     * {@code true} when using this, so that auto-imports that are unused in a template won't degrade performance by
+     * unnecessary loading and initializing the imported library.
+     * 
      * <p>
      * The order of the imports will be the same as the order in which they were added with this method. Note that if
      * there are also auto-includes ({@link #addAutoInclude(String)}), those inclusions will be executed after the
@@ -3022,8 +3050,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     /**
      * Removes all auto-imports, then calls {@link #addAutoImport(String, String)} for each {@link Map}-entry (the entry
      * key is the {@code namespaceVarName}). The order of the auto-imports will be the same as {@link Map#keySet()}
-     * returns the keys, thus, it's not the best idea to use a {@link HashMap} (although the order of imports doesn't
-     * mater for properly designed libraries).
+     * returns the keys (but the order of imports doesn't mater for properly designed libraries anyway).
      */
     public void setAutoImports(Map map) {
         // "synchronized" is removed from the API as it's not safe to set anything after publishing the Configuration
@@ -3048,8 +3075,10 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     protected void doAutoImportsAndIncludes(Environment env)
     throws TemplateException, IOException {
         for (Map.Entry<String, String> autoImport : autoImports.entrySet()) {
-            // Template name 1st, namespace var 2nd.
-            env.importLib(autoImport.getValue(), autoImport.getKey());
+            Boolean autoImportsLazy = getLazyAutoImports();
+            env.importLib(
+                    autoImport.getValue(), autoImport.getKey(),
+                    autoImportsLazy != null ? autoImportsLazy.booleanValue() : getLazyImports());
         }
         for (int i = 0; i < autoIncludes.size(); i++) {
             String templateName = autoIncludes.get(i);
@@ -3103,6 +3132,62 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
             autoIncludes.remove(templateName);
         }
     }
+    
+    /**
+     * The getter pair of {@link #setLazyImports(boolean)}.
+     * 
+     * @since 2.3.25
+     */
+    public boolean getLazyImports() {
+        return lazyImpots;
+    }
+
+    /**
+     * Specifies if {@code <#import ...>} (and {@link Environment#importLib(String, String)}) should delay the loading
+     * and processing of the imported templates until the content of the imported namespace is actually accessed. This
+     * makes the overhead of <em>unused</em> imports negligible. A drawback is that importing a missing or otherwise
+     * broken template will be successful, and the problem will remain hidden until (and if) the namespace content is
+     * actually used. Also, you lose the strict control over when the namespace initializing code in the imported
+     * template will be executed, though it shouldn't mater for well written imported templates anyway. Note that the
+     * namespace initializing code will run with the same {@linkplain Configurable#getLocale() locale} as it was at the
+     * point of the {@code <#import ...>} call (other settings won't be handled specially like that).
+     * 
+     * <p>
+     * The default is {@code false} (and thus imports are eager) for backward compatibility, which can cause
+     * perceivable overhead if you have many imports and only a few of them is used.
+     * 
+     * <p>
+     * This setting also affects {@linkplain #setAutoImports(Map) auto-imports}, unless you have set a non-{@code null}
+     * value just for that via {@link #setLazyAutoImports(Boolean)}.
+     * 
+     * @see #setLazyAutoImports(Boolean)
+     * 
+     * @since 2.3.25
+     */
+    public void setLazyImports(boolean importsLazy) {
+        this.lazyImpots = importsLazy;
+    }
+
+    /**
+     * The getter pair of {@link #setLazyAutoImports(Boolean)}.
+     * 
+     * @since 2.3.25
+     */
+    public Boolean getLazyAutoImports() {
+        return lazyAutoImport;
+    }
+
+    /**
+     * Specifies if {@linkplain #setAutoImports(Map) auto-imports} will be
+     * {@link #setLazyImports(boolean) lazy imports}. This is useful to make the overhead of <em>unused</em>
+     * auto-imports negligible. If this is set to {@code null}, {@link #getLazyImports()} specifies the behavior of
+     * auto-imports too. The default value is {@code null}.
+     * 
+     * @since 2.3.25
+     */
+    public void setLazyAutoImports(Boolean autoImportsLazy) {
+        this.lazyAutoImport = autoImportsLazy;
+    }
 
     /**
      * Returns FreeMarker version number string. 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 0ea368d..35ca1a5 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26409,6 +26409,44 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
     <appendix xml:id="app_versions">
       <title>Version history</title>
 
+      <section xml:id="versions_2_3_25">
+        <title>2.3.25</title>
+
+        <section>
+          <title>Changes on the FTL side</title>
+
+          <itemizedlist>
+            <listitem>
+              <para>[TODO]</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+
+        <section>
+          <title>Changes on the Java side</title>
+
+          <itemizedlist>
+            <listitem>
+              <para>Lazy imports: With the new boolean
+              <literal>Configuration</literal>-level settings,
+              <literal>lazy_imports</literal> and
+              <literal>lazy_auto_imports</literal>, you can request imports
+              (as in <literal>&lt;#import "lib/utils.ftl" as u&gt;</literal>)
+              and/or auto-imports to be lazy. When the import is lazy, the
+              namespace variable (<literal>u</literal> in this example) will
+              be created immediately, just like before, but the template will
+              be imported and processed only when (and if ever) the content of
+              the imported namespace is accessed. The main application of this
+              is with auto-imports, where you don't want the overhead of
+              importing templates that aren't actually used in a template.
+              (Also, a new <literal>Environment.importLib</literal> method
+              overload was added, where you can specify if you want a lazy or
+              an eager import.)</para>
+            </listitem>
+          </itemizedlist>
+        </section>
+      </section>
+
       <section xml:id="versions_2_3_24">
         <title>2.3.24 Release Candidate 1</title>
 
@@ -26434,8 +26472,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
           making process have stabilized in a manner consistent with other
           successful ASF projects. While incubation status is not necessarily
           a reflection of the completeness or stability of the code, it does
-          indicate that the project has yet to be fully endorsed by the ASF.
-          </para>
+          indicate that the project has yet to be fully endorsed by the
+          ASF.</para>
         </section>
 
         <section>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/test/java/freemarker/core/IncludeAndImportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/IncludeAndImportTest.java b/src/test/java/freemarker/core/IncludeAndImportTest.java
index 6123e9a..28161e5 100644
--- a/src/test/java/freemarker/core/IncludeAndImportTest.java
+++ b/src/test/java/freemarker/core/IncludeAndImportTest.java
@@ -18,16 +18,26 @@
  */
 package freemarker.core;
 
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
 import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 
 import org.junit.Before;
 import org.junit.Test;
 
 import freemarker.cache.StringTemplateLoader;
+import freemarker.core.Environment.LazilyInitializedNamespace;
+import freemarker.core.Environment.Namespace;
 import freemarker.template.Configuration;
 import freemarker.template.TemplateException;
+import freemarker.template.TemplateNotFoundException;
+import freemarker.template.WrappingTemplateModel;
 import freemarker.test.TemplateTest;
 
+@SuppressWarnings("boxing")
 public class IncludeAndImportTest extends TemplateTest {
 
     @Override
@@ -45,8 +55,19 @@ public class IncludeAndImportTest extends TemplateTest {
         addTemplate("lib1.ftl", "<#global lib1Cnt = (lib1Cnt!0) + 1><#global history = (history!) + 'L1'>"
                 + "<#macro m>In lib1</#macro>");
         addTemplate("lib2.ftl", "<#global history = (history!) + 'L2'>"
+                + "<#macro m>In lib2</#macro>");
+        addTemplate("lib3.ftl", "<#global history = (history!) + 'L3'>"
+                + "<#macro m>In lib3</#macro>");
+        
+        addTemplate("lib2CallsLib1.ftl", "<#global history = (history!) + 'L2'>"
                 + "<#macro m>In lib2 (<@lib1.m/>)</#macro>");
-        addTemplate("lib3.ftl", "<#import 'lib1.ftl' as lib1>");
+        addTemplate("lib3ImportsLib1.ftl", "<#import 'lib1.ftl' as lib1><#global history = (history!) + 'L3'>"
+                + "<#macro m>In lib3 (<@lib1.m/>)</#macro>");
+        
+        addTemplate("lib_de.ftl", "<#global history = (history!) + 'LDe'><#assign initLocale=.locale>"
+                + "<#macro m>de</#macro>");
+        addTemplate("lib_en.ftl", "<#global history = (history!) + 'LEn'><#assign initLocale=.locale>"
+                + "<#macro m>en</#macro>");
     }
 
     @Test
@@ -74,7 +95,7 @@ public class IncludeAndImportTest extends TemplateTest {
     public void importInMainCreatesGlobalBugfix() throws IOException, TemplateException {
         // An import in the main namespace should create a global variable, but there's a bug where that doesn't happen
         // if the imported library was already initialized elsewhere.
-        String ftl = "<#import 'lib3.ftl' as lib3>${lib1Cnt} ${.main.lib1???c} ${.globals.lib1???c}, "
+        String ftl = "<#import 'lib3ImportsLib1.ftl' as lib3>${lib1Cnt} ${.main.lib1???c} ${.globals.lib1???c}, "
         + "<#import 'lib1.ftl' as lib1>${lib1Cnt} ${.main.lib1???c} ${.globals.lib1???c}";
         assertOutput(ftl, "1 false false, 1 true false");
         // Activate bugfix:
@@ -90,10 +111,156 @@ public class IncludeAndImportTest extends TemplateTest {
         getConfiguration().addAutoInclude("inc1.ftl");
         getConfiguration().addAutoInclude("inc2.ftl");
         getConfiguration().addAutoImport("lib1", "lib1.ftl");
-        getConfiguration().addAutoImport("lib2", "lib2.ftl");
+        getConfiguration().addAutoImport("lib2", "lib2CallsLib1.ftl");
         assertOutput(
                 "<#include 'inc3.ftl'>[main] ${inc1Cnt}, ${history}, <@lib1.m/>, <@lib2.m/>",
                 "[inc1][inc2][inc3][main] 1, L1L2I, In lib1, In lib2 (In lib1)");
     }
     
+    /**
+     * Demonstrates design issue in FreeMarker 2.3.x where the lookupStrategy is not factored in when identifying
+     * already existing namespaces.
+     */
+    @Test
+    public void lookupSrategiesAreNotConsideredProperly() throws IOException, TemplateException {
+        // As only the name of the template is used for the finding the already existing namespace, the settings that
+        // influence the lookup are erroneously ignored.
+        assertOutput(
+                "<#setting locale='en_US'><#import 'lib.ftl' as ns1>"
+                + "<#setting locale='de_DE'><#import 'lib.ftl' as ns2>"
+                + "<@ns1.m/> <@ns2.m/> ${history}",
+                "en en LEn");
+        
+        // The opposite of the prevous, where differn names refer to the same template after a lookup: 
+        assertOutput(
+                "<#setting locale='en_US'>"
+                + "<#import '*/lib.ftl' as ns1>"
+                + "<#import 'lib.ftl' as ns2>"
+                + "<@ns1.m/> <@ns2.m/> ${history}",
+                "en en LEnLEn");
+    }
+    
+    @Test
+    public void lazyImportBasics() throws IOException, TemplateException {
+        String ftlImports = "<#import 'lib1.ftl' as l1><#import 'lib2.ftl' as l2><#import 'lib3ImportsLib1.ftl' as l3>";
+        String ftlCalls = "<@l2.m/>, <@l1.m/>; ${history}";
+        String ftl = ftlImports + ftlCalls;
+        
+        assertOutput(ftl, "In lib2, In lib1; L1L2L3");
+        
+        getConfiguration().setLazyImports(true);
+        assertOutput(ftl, "In lib2, In lib1; L2L1");
+        
+        assertOutput(ftlImports + "<@l3.m/>, " + ftlCalls, "In lib3 (In lib1), In lib2, In lib1; L3L1L2");
+    }
+
+    @Test
+    public void lazyImportAndLocale() throws IOException, TemplateException {
+        getConfiguration().setLazyImports(true);
+        assertOutput("<#setting locale = 'de_DE'><#import 'lib.ftl' as lib>"
+                + "[${history!}] "
+                + "<#setting locale = 'en'>"
+                + "<@lib.m/> ${lib.initLocale} [${history}]",
+                "[] de de_DE [LDe]");
+    }
+
+    @Test
+    public void lazyAutoImportSettings() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoImport("l1", "lib1.ftl");
+        cfg.addAutoImport("l2", "lib2.ftl");
+        cfg.addAutoImport("l3", "lib3.ftl");
+        
+        String ftl = "<@l2.m/>, <@l1.m/>; ${history}";
+        String expectedEagerOutput = "In lib2, In lib1; L1L2L3";
+        String expecedLazyOutput = "In lib2, In lib1; L2L1";
+        
+        assertOutput(ftl, expectedEagerOutput);
+        cfg.setLazyImports(true);
+        assertOutput(ftl, expecedLazyOutput);
+        cfg.setLazyImports(false);
+        assertOutput(ftl, expectedEagerOutput);
+        cfg.setLazyAutoImports(true);
+        assertOutput(ftl, expecedLazyOutput);
+        cfg.setLazyAutoImports(null);
+        assertOutput(ftl, expectedEagerOutput);
+        cfg.setLazyImports(true);
+        cfg.setLazyAutoImports(false);
+        assertOutput(ftl, expectedEagerOutput);
+    }
+    
+    @Test
+    public void lazyAutoImportMixedWithManualImport() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+        cfg.addAutoImport("l1", "lib1.ftl");
+        cfg.addAutoImport("l2", "/./lib2.ftl");
+        cfg.addAutoImport("l3", "lib3.ftl");
+        cfg.setLazyAutoImports(true);
+
+        String ftl = "<@l2.m/>, <@l1.m/>; ${history}";
+        String expectOutputWithoutHistory = "In lib2, In lib1; ";
+        String expecedOutput = expectOutputWithoutHistory + "L2L1";
+        
+        assertOutput(ftl, expecedOutput);
+        assertOutput("<#import 'lib1.ftl' as l1>" + ftl, expectOutputWithoutHistory + "L1L2");
+        assertOutput("<#import './x/../lib1.ftl' as l1>" + ftl, expectOutputWithoutHistory + "L1L2");
+        assertOutput("<#import 'lib2.ftl' as l2>" + ftl, expecedOutput);
+        assertOutput("<#import 'lib3.ftl' as l3>" + ftl, expectOutputWithoutHistory + "L3L2L1");
+        cfg.setLazyImports(true);
+        assertOutput("<#import 'lib1.ftl' as l1>" + ftl, expecedOutput);
+        assertOutput("<#import './x/../lib1.ftl' as l1>" + ftl, expecedOutput);
+        assertOutput("<#import 'lib2.ftl' as l2>" + ftl, expecedOutput);
+        assertOutput("<#import 'lib3.ftl' as l3>" + ftl, expecedOutput);
+    }
+
+    @Test
+    public void lazyImportErrors() throws IOException, TemplateException {
+        Configuration cfg = getConfiguration();
+        cfg.setLazyImports(true);
+        
+        assertOutput("<#import 'noSuchTemplate.ftl' as wrong>x", "x");
+        
+        cfg.addAutoImport("wrong", "noSuchTemplate.ftl");
+        assertOutput("x", "x");
+
+        try {
+            assertOutput("${wrong.x}", "");
+            fail();
+        } catch (TemplateException e) {
+            assertThat(e.getMessage(),
+                    allOf(containsString("Lazy initialization"), containsString("noSuchTemplate.ftl")));
+            assertThat(e.getCause(), instanceOf(TemplateNotFoundException.class));
+        }
+        
+        addTemplate("containsError.ftl", "${noSuchVar}");
+        try {
+            assertOutput("<#import 'containsError.ftl' as lib>${lib.x}", "");
+            fail();
+        } catch (TemplateException e) {
+            assertThat(e.getMessage(),
+                    allOf(containsString("Lazy initialization"), containsString("containsError.ftl")));
+            assertThat(e.getCause(), instanceOf(InvalidReferenceException.class));
+            assertThat(e.getCause().getMessage(), containsString("noSuchVar"));
+        }
+    }
+    
+    /**
+     * Ensures that all methods are overridden so that they will do the lazy initialization.
+     */
+    @Test
+    public void lazilyInitializingNamespaceOverridesAll() throws SecurityException, NoSuchMethodException {
+        for (Method m : Namespace.class.getMethods()) {
+            Class<?> declClass = m.getDeclaringClass();
+            if (declClass == Object.class || declClass == WrappingTemplateModel.class
+                    || (m.getModifiers() & Modifier.STATIC) != 0
+                    || m.getName().equals("synchronizedWrapper")) {
+                continue;
+            }
+            Method lazyM = LazilyInitializedNamespace.class.getMethod(m.getName(), m.getParameterTypes());
+            if (lazyM.getDeclaringClass() != LazilyInitializedNamespace.class) {
+                fail("The " + lazyM + " method wasn't overidden in " + LazilyInitializedNamespace.class.getName());
+            }
+        }
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6bdb716e/src/test/java/freemarker/template/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/template/ConfigurationTest.java b/src/test/java/freemarker/template/ConfigurationTest.java
index 39ee7b6..28b5d9a 100644
--- a/src/test/java/freemarker/template/ConfigurationTest.java
+++ b/src/test/java/freemarker/template/ConfigurationTest.java
@@ -1529,6 +1529,28 @@ public class ConfigurationTest extends TestCase {
         cfg.setSetting("naming_convention", "auto_detect");
         assertEquals(Configuration.AUTO_DETECT_NAMING_CONVENTION, cfg.getNamingConvention());
     }
+
+    public void testLazyImportsSetSetting() throws TemplateException {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
+
+        assertFalse(cfg.getLazyImports());
+        cfg.setSetting("lazy_imports", "true");
+        assertTrue(cfg.getLazyImports());
+        cfg.setSetting("lazyImports", "false");
+        assertFalse(cfg.getLazyImports());
+    }
+    
+    public void testLazyAutoImportsSetSetting() throws TemplateException {
+        Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
+
+        assertNull(cfg.getLazyAutoImports());
+        cfg.setSetting("lazy_auto_imports", "true");
+        assertEquals(Boolean.TRUE, cfg.getLazyAutoImports());
+        cfg.setSetting("lazyAutoImports", "false");
+        assertEquals(Boolean.FALSE, cfg.getLazyAutoImports());
+        cfg.setSetting("lazyAutoImports", "null");
+        assertNull(cfg.getLazyAutoImports());
+    }
     
     @Test
     public void testGetSettingNamesAreSorted() throws Exception {


[16/32] incubator-freemarker git commit: (Documentation typos)

Posted by dd...@apache.org.
(Documentation 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/416667cb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/416667cb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/416667cb

Branch: refs/heads/2.3
Commit: 416667cb17c8ac919846c09c5a51f4a1d1566b0f
Parents: b8e1d5e
Author: ddekany <dd...@apache.org>
Authored: Thu Feb 11 23:38:10 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Thu Feb 11 23:38:10 2016 +0100

----------------------------------------------------------------------
 README                    | 25 +++++++++++++------------
 src/manual/en_US/book.xml | 28 +++++++++++++++-------------
 2 files changed, 28 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/416667cb/README
----------------------------------------------------------------------
diff --git a/README b/README
index f6e2c31..dde3126 100644
--- a/README
+++ b/README
@@ -139,10 +139,10 @@ apply it to your development environment:
 
 - Install Ant and Ivy, if you haven't yet; see earlier.
 - From the command line, run `ant clean javacc ide-dependencies`. (Note that
-  now the "ide-dependencies" library was created. Also that
-  "build/generated-sources" was created.)
+  now the "ide-dependencies" and  "build/generated-sources" was created.)
 - Start Eclipse
-- Many developers prefer to start a new workspace (File -> "Switch workspace")
+- You may prefer to start a new workspace (File -> "Switch workspace"), but
+  it's optional.
 - Window -> Preferences
   - General -> Workspace, set the text file encoding
     to "UTF-8". (Or, you can set the same later on project level instead.)
@@ -150,7 +150,7 @@ apply it to your development environment:
     Select src\ide-settings\Eclipse-Mars\Formatter-profile-FreeMarker.xml
     inside the FreeMarker project directory.
     This profile uses space-only indentation policy and 120 character line
-    width, and formattings rules that are pretty much standard in modern Java.
+    width, and formatting rules that are pretty much standard in modern Java.
   - Java -> Installed JRE-s:
     Ensure that you have JDK 6 installed, and that it was added to Eclipse.
     Note that it's not JRE, but JDK.
@@ -158,16 +158,16 @@ apply it to your development environment:
   - In the first window popping up:
     - Change the "location" to the directory of the FreeMarker project
     - Press "Next"
-  - In the next window, you see the build path settings. Ensure that:
+  - In the next window, you see the build path settings:
     - On "Source" tab, ensure that exactly these are marked as source
-      directories:
+      directories (be careful, Eclipse doesn't auto-detect these well):
         build/generated-sources/java
         src/main/java
         src/main/resources
         src/test/java
         src/test/resources
     - On the "Libraries" tab:
-      - Delete everyhing from there, except the "JRE System Library [...]".
+      - Delete everyhing from there, except the "JRE System Library [...]"
       - Edit "JRE System Library [...]" to "Execution Environment" "JavaSE 1.6"
       - Add all jar-s that are directly under the "ide-dependencies" directory
         (use the "Add JARs..." and select all those files).
@@ -178,18 +178,19 @@ apply it to your development environment:
    - Press "Finish"
 - Eclipse will indicate many errors at this point; it's expected, read on.
 - Project -> Properties -> Java Compiler
-  - Set "Compiler Compliance Level" to "1.5"
+  - Set "Compiler Compliance Level" to "1.5" (you will have to uncheck
+    "Use compliance from execution environment" for that)
   - In Errors/Warnings, check in "Enable project specific settings", then set
     "Forbidden reference (access rules)" from "Error" to "Warning".
-- You will still have errors on these Java files (because different java
+- You will still have errors on these java files (because different java
   files depend on different versions of the same library, and Eclipse can't
-  handle that). Exclude them from the Build Path (in the Package Explorer,
-  right click on the problematic file -> "Build Path" -> "Exclude").
+  handle that). Exclude those java files from the Build Path (in the Package
+  Explorer, right click on the problematic file -> "Build Path" -> "Exclude").
     _Jython20*.java
     _Jython22*.java
     _FreeMarkerPageContext2.java
     FreeMarkerJspFactory2.java
-  Now you shouldn't have any errors.
+  Also, close these files if they are open. Now you shouldn't have any errors.
 - At Project -> Properties -> Java Code Style -> Formatter, check in "Enable
   project specific settings", and then select "FreeMarker" as active profile.
 - Right click on the project -> Run As -> JUnit Test

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/416667cb/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 2e6fa99..c47f5d9 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -20342,19 +20342,21 @@ All rights reserved.</emphasis></programlisting>
   &lt;/div&gt;
 &lt;/#list&gt;</programlisting>
 
-            <para>As <literal>sep</literal> is just a convenient way of
-            writing <literal>&lt;#if
-            <replaceable>item</replaceable>?has_next&gt;...&lt;/#if&gt;</literal>,
-            it can be used anywhere where there's a <literal>list</literal> or
-            <literal>items</literal> loop variable is available, and for
-            unlimited times. Also, it can have arbitrary FTL as nested
-            content.</para>
-
-            <para>The parser will check that <literal>sep</literal> is used
-            inside <literal>list <replaceable>...</replaceable> as
-            item</literal> or an <literal>items</literal> directive, so you
-            can't move <literal>sep</literal> out from the repeated part into
-            a macro or included template.</para>
+            <para><literal>sep</literal> is just a shorthand for
+            <literal>&lt;#if
+            <replaceable>item</replaceable>?has_next&gt;...&lt;/#if&gt;</literal>.
+            Thus, it can be used anywhere where there's a
+            <literal>list</literal> or <literal>items</literal> loop variable
+            available, it can occur for multiple times, and it can have
+            arbitrary nested content.</para>
+
+            <para>The parser ensures that <literal>sep</literal> is only used
+            on a place where there's a visible loop variable. This happens
+            earlier than the actual execution of the template. Thus, you can't
+            move <literal>sep</literal> from inside the associated
+            <literal>list</literal> or <literal>items</literal> directive into
+            a macro or included template (the parser can't know where those
+            will be called from).</para>
           </section>
 
           <section>


[30/32] incubator-freemarker git commit: (Manual: Release date updated)

Posted by dd...@apache.org.
(Manual: Release date updated)


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

Branch: refs/heads/2.3
Commit: 4b8df1fd03c21495e646ac1721734811564317f5
Parents: af6f05c
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 22:44:12 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 22:44:12 2016 +0100

----------------------------------------------------------------------
 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/4b8df1fd/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 35399f2..e3d86c5 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26492,7 +26492,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
       <section xml:id="versions_2_3_24">
         <title>2.3.24</title>
 
-        <para>Planned final release date: around 2016-03-01</para>
+        <para>Release date: 2016-03-20 + release process delay</para>
 
         <section>
           <title>Legal changes</title>


[17/32] incubator-freemarker git commit: (JavaDoc refinements)

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


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

Branch: refs/heads/2.3
Commit: 6b51f59d54f149d655fcf912908e28af5e6eecb3
Parents: 416667c
Author: ddekany <dd...@apache.org>
Authored: Mon Feb 15 00:25:08 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Feb 15 00:25:08 2016 +0100

----------------------------------------------------------------------
 .../freemarker/cache/WebappTemplateLoader.java  |  2 +-
 .../core/CommonTemplateMarkupOutputModel.java   |  9 ++++---
 .../freemarker/core/MarkupOutputFormat.java     | 26 ++++++++++++++------
 src/main/java/freemarker/core/OutputFormat.java |  2 +-
 .../core/TemplateMarkupOutputModel.java         | 21 +++++++++-------
 .../java/freemarker/template/Configuration.java | 24 ++++++++++++------
 .../java/freemarker/core/OutputFormatTest.java  |  2 +-
 7 files changed, 56 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/src/main/java/freemarker/cache/WebappTemplateLoader.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/WebappTemplateLoader.java b/src/main/java/freemarker/cache/WebappTemplateLoader.java
index d4f32dc..44c40df 100644
--- a/src/main/java/freemarker/cache/WebappTemplateLoader.java
+++ b/src/main/java/freemarker/cache/WebappTemplateLoader.java
@@ -51,7 +51,7 @@ public class WebappTemplateLoader implements TemplateLoader {
     private boolean attemptFileAccess = true;
 
     /**
-     * Creates a resource template cache that will use the specified servlet context to load the resources. It will use
+     * Creates a template loader that will use the specified servlet context to load the resources. It will use
      * the base path of <code>"/"</code> meaning templates will be resolved relative to the servlet context root
      * location.
      * 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java b/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
index 9d04428..3f1a43e 100644
--- a/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
+++ b/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
@@ -45,17 +45,20 @@ public abstract class CommonTemplateMarkupOutputModel<MO extends CommonTemplateM
 
     public abstract CommonMarkupOutputFormat<MO> getOutputFormat();
 
-    /** Maybe {@code null}, but then the other field isn't {@code null}. */
+    /** Maybe {@code null}, but then {@link #getMarkupContent()} isn't {@code null}. */
     final String getPlainTextContent() {
         return plainTextContent;
     }
 
-    /** Maybe {@code null}, but then the other field isn't {@code null}. */
+    /** Maybe {@code null}, but then {@link #getPlainTextContent()} isn't {@code null}. */
     final String getMarkupContent() {
         return markupContet;
     }
 
-    /** Use only to set {@code null} field to the value calculated from the other field! */
+    /**
+     * Use only to set the value calculated from {@link #getPlainTextContent()}, when {@link #getMarkupContent()} was
+     * still {@code null}!
+     */
     final void setMarkupContet(String markupContet) {
         this.markupContet = markupContet;
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/src/main/java/freemarker/core/MarkupOutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/MarkupOutputFormat.java b/src/main/java/freemarker/core/MarkupOutputFormat.java
index 0f1302c..b058591 100644
--- a/src/main/java/freemarker/core/MarkupOutputFormat.java
+++ b/src/main/java/freemarker/core/MarkupOutputFormat.java
@@ -21,13 +21,23 @@ package freemarker.core;
 import java.io.IOException;
 import java.io.Writer;
 
+import freemarker.template.Configuration;
 import freemarker.template.TemplateModelException;
 
 /**
- * An {@link OutputFormat}-s that represent a "markup", which is any format where certain character sequences have
- * special meaning and thus may need escaping. (Escaping is important for FreeMarker, as typically it has to insert
- * non-markup text from the data-model into the output markup.) This class, among others, defines the operations related
- * to {@link TemplateMarkupOutputModel}-s that belong to the output format.
+ * Superclass of {@link OutputFormat}-s that represent a "markup" format, which is any format where certain character
+ * sequences have special meaning and thus may need escaping. (Escaping is important for FreeMarker, as typically it has
+ * to insert non-markup text from the data-model into the output markup. See also:
+ * {@link Configuration#setOutputFormat(OutputFormat)}.)
+ * 
+ * <p>
+ * An {@link OutputFormat} subclass always has a corresponding {@link TemplateMarkupOutputModel} subclass pair (like
+ * {@link HTMLOutputFormat} has {@link TemplateHTMLOutputModel}). The {@link OutputFormat} implements the operations
+ * related to {@link TemplateMarkupOutputModel} objects of that kind, while the {@link TemplateMarkupOutputModel} only
+ * encapsulates the data (the actual markup or text).
+ * 
+ * <p>
+ * To implement a custom output format, you may want to extend {@link CommonMarkupOutputFormat}.
  * 
  * @param <MO>
  *            The {@link TemplateMarkupOutputModel} class this output format can deal with.
@@ -105,15 +115,17 @@ public abstract class MarkupOutputFormat<MO extends TemplateMarkupOutputModel> e
     public abstract boolean isEmpty(MO mo) throws TemplateModelException;
     
     /**
-     * Tells if a string built-in that can't handle a {@link TemplateMarkupOutputModel} left operand can bypass this
-     * object as is. A typical such case would be when a {@link TemplateHTMLOutputModel} of "HTML" format bypasses
+     * Tells if a string built-in that can't handle a {@link TemplateMarkupOutputModel} left hand operand can bypass
+     * this object as is. A typical such case would be when a {@link TemplateHTMLOutputModel} of "HTML" format bypasses
      * {@code ?html}.
      */
     public abstract boolean isLegacyBuiltInBypassed(String builtInName) throws TemplateModelException;
     
     /**
      * Tells if by default auto-escaping should be on for this format. It should be {@code true} if you need to escape
-     * on most of the places where you insert values. 
+     * on most of the places where you insert values.
+     * 
+     * @see Configuration#setAutoEscapingPolicy(int)
      */
     public abstract boolean isAutoEscapedByDefault();
     

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/src/main/java/freemarker/core/OutputFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/OutputFormat.java b/src/main/java/freemarker/core/OutputFormat.java
index 72ea821..5f4bc60 100644
--- a/src/main/java/freemarker/core/OutputFormat.java
+++ b/src/main/java/freemarker/core/OutputFormat.java
@@ -23,7 +23,7 @@ import freemarker.template.utility.ClassUtil;
 import freemarker.template.utility.StringUtil;
 
 /**
- * Represents an output format.
+ * Represents an output format. If you need auto-escaping, see its subclass, {@link MarkupOutputFormat}. 
  * 
  * @see Configuration#setOutputFormat(OutputFormat)
  * @see Configuration#setRegisteredCustomOutputFormats(java.util.Collection)

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateMarkupOutputModel.java b/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
index 3606379..3beead0 100644
--- a/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
+++ b/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
@@ -18,23 +18,23 @@
  */
 package freemarker.core;
 
-import freemarker.template.Configuration;
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateScalarModel;
 
 /**
  * "markup output" template language data-type; stores markup (some kind of "rich text" / structured format, as opposed
- * to plain text) that meant to be printed as template output. Each implementation of this type has a
- * {@link OutputFormat} subclass pair (like {@link TemplateHTMLOutputModel} has {@link HTMLOutputFormat}). This type is
- * related to the {@link Configuration#setOutputFormat(OutputFormat)} and
- * {@link Configuration#setAutoEscapingPolicy(int)} mechanism; see more there. Values of this type are exempt from
- * automatic escaping with that mechanism.
+ * to plain text) that meant to be printed as template output. This type is related to the {@link OutputFormat}
+ * mechanism. Values of this kind are exempt from {@link OutputFormat}-based automatic escaping.
  * 
  * <p>
- * Note that {@link TemplateMarkupOutputModel}-s are by design not handled like {@link TemplateScalarModel}-s, and so
+ * Each implementation of this type has a {@link OutputFormat} subclass pair, whose singleton instance is returned by
+ * {@link #getOutputFormat()}. See more about how markup output values work at {@link OutputFormat}.
+ * 
+ * <p>
+ * Note that {@link TemplateMarkupOutputModel}-s are by design not treated like {@link TemplateScalarModel}-s, and so
  * the implementations of this interface usually shouldn't implement {@link TemplateScalarModel}. (Because, operations
- * applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.) The template
- * author should make conscious decision of passing in the markup as String by using {@code ?markup_string}.
+ * applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.) If the template
+ * author wants to pass in the "source" of the markup as string somewhere, he should use {@code ?markup_string}.
  * 
  * @param <MO>
  *            Refers to the interface's own type, which is useful in interfaces that extend
@@ -44,6 +44,9 @@ import freemarker.template.TemplateScalarModel;
  */
 public interface TemplateMarkupOutputModel<MO extends TemplateMarkupOutputModel<MO>> extends TemplateModel {
 
+    /**
+     * Returns the singleton {@link OutputFormat} object that implements the operations for the "markup output" value.
+     */
     MarkupOutputFormat<MO> getOutputFormat();
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/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 82c46b3..ec5f270 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -1374,12 +1374,20 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     /**
-     * Sets the file system directory from which to load templates.
-     * This is equivalent to {@code setTemplateLoader(new FileTemplateLoader(dir))},
-     * so see {@link FileTemplateLoader#FileTemplateLoader(File)} for more details.
+     * Sets the file system directory from which to load templates. This is equivalent to
+     * {@code setTemplateLoader(new FileTemplateLoader(dir))}, so see
+     * {@link FileTemplateLoader#FileTemplateLoader(File)} for more details.
      * 
-     * Note that FreeMarker can load templates from non-file-system sources too. 
-     * See {@link #setTemplateLoader(TemplateLoader)} from more details.
+     * <p>
+     * Note that FreeMarker can load templates from non-file-system sources too. See
+     * {@link #setTemplateLoader(TemplateLoader)} from more details.
+     * 
+     * <p>
+     * Note that this shouldn't be used for loading templates that are coming from a WAR; use
+     * {@link #setServletContextForTemplateLoading(Object, String)} then. Servlet containers might not unpack the WAR
+     * file, in which case you clearly can't access the contained files via {@link File}. Even if the WAR is unpacked,
+     * the servlet container might not expose the location as a {@link File}.
+     * {@link #setServletContextForTemplateLoading(Object, String)} on the other hand will work in all these cases.
      */
     public void setDirectoryForTemplateLoading(File dir) throws IOException {
         TemplateLoader tl = getTemplateLoader();
@@ -1746,8 +1754,8 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
     }
 
     /**
-     * Sets when auto-escaping should be enabled depending on the current output format; default is
-     * {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}. Note that the default output format,
+     * Sets when auto-escaping should be enabled depending on the current {@linkplain OutputFormat output format};
+     * default is {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}. Note that the default output format,
      * {@link UndefinedOutputFormat}, is a non-escaping format, so there auto-escaping will be off.
      * Note that the templates can turn auto-escaping on/off locally with directives like {@code <#ftl auto_esc=...>},
      * which will ignore the policy.
@@ -1813,7 +1821,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * Sets the default output format. Usually, you should leave this on its default, which is
      * {@link UndefinedOutputFormat#INSTANCE}, and then use standard file extensions like "ftlh" (for HTML) or "ftlx"
      * (for XML) and ensure that {@link #setRecognizeStandardFileExtensions(boolean)} is {@code true} (see more there).
-     * Where you can't use standard the file extensions, templates still can be associated to output formats with
+     * Where you can't use the standard the extensions, templates still can be associated to output formats with
      * patterns matching their name (their path) using {@link #setTemplateConfigurations(TemplateConfigurationFactory)}.
      * But if all templates will have the same output format, you may use {@link #setOutputFormat(OutputFormat)} after
      * all, to set a value like {@link HTMLOutputFormat#INSTANCE}, {@link XMLOutputFormat#INSTANCE}, etc. Also note

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6b51f59d/src/test/java/freemarker/core/OutputFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/OutputFormatTest.java b/src/test/java/freemarker/core/OutputFormatTest.java
index dc5e7d4..bab9619 100644
--- a/src/test/java/freemarker/core/OutputFormatTest.java
+++ b/src/test/java/freemarker/core/OutputFormatTest.java
@@ -944,7 +944,7 @@ public class OutputFormatTest extends TemplateTest {
     }
     
     @Test
-    public void testBannedDirectivesIsWhenAutoEscaping() throws Exception {
+    public void testBannedDirectivesWhenAutoEscaping() throws Exception {
         String commonFTL = "<#escape x as x?html>x</#escape>";
         assertOutput(commonFTL, "x");
         assertErrorContains("<#ftl outputFormat='HTML'>" + commonFTL, "escape", "HTML", "double-escaping");


[13/32] incubator-freemarker git commit: Removed Eclipse project files from the source release (there are Eclipse setup instructions in the README).

Posted by dd...@apache.org.
Removed Eclipse project files from the source release (there are Eclipse setup instructions in the README).


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

Branch: refs/heads/2.3
Commit: cbf9457028c63b5fa31a4c375f1341de2af6713e
Parents: 6c4888b
Author: ddekany <dd...@apache.org>
Authored: Sat Jan 30 09:58:50 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Jan 30 09:58:50 2016 +0100

----------------------------------------------------------------------
 build.xml | 3 ---
 1 file changed, 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/cbf94570/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index f37a350..ff0030d 100644
--- a/build.xml
+++ b/build.xml
@@ -690,13 +690,10 @@
         <exclude name="**/*.*~" />
         <include name="src/**" />
         <include name="examples/**" />
-        <include name=".settings/**" />
         <include name="*.xml" />
         <include name="*.sample" />
         <include name="*.txt" />
         <include name="osgi.bnd" />
-        <include name=".classpath" />
-        <include name=".project" />
         <include name=".git*" />
       </fileset>
     </copy>


[10/32] incubator-freemarker git commit: Removed all Eclipse files, instead, added an Eclipse setup guide to the README. It's written so that it useful for other IDE-s too.

Posted by dd...@apache.org.
Removed all Eclipse files, instead, added an Eclipse setup guide to the README. It's written so that it useful for other IDE-s too.


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

Branch: refs/heads/2.3
Commit: 62158399bc38ed75e3a4895413af7190fcdc2bac
Parents: e451073
Author: ddekany <dd...@apache.org>
Authored: Mon Jan 25 17:38:45 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Jan 26 00:25:44 2016 +0100

----------------------------------------------------------------------
 .classpath                                      |  60 ---
 .project                                        |  41 --
 .settings/edu.umd.cs.findbugs.core.prefs        | 143 -------
 .../edu.umd.cs.findbugs.plugin.eclipse.prefs    |   4 -
 .settings/org.eclipse.core.resources.prefs      |   2 -
 .settings/org.eclipse.core.runtime.prefs        |   2 -
 .settings/org.eclipse.jdt.core.prefs            | 409 -------------------
 .settings/org.eclipse.jdt.ui.prefs              |  71 ----
 .../org.eclipse.ltk.core.refactoring.prefs      |   2 -
 README                                          |  86 +++-
 codestyle.xml                                   | 313 --------------
 .../Formatter-profile-FreeMarker.xml            | 313 ++++++++++++++
 12 files changed, 385 insertions(+), 1061 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.classpath
----------------------------------------------------------------------
diff --git a/.classpath b/.classpath
deleted file mode 100644
index 53283ee..0000000
--- a/.classpath
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-	<classpathentry excluding="freemarker/ext/dom/SunInternalXalanXPathSupport.java|freemarker/ext/jsp/FreeMarkerJspFactory2.java|freemarker/ext/jsp/_FreeMarkerPageContext1.java|freemarker/ext/jsp/_FreeMarkerPageContext2.java|freemarker/ext/jython/_Jython20And21VersionAdapter.java|freemarker/ext/jython/_Jython22VersionAdapter.java" kind="src" path="src/main/java"/>
-	<classpathentry kind="src" path="src/main/resources"/>
-	<classpathentry kind="src" path="src/test/java"/>
-	<classpathentry kind="src" path="src/test/resources"/>
-	<classpathentry kind="src" path="build/generated-sources/java">
-		<attributes>
-			<attribute name="ignore_optional_problems" value="true"/>
-		</attributes>
-	</classpathentry>
-	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/annotations-3.0.0.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/ant-1.6.5.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/avalon-logkit-2.0.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/com.sun.el-1.0.0.v201105211818.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/commons-logging-1.1.1.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/hamcrest-core-1.3.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/javarebel-sdk-1.2.2.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/javax.el-2.1.0.v201105211819.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/javax.servlet-2.5.0.v201103041518.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/javax.servlet.jsp-2.1.0.v201105211820.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/javax.servlet.jsp.jstl-1.2.0.v201105211821.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jaxen-1.0-FCS.jar"/>
-	<classpathentry kind="lib" path="D:/Temp/git_fm/freemarker-2.3-gae/ide-dependencies/jdom-1.0b8.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-continuation-7.6.16.v20140903.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-http-7.6.16.v20140903.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-io-7.6.16.v20140903.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-jsp-7.6.16.v20140903.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-security-7.6.16.v20140903.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-server-7.6.16.v20140903.jar" sourcepath="D:/Temp/git_fm/!non-git/jetty/jetty-server-7.6.16.v20140903-sources.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-servlet-7.6.16.v20140903.jar" sourcepath="D:/Temp/git_fm/!non-git/jetty/jetty-servlet-7.6.16.v20140903-sources.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-util-7.6.16.v20140903.jar" sourcepath="D:/Temp/git_fm/!non-git/jetty/jetty-util-7.6.16.v20140903-sources.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-webapp-7.6.16.v20140903.jar" sourcepath="D:/Temp/git_fm/!non-git/jetty/jetty-webapp-7.6.16.v20140903-sources.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jetty-xml-7.6.16.v20140903.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/js-1.6R1.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/jython-2.5.0.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/org.apache.jasper.glassfish-2.1.0.v201110031002.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/org.apache.taglibs.standard.glassfish-1.2.0.v201112081803.jar" sourcepath="D:/Temp/git_fm/!non-git/jetty/org.apache.taglibs.standard.glassfish-1.2.0.v201112081803-sources.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/org.eclipse.jdt.core-3.7.1.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/saxpath-1.0-FCS.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/xalan-2.7.0.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/dom4j-1.3.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/logback-classic-1.1.2.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/logback-core-1.1.2.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/slf4j-api-1.7.6.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/commons-io-2.2.jar" sourcepath="D:/Temp/git_fm/!non-git/jetty/commons-io-2.2-sources.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/guava-jdk5-17.0.jar"/>
-	<classpathentry exported="true" kind="lib" path="ide-dependencies/log4j-over-slf4j-1.6.1.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/commons-beanutils-1.7.0.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/commons-collections-3.1.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/commons-lang-2.3.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/displaytag-1.2.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/jcl-over-slf4j-1.6.1.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/junit-4.12.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/hamcrest-library-1.3.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/spring-core-2.5.6.SEC03.jar"/>
-	<classpathentry kind="lib" path="ide-dependencies/spring-test-2.5.6.SEC03.jar"/>
-	<classpathentry kind="output" path=".bin/"/>
-</classpath>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.project
----------------------------------------------------------------------
diff --git a/.project b/.project
deleted file mode 100644
index ccb2812..0000000
--- a/.project
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>FreeMarker-2.3-gae</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.eclipse.wst.common.project.facet.core.builder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>org.eclipse.jdt.core.javabuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-		<buildCommand>
-			<name>edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.eclipse.jdt.core.javanature</nature>
-		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
-		<nature>org.apache.ivyde.eclipse.ivynature</nature>
-		<nature>edu.umd.cs.findbugs.plugin.eclipse.findbugsNature</nature>
-	</natures>
-	<filteredResources>
-		<filter>
-			<id>0</id>
-			<name></name>
-			<type>26</type>
-			<matcher>
-				<id>org.eclipse.ui.ide.multiFilter</id>
-				<arguments>1.0-projectRelativePath-matches-false-true-build/(?!generated-sources)[\w-]+</arguments>
-			</matcher>
-		</filter>
-	</filteredResources>
-</projectDescription>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/edu.umd.cs.findbugs.core.prefs
----------------------------------------------------------------------
diff --git a/.settings/edu.umd.cs.findbugs.core.prefs b/.settings/edu.umd.cs.findbugs.core.prefs
deleted file mode 100644
index c049d3c..0000000
--- a/.settings/edu.umd.cs.findbugs.core.prefs
+++ /dev/null
@@ -1,143 +0,0 @@
-#FindBugs User Preferences
-#Sun Jul 12 16:29:44 CEST 2015
-cloud_id=edu.umd.cs.findbugs.cloud.doNothingCloud
-detectorAppendingToAnObjectOutputStream=AppendingToAnObjectOutputStream|true
-detectorAtomicityProblem=AtomicityProblem|true
-detectorBadAppletConstructor=BadAppletConstructor|false
-detectorBadResultSetAccess=BadResultSetAccess|true
-detectorBadSyntaxForRegularExpression=BadSyntaxForRegularExpression|true
-detectorBadUseOfReturnValue=BadUseOfReturnValue|true
-detectorBadlyOverriddenAdapter=BadlyOverriddenAdapter|true
-detectorBooleanReturnNull=BooleanReturnNull|true
-detectorCallToUnsupportedMethod=CallToUnsupportedMethod|false
-detectorCheckExpectedWarnings=CheckExpectedWarnings|false
-detectorCheckImmutableAnnotation=CheckImmutableAnnotation|true
-detectorCheckRelaxingNullnessAnnotation=CheckRelaxingNullnessAnnotation|true
-detectorCheckTypeQualifiers=CheckTypeQualifiers|true
-detectorCloneIdiom=CloneIdiom|true
-detectorComparatorIdiom=ComparatorIdiom|true
-detectorConfusedInheritance=ConfusedInheritance|true
-detectorConfusionBetweenInheritedAndOuterMethod=ConfusionBetweenInheritedAndOuterMethod|true
-detectorCovariantArrayAssignment=CovariantArrayAssignment|false
-detectorCrossSiteScripting=CrossSiteScripting|true
-detectorDefaultEncodingDetector=DefaultEncodingDetector|true
-detectorDoInsideDoPrivileged=DoInsideDoPrivileged|true
-detectorDontCatchIllegalMonitorStateException=DontCatchIllegalMonitorStateException|true
-detectorDontIgnoreResultOfPutIfAbsent=DontIgnoreResultOfPutIfAbsent|true
-detectorDontUseEnum=DontUseEnum|true
-detectorDroppedException=DroppedException|true
-detectorDumbMethodInvocations=DumbMethodInvocations|true
-detectorDumbMethods=DumbMethods|true
-detectorDuplicateBranches=DuplicateBranches|true
-detectorEmptyZipFileEntry=EmptyZipFileEntry|false
-detectorEqualsOperandShouldHaveClassCompatibleWithThis=EqualsOperandShouldHaveClassCompatibleWithThis|true
-detectorExplicitSerialization=ExplicitSerialization|true
-detectorFinalizerNullsFields=FinalizerNullsFields|true
-detectorFindBadCast2=FindBadCast2|true
-detectorFindBadForLoop=FindBadForLoop|true
-detectorFindCircularDependencies=FindCircularDependencies|false
-detectorFindComparatorProblems=FindComparatorProblems|true
-detectorFindDeadLocalStores=FindDeadLocalStores|true
-detectorFindDoubleCheck=FindDoubleCheck|true
-detectorFindEmptySynchronizedBlock=FindEmptySynchronizedBlock|true
-detectorFindFieldSelfAssignment=FindFieldSelfAssignment|true
-detectorFindFinalizeInvocations=FindFinalizeInvocations|true
-detectorFindFloatEquality=FindFloatEquality|true
-detectorFindHEmismatch=FindHEmismatch|true
-detectorFindInconsistentSync2=FindInconsistentSync2|true
-detectorFindJSR166LockMonitorenter=FindJSR166LockMonitorenter|true
-detectorFindLocalSelfAssignment2=FindLocalSelfAssignment2|true
-detectorFindMaskedFields=FindMaskedFields|true
-detectorFindMismatchedWaitOrNotify=FindMismatchedWaitOrNotify|true
-detectorFindNakedNotify=FindNakedNotify|true
-detectorFindNonShortCircuit=FindNonShortCircuit|true
-detectorFindNullDeref=FindNullDeref|true
-detectorFindNullDerefsInvolvingNonShortCircuitEvaluation=FindNullDerefsInvolvingNonShortCircuitEvaluation|true
-detectorFindOpenStream=FindOpenStream|true
-detectorFindPuzzlers=FindPuzzlers|true
-detectorFindRefComparison=FindRefComparison|true
-detectorFindReturnRef=FindReturnRef|true
-detectorFindRoughConstants=FindRoughConstants|true
-detectorFindRunInvocations=FindRunInvocations|true
-detectorFindSelfComparison=FindSelfComparison|true
-detectorFindSelfComparison2=FindSelfComparison2|true
-detectorFindSleepWithLockHeld=FindSleepWithLockHeld|true
-detectorFindSpinLoop=FindSpinLoop|true
-detectorFindSqlInjection=FindSqlInjection|true
-detectorFindTwoLockWait=FindTwoLockWait|true
-detectorFindUncalledPrivateMethods=FindUncalledPrivateMethods|true
-detectorFindUnconditionalWait=FindUnconditionalWait|true
-detectorFindUninitializedGet=FindUninitializedGet|true
-detectorFindUnrelatedTypesInGenericContainer=FindUnrelatedTypesInGenericContainer|true
-detectorFindUnreleasedLock=FindUnreleasedLock|true
-detectorFindUnsatisfiedObligation=FindUnsatisfiedObligation|true
-detectorFindUnsyncGet=FindUnsyncGet|true
-detectorFindUseOfNonSerializableValue=FindUseOfNonSerializableValue|true
-detectorFindUselessControlFlow=FindUselessControlFlow|true
-detectorFindUselessObjects=FindUselessObjects|true
-detectorFormatStringChecker=FormatStringChecker|true
-detectorHugeSharedStringConstants=HugeSharedStringConstants|true
-detectorIDivResultCastToDouble=IDivResultCastToDouble|true
-detectorIncompatMask=IncompatMask|true
-detectorInconsistentAnnotations=InconsistentAnnotations|true
-detectorInefficientIndexOf=InefficientIndexOf|true
-detectorInefficientInitializationInsideLoop=InefficientInitializationInsideLoop|false
-detectorInefficientMemberAccess=InefficientMemberAccess|false
-detectorInefficientToArray=InefficientToArray|true
-detectorInfiniteLoop=InfiniteLoop|true
-detectorInfiniteRecursiveLoop=InfiniteRecursiveLoop|true
-detectorInheritanceUnsafeGetResource=InheritanceUnsafeGetResource|true
-detectorInitializationChain=InitializationChain|true
-detectorInitializeNonnullFieldsInConstructor=InitializeNonnullFieldsInConstructor|true
-detectorInstantiateStaticClass=InstantiateStaticClass|true
-detectorIntCast2LongAsInstant=IntCast2LongAsInstant|true
-detectorInvalidJUnitTest=InvalidJUnitTest|true
-detectorIteratorIdioms=IteratorIdioms|true
-detectorLazyInit=LazyInit|true
-detectorLoadOfKnownNullValue=LoadOfKnownNullValue|true
-detectorLostLoggerDueToWeakReference=LostLoggerDueToWeakReference|true
-detectorMethodReturnCheck=MethodReturnCheck|true
-detectorMultithreadedInstanceAccess=MultithreadedInstanceAccess|true
-detectorMutableEnum=MutableEnum|true
-detectorMutableLock=MutableLock|true
-detectorMutableStaticFields=MutableStaticFields|true
-detectorNaming=Naming|true
-detectorNoteUnconditionalParamDerefs=NoteUnconditionalParamDerefs|true
-detectorNumberConstructor=NumberConstructor|true
-detectorOptionalReturnNull=OptionalReturnNull|true
-detectorOverridingEqualsNotSymmetrical=OverridingEqualsNotSymmetrical|true
-detectorPreferZeroLengthArrays=PreferZeroLengthArrays|true
-detectorPublicSemaphores=PublicSemaphores|false
-detectorQuestionableBooleanAssignment=QuestionableBooleanAssignment|true
-detectorReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass=ReadOfInstanceFieldInMethodInvokedByConstructorInSuperclass|true
-detectorReadReturnShouldBeChecked=ReadReturnShouldBeChecked|true
-detectorRedundantConditions=RedundantConditions|true
-detectorRedundantInterfaces=RedundantInterfaces|true
-detectorRepeatedConditionals=RepeatedConditionals|true
-detectorRuntimeExceptionCapture=RuntimeExceptionCapture|true
-detectorSerializableIdiom=SerializableIdiom|true
-detectorStartInConstructor=StartInConstructor|true
-detectorStaticCalendarDetector=StaticCalendarDetector|true
-detectorStringConcatenation=StringConcatenation|true
-detectorSuperfluousInstanceOf=SuperfluousInstanceOf|true
-detectorSuspiciousThreadInterrupted=SuspiciousThreadInterrupted|true
-detectorSwitchFallthrough=SwitchFallthrough|true
-detectorSynchronizationOnSharedBuiltinConstant=SynchronizationOnSharedBuiltinConstant|true
-detectorSynchronizeAndNullCheckField=SynchronizeAndNullCheckField|true
-detectorSynchronizeOnClassLiteralNotGetClass=SynchronizeOnClassLiteralNotGetClass|true
-detectorSynchronizingOnContentsOfFieldToProtectField=SynchronizingOnContentsOfFieldToProtectField|true
-detectorURLProblems=URLProblems|true
-detectorUncallableMethodOfAnonymousClass=UncallableMethodOfAnonymousClass|true
-detectorUnnecessaryMath=UnnecessaryMath|true
-detectorUnreadFields=UnreadFields|true
-detectorUselessSubclassMethod=UselessSubclassMethod|false
-detectorVarArgsProblems=VarArgsProblems|true
-detectorVolatileUsage=VolatileUsage|true
-detectorWaitInLoop=WaitInLoop|true
-detectorWrongMapIterator=WrongMapIterator|true
-detectorXMLFactoryBypass=XMLFactoryBypass|true
-detector_threshold=2
-effort=default
-filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,MT_CORRECTNESS,PERFORMANCE,STYLE|false|17
-filter_settings_neg=MALICIOUS_CODE,SECURITY,EXPERIMENTAL,NOISE,I18N|
-run_at_full_build=false

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs
----------------------------------------------------------------------
diff --git a/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs b/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs
deleted file mode 100644
index ac3837f..0000000
--- a/.settings/edu.umd.cs.findbugs.plugin.eclipse.prefs
+++ /dev/null
@@ -1,4 +0,0 @@
-eclipse.preferences.version=1
-edu.umd.cs.findbugs.plugin.eclipse.findbugsMarkerScariest=Error
-edu.umd.cs.findbugs.plugin.eclipse.findbugsMarkerScary=Error
-edu.umd.cs.findbugs.plugin.eclipse.findbugsMarkerTroubling=Error

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/org.eclipse.core.resources.prefs
----------------------------------------------------------------------
diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index 99f26c0..0000000
--- a/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-encoding/<project>=UTF-8

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/org.eclipse.core.runtime.prefs
----------------------------------------------------------------------
diff --git a/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs
deleted file mode 100644
index 5a0ad22..0000000
--- a/.settings/org.eclipse.core.runtime.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-line.separator=\n

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/org.eclipse.jdt.core.prefs
----------------------------------------------------------------------
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index e0e730a..0000000
--- a/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,409 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.jdt.core.codeComplete.argumentPrefixes=
-org.eclipse.jdt.core.codeComplete.argumentSuffixes=
-org.eclipse.jdt.core.codeComplete.fieldPrefixes=
-org.eclipse.jdt.core.codeComplete.fieldSuffixes=
-org.eclipse.jdt.core.codeComplete.localPrefixes=
-org.eclipse.jdt.core.codeComplete.localSuffixes=
-org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
-org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
-org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
-org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
-org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
-org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
-org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
-org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
-org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.doc.comment.support=enabled
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=warning
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=ignore
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=ignore
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
-org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
-org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
-org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
-org.eclipse.jdt.core.compiler.problem.nullReference=error
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=error
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_assignment=0
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
-org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
-org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
-org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
-org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
-org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
-org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
-org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_after_package=1
-org.eclipse.jdt.core.formatter.blank_lines_before_field=0
-org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=1
-org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
-org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
-org.eclipse.jdt.core.formatter.blank_lines_before_method=1
-org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
-org.eclipse.jdt.core.formatter.blank_lines_before_package=0
-org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
-org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
-org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
-org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
-org.eclipse.jdt.core.formatter.comment.format_block_comments=true
-org.eclipse.jdt.core.formatter.comment.format_header=false
-org.eclipse.jdt.core.formatter.comment.format_html=true
-org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
-org.eclipse.jdt.core.formatter.comment.format_line_comments=true
-org.eclipse.jdt.core.formatter.comment.format_source_code=true
-org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
-org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
-org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
-org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
-org.eclipse.jdt.core.formatter.comment.line_length=120
-org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
-org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
-org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
-org.eclipse.jdt.core.formatter.compact_else_if=true
-org.eclipse.jdt.core.formatter.continuation_indentation=2
-org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
-org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
-org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
-org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
-org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
-org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
-org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_empty_lines=false
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
-org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
-org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
-org.eclipse.jdt.core.formatter.indentation.size=8
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
-org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
-org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
-org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
-org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
-org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
-org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
-org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
-org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
-org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
-org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
-org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
-org.eclipse.jdt.core.formatter.join_lines_in_comments=true
-org.eclipse.jdt.core.formatter.join_wrapped_lines=false
-org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
-org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
-org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=true
-org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=true
-org.eclipse.jdt.core.formatter.lineSplit=120
-org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
-org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
-org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=4
-org.eclipse.jdt.core.formatter.use_on_off_tags=false
-org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
-org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
-org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
-org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/org.eclipse.jdt.ui.prefs
----------------------------------------------------------------------
diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index abd2581..0000000
--- a/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,71 +0,0 @@
-eclipse.preferences.version=1
-editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
-formatter_profile=_FreeMarker
-formatter_settings_version=12
-internal.default.compliance=default
-org.eclipse.jdt.ui.exception.name=e
-org.eclipse.jdt.ui.gettersetter.use.is=true
-org.eclipse.jdt.ui.ignorelowercasenames=true
-org.eclipse.jdt.ui.importorder=java;javax;org;com;
-org.eclipse.jdt.ui.keywordthis=false
-org.eclipse.jdt.ui.ondemandthreshold=99
-org.eclipse.jdt.ui.overrideannotation=true
-org.eclipse.jdt.ui.staticondemandthreshold=1
-sp_cleanup.add_default_serial_version_id=true
-sp_cleanup.add_generated_serial_version_id=false
-sp_cleanup.add_missing_annotations=true
-sp_cleanup.add_missing_deprecated_annotations=true
-sp_cleanup.add_missing_methods=false
-sp_cleanup.add_missing_nls_tags=false
-sp_cleanup.add_missing_override_annotations=true
-sp_cleanup.add_missing_override_annotations_interface_methods=false
-sp_cleanup.add_serial_version_id=false
-sp_cleanup.always_use_blocks=true
-sp_cleanup.always_use_parentheses_in_expressions=false
-sp_cleanup.always_use_this_for_non_static_field_access=false
-sp_cleanup.always_use_this_for_non_static_method_access=false
-sp_cleanup.convert_functional_interfaces=false
-sp_cleanup.convert_to_enhanced_for_loop=false
-sp_cleanup.correct_indentation=false
-sp_cleanup.format_source_code=false
-sp_cleanup.format_source_code_changes_only=false
-sp_cleanup.insert_inferred_type_arguments=false
-sp_cleanup.make_local_variable_final=true
-sp_cleanup.make_parameters_final=true
-sp_cleanup.make_private_fields_final=true
-sp_cleanup.make_type_abstract_if_missing_method=false
-sp_cleanup.make_variable_declarations_final=false
-sp_cleanup.never_use_blocks=false
-sp_cleanup.never_use_parentheses_in_expressions=true
-sp_cleanup.on_save_use_additional_actions=true
-sp_cleanup.organize_imports=true
-sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
-sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
-sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
-sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
-sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
-sp_cleanup.remove_private_constructors=true
-sp_cleanup.remove_redundant_type_arguments=false
-sp_cleanup.remove_trailing_whitespaces=false
-sp_cleanup.remove_trailing_whitespaces_all=true
-sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
-sp_cleanup.remove_unnecessary_casts=true
-sp_cleanup.remove_unnecessary_nls_tags=false
-sp_cleanup.remove_unused_imports=false
-sp_cleanup.remove_unused_local_variables=false
-sp_cleanup.remove_unused_private_fields=true
-sp_cleanup.remove_unused_private_members=false
-sp_cleanup.remove_unused_private_methods=true
-sp_cleanup.remove_unused_private_types=true
-sp_cleanup.sort_members=false
-sp_cleanup.sort_members_all=false
-sp_cleanup.use_anonymous_class_creation=false
-sp_cleanup.use_blocks=false
-sp_cleanup.use_blocks_only_for_return_and_throw=false
-sp_cleanup.use_lambda=true
-sp_cleanup.use_parentheses_in_expressions=false
-sp_cleanup.use_this_for_non_static_field_access=false
-sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
-sp_cleanup.use_this_for_non_static_method_access=false
-sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
-sp_cleanup.use_type_arguments=false

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/.settings/org.eclipse.ltk.core.refactoring.prefs
----------------------------------------------------------------------
diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs
deleted file mode 100644
index b196c64..0000000
--- a/.settings/org.eclipse.ltk.core.refactoring.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/README
----------------------------------------------------------------------
diff --git a/README b/README
index ee86845..f6e2c31 100644
--- a/README
+++ b/README
@@ -130,17 +130,75 @@ re-download some of them, it will not happen automatically anymore.
 You have to issue "ant update-deps" for that.
 
 
-Eclipse and other IDE-s
------------------------
-
-Run "ant ide-dependencies"; This will create an "ide-dependencies" library
-that contains all the jars that you have to add to the classpath in the IDE.
-Note that here we assume that you have run the build or at least
-"ant update-deps" earlier. 
-
-Known issue with workaround: An old org.jaxen is included in dom4j-*.jar,
-which conflicts with jaxen-*.jar. If dom4j wins, your IDE will show some
-errors in the XML related parts. To fix that, always add dom4j-*.jar last.
-
-You could also use IvyDE instead, with configuration "IDE", but as the
-dependencies hardly ever change, it might not worth the trouble.
+Eclipse and other IDE setup
+---------------------------
+
+Below you find the setp-by-step setup for Eclipse Mars.1. If you are using a
+different version or an entierly different IDE, still read this, and try to
+apply it to your development environment:
+
+- Install Ant and Ivy, if you haven't yet; see earlier.
+- From the command line, run `ant clean javacc ide-dependencies`. (Note that
+  now the "ide-dependencies" library was created. Also that
+  "build/generated-sources" was created.)
+- Start Eclipse
+- Many developers prefer to start a new workspace (File -> "Switch workspace")
+- Window -> Preferences
+  - General -> Workspace, set the text file encoding
+    to "UTF-8". (Or, you can set the same later on project level instead.)
+  - Java -> Code Style -> Formatter -> Import...
+    Select src\ide-settings\Eclipse-Mars\Formatter-profile-FreeMarker.xml
+    inside the FreeMarker project directory.
+    This profile uses space-only indentation policy and 120 character line
+    width, and formattings rules that are pretty much standard in modern Java.
+  - Java -> Installed JRE-s:
+    Ensure that you have JDK 6 installed, and that it was added to Eclipse.
+    Note that it's not JRE, but JDK.
+- Create new "Java Project" in Eclipse:
+  - In the first window popping up:
+    - Change the "location" to the directory of the FreeMarker project
+    - Press "Next"
+  - In the next window, you see the build path settings. Ensure that:
+    - On "Source" tab, ensure that exactly these are marked as source
+      directories:
+        build/generated-sources/java
+        src/main/java
+        src/main/resources
+        src/test/java
+        src/test/resources
+    - On the "Libraries" tab:
+      - Delete everyhing from there, except the "JRE System Library [...]".
+      - Edit "JRE System Library [...]" to "Execution Environment" "JavaSE 1.6"
+      - Add all jar-s that are directly under the "ide-dependencies" directory
+        (use the "Add JARs..." and select all those files).
+    - On the "Order and Export" tab find dom4j-*.jar, and send it to the
+        bottom of the list (becase, an old org.jaxen is included inside
+        dom4j-*.jar, which casues compilation errors if it wins over
+        jaxen-*.jar).
+   - Press "Finish"
+- Eclipse will indicate many errors at this point; it's expected, read on.
+- Project -> Properties -> Java Compiler
+  - Set "Compiler Compliance Level" to "1.5"
+  - In Errors/Warnings, check in "Enable project specific settings", then set
+    "Forbidden reference (access rules)" from "Error" to "Warning".
+- You will still have errors on these Java files (because different java
+  files depend on different versions of the same library, and Eclipse can't
+  handle that). Exclude them from the Build Path (in the Package Explorer,
+  right click on the problematic file -> "Build Path" -> "Exclude").
+    _Jython20*.java
+    _Jython22*.java
+    _FreeMarkerPageContext2.java
+    FreeMarkerJspFactory2.java
+  Now you shouldn't have any errors.
+- At Project -> Properties -> Java Code Style -> Formatter, check in "Enable
+  project specific settings", and then select "FreeMarker" as active profile.
+- Right click on the project -> Run As -> JUnit Test
+  It should run without problems (all green).
+- It's highly recommened to use the Eclipse FindBugs plugin.
+  - Install it from Eclipse Marketplace (3.0.1 as of this writing)
+  - Window -> Preferences -> Java -> FindBugs:
+    Set all bug marker ranks from Warning to Error. (For false alarms we add
+    @SuppressFBWarnings(value = "...", justification = "...") annotations.)
+  - Project -> Properties -> FindBugs -> [x] Run Automatically
+  - There should 0 errors. But sometimes the plugin fails to take the
+    @SuppressFBWarnings annotations into account; then use Project -> Clean. 


[21/32] incubator-freemarker git commit: Manual Version history and JavaDoc fixes/improvements.

Posted by dd...@apache.org.
Manual Version history and JavaDoc fixes/improvements.


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

Branch: refs/heads/2.3
Commit: ac7a07ef17506aad136774c441f32e11e95eb1f9
Parents: 021d95d
Author: ddekany <dd...@apache.org>
Authored: Tue Mar 15 12:40:15 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Mar 15 12:40:15 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/TextBlock.java    |   4 +
 .../java/freemarker/template/Configuration.java |   2 +-
 src/manual/en_US/book.xml                       | 162 +++++++++++--------
 3 files changed, 102 insertions(+), 66 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ac7a07ef/src/main/java/freemarker/core/TextBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TextBlock.java b/src/main/java/freemarker/core/TextBlock.java
index 3a7c78f..dce4958 100644
--- a/src/main/java/freemarker/core/TextBlock.java
+++ b/src/main/java/freemarker/core/TextBlock.java
@@ -26,6 +26,8 @@ import freemarker.template.utility.StringUtil;
 
 /**
  * A TemplateElement representing a block of plain text.
+ * 
+ * @deprected This is an internal API; don't use it.
  */
 public final class TextBlock extends TemplateElement {
     
@@ -56,6 +58,8 @@ public final class TextBlock extends TemplateElement {
 
     /**
      * Simply outputs the text.
+     * 
+     * @deprected This is an internal API; don't call or override it.
      */
     @Override
     public TemplateElement[] accept(Environment env)

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ac7a07ef/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 ec5f270..564d066 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -1821,7 +1821,7 @@ public class Configuration extends Configurable implements Cloneable, ParserConf
      * Sets the default output format. Usually, you should leave this on its default, which is
      * {@link UndefinedOutputFormat#INSTANCE}, and then use standard file extensions like "ftlh" (for HTML) or "ftlx"
      * (for XML) and ensure that {@link #setRecognizeStandardFileExtensions(boolean)} is {@code true} (see more there).
-     * Where you can't use the standard the extensions, templates still can be associated to output formats with
+     * Where you can't use the standard extensions, templates still can be associated to output formats with
      * patterns matching their name (their path) using {@link #setTemplateConfigurations(TemplateConfigurationFactory)}.
      * But if all templates will have the same output format, you may use {@link #setOutputFormat(OutputFormat)} after
      * all, to set a value like {@link HTMLOutputFormat#INSTANCE}, {@link XMLOutputFormat#INSTANCE}, etc. Also note

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ac7a07ef/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 638c695..a037f65 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26488,9 +26488,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <link linkend="dgui_misc_autoescaping">auto-escaping and output
               formats mechanism</link>, which deprecates escaping with the
               <link linkend="ref_directive_escape"><literal>escape</literal>
-              directive</link>. These are the items related to this new
-              mechanism (see <link linkend="dgui_misc_autoescaping">early
-              linked section</link> for a guide):</para>
+              directive</link>. These are the changes related to this new
+              mechanism (see earlier link for a guide):</para>
 
               <itemizedlist>
                 <listitem>
@@ -26532,16 +26531,15 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 </listitem>
 
                 <listitem>
-                  <para>Added new built-in: <literal>markup_string</literal>.
-                  This returns the markup of a <link
+                  <para>New built-in: <literal>markup_string</literal>. This
+                  returns the markup of a <link
                   linkend="dgui_misc_autoescaping_movalues">markup output
-                  value</link> as a string.</para>
+                  value</link> as string.</para>
                 </listitem>
 
                 <listitem>
-                  <para>Added new built-in:
-                  <literal>is_markup_output</literal>, returns
-                  <literal>true</literal> if the value is of type
+                  <para>New built-in: <literal>is_markup_output</literal>,
+                  returns <literal>true</literal> if the value is of type
                   <quote>markup output</quote>.</para>
                 </listitem>
 
@@ -26587,23 +26585,25 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   works with the new <quote>markup output</quote> type as
                   well. Like <literal>someMarkup + somePlainText</literal>
                   will result in markup where <literal>somePlainText</literal>
-                  is included properly escaped.</para>
+                  is escaped automatically before it's appended to the
+                  markup.</para>
                 </listitem>
 
                 <listitem>
                   <para>The <literal>has_content</literal> built-in now
-                  supports markup output values, considering 0 length markup
-                  as empty.</para>
+                  supports <quote>markup output</quote> values, considering 0
+                  length markup as empty.</para>
                 </listitem>
               </itemizedlist>
             </listitem>
 
             <listitem>
-              <para>There can be now user defined number and
-              date/time/datetime formatters, defined by the programmers when
-              configuring FreeMarker, which can be referred with strings
-              starting with <literal>"@"</literal>, like in
-              <literal>&lt;#setting number_format='@foo'&gt;</literal>, or
+              <para>You can now define custom number and date/time/datetime
+              formatters. These are defined by the programmers (and thus can
+              implement any kind of exotic formatting rules) when configuring
+              FreeMarker, and can be referred with strings starting with
+              <literal>"@"</literal>, like in <literal>&lt;#setting
+              number_format='@foo'&gt;</literal>, or
               <literal>${n?string.@foo_params}</literal>,
               <literal>&lt;#setting number_format='@foo params'&gt;</literal>,
               or <literal>${n?string.@foo}</literal>,
@@ -26622,7 +26622,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               it's possible to specify options like rounding mode or the
               symbols used, with a FreeMarker-specific <link
               linkend="topic.extendedJavaDecimalFormat">extension to the
-              pattern syntax</link>.</para>
+              <literal>DecimalFormat</literal> pattern syntax</link>.</para>
             </listitem>
 
             <listitem>
@@ -26668,8 +26668,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <literal>[<replaceable>index</replaceable>]</literal> operator,
               but not <literal>?size</literal>, which causes
               <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
-              to fail, among others. (They shouldn't implement either, but
-              this is historical heritage.)</para>
+              to fail, among others.</para>
             </listitem>
           </itemizedlist>
         </section>
@@ -26680,7 +26679,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
           <itemizedlist>
             <listitem>
               <para><emphasis role="strong">Attention!</emphasis> FreeMarker
-              now requires at least 1.5 (aka. Java 5). 2.3.24 has only
+              now requires at least Java 1.5 (aka. Java 5). 2.3.24 has only
               required Java 1.4. (Reason: Without this, new public API-s
               couldn't use generics, which affect negatively the majority of
               users, while old installations that are still using 1.4 are
@@ -26712,6 +26711,19 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
               <itemizedlist>
                 <listitem>
+                  <para>As FTL has now a new type, <quote>markup
+                  output</quote>, there's also a corresponding new model
+                  interface, <literal>TemplateMarkupOutputModel</literal>.
+                  This also means that you can prevent the auto-escaping of
+                  values coming from the data-model by returning a
+                  <literal>TemplateMarkupOutputModel</literal> instead of a
+                  <literal>String</literal>. Like the template author can just
+                  write <literal>${messages.foo}</literal>, and it will be
+                  auto-escaped or not depending on if the message is known to
+                  be markup or not.</para>
+                </listitem>
+
+                <listitem>
                   <para>Added new configuration setting:
                   <literal>recognize_standard_file_extensions</literal>. When
                   <literal>true</literal>, templates whose source name ends
@@ -26723,20 +26735,20 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   linkend="pgui_config_incompatible_improvements_how_to_set">the
                   <literal>incompatible_improvements</literal> setting</link>
                   is set to 2.3.24 (or higher) then this setting defaults to
-                  <literal>true</literal>. Otherwise it's
+                  <literal>true</literal>. Otherwise it's default is
                   <literal>false</literal>, but enabling it is highly
                   recommended.</para>
                 </listitem>
 
                 <listitem>
                   <para>Added new configuration setting:
-                  <literal>output_format</literal>. This specifies the name of
-                  the <link
+                  <literal>output_format</literal>. This specifies the <link
                   linkend="dgui_misc_autoescaping_outputformat">output
-                  format</link> (such as <literal>HTML</literal>,
-                  <literal>XML</literal>, <literal>plainText</literal>, etc.)
-                  that governs auto-escaping. The output format can be
-                  different for different templates, using the
+                  format</link> object to use (such as
+                  <literal>HTMLOutputFormat.INSTANCE</literal>,
+                  <literal>XMLOutputFormat.INSTANCE</literal>, etc.) that
+                  governs auto-escaping. The output format can be different
+                  for different templates, using the
                   <literal>template_configurations</literal> setting (<link
                   linkend="pgui_config_outputformatsautoesc">see here
                   how...</link>).</para>
@@ -26771,12 +26783,12 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <literal>TemplateDateFormat</literal>,
                   <literal>TemplateDateFormatFactory</literal>, also the
                   exceptions these can throw. These allow implementing any
-                  kind of formatting rules that are doable in Java (they
+                  kind of formatting rule that's doable in Java (i.e., they
                   aren't restricted to any <literal>java.text</literal>
                   formatters). Furthermore these formatters get the
                   <literal>TemplateModel</literal> instead of a the bare
                   <literal>java.lang.Number</literal> or
-                  <literal>java.util.Date</literal>, which let you use the
+                  <literal>java.util.Date</literal>, which lets you use the
                   extra application-specific meta information that you may
                   pack into the <literal>TemplateModel</literal>-s, such as
                   physical unit, preferred precision, and so on.</para>
@@ -26791,20 +26803,23 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   TemplateDateFormatFactory&gt;)</literal>) with which you can
                   register your own formats. These formats can be referred
                   from everywhere where you can use a string to define a
-                  format (often as a pattern), with a format string like
-                  <literal>"@foo"</literal> or <literal>"@foo
-                  params"</literal>, where <literal>"foo"</literal> is the key
-                  in the <literal>Map&lt;String, ...&gt;</literal> parameter
-                  of the earlier shown methods, and the parameters (if any)
-                  are interpreted by the
-                  <literal>Template<replaceable>Xxx</replaceable>FormatFactory</literal>.
-                  Like, you can do <literal>cfg.setNumberFormat("@foo
-                  params")</literal>, or <literal>&lt;#setting
-                  number_format='@foo params'&gt;</literal>, or
-                  <literal>${n?string.@foo_params}</literal>. For backward
-                  compatibility, the initial <literal>@</literal> only has
-                  this special meaning if either you have any custom formats
-                  or <link linkend="pgui_config_incompatible_improvements">the
+                  format, with a format string like <literal>"@foo"</literal>
+                  or <literal>"@foo params"</literal>, where
+                  <literal>"foo"</literal> is the key in the
+                  <literal>Map&lt;String, ...&gt;</literal> parameter of the
+                  earlier shown methods, and the parameters (if any) are
+                  interpreted by the
+                  <literal>Template<replaceable>Xxx</replaceable>FormatFactory</literal>
+                  implementation that you provide. Like, you can issue
+                  <literal>cfg.setNumberFormat("@foo params")</literal>, or
+                  <literal>&lt;#setting number_format='@foo
+                  params'&gt;</literal>, or
+                  <literal>${n?string.@foo_params}</literal>, similarly as you
+                  can issue <literal>cfg.setNumberFormat("0.##")</literal>,
+                  etc. For backward compatibility, the initial
+                  <literal>@</literal> only has this special meaning if either
+                  you have any custom formats or <link
+                  linkend="pgui_config_incompatible_improvements">the
                   <literal>incompatible_improvements</literal> setting</link>
                   is at least 2.3.24. Note that the
                   <literal>custom_number_formats</literal> and
@@ -26819,11 +26834,11 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 <listitem>
                   <para>Added new <literal>Environment</literal> methods
                   returning <literal>TemplateNumberFormat</literal> and
-                  <literal>TemplateDateFormat</literal> objects. See
+                  <literal>TemplateDateFormat</literal> objects. See the
                   <literal>getTemplateNumberFormat(<replaceable>...</replaceable>)</literal>
                   and
                   <literal>getTemplateDateFormat(<replaceable>...</replaceable>)</literal>
-                  variations.</para>
+                  variations in the API.</para>
                 </listitem>
 
                 <listitem>
@@ -26849,17 +26864,20 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   number and date/time/datetime formatting results, like
                   <literal>1.23*10&lt;sup&gt;6&lt;/sup&gt;</literal>, which
                   won't be accidentally auto-escaped, as FreeMarker knows that
-                  it's already HTML. (See [TODO] as an example.) Note that no
-                  out-of-the-box format formats to markup (at the moment), but
-                  you could write such custom format.</para>
+                  it's already HTML. This is done by returning a
+                  <literal>TemplateMarkupOutputModel</literal> instead of a
+                  <literal>String</literal>; see the new auto-escaping
+                  mechanism earlier. Note that no out-of-the-box format
+                  utilizes this (at the moment), but you could write such
+                  custom format.</para>
                 </listitem>
 
                 <listitem>
                   <para>The internal format object caching architecture has
-                  been reworked, so that it can handle custom formats too. But
-                  this reworking also fixes some bottlenecks under highly
-                  concurrent load, and some (otherwise unlikely) memory
-                  leaking possibilities.</para>
+                  been reworked, so that it can handle custom formats too.
+                  This reworking also fixes some bottlenecks under highly
+                  concurrent load, and some (otherwise unlikely) memory leak
+                  possibilities.</para>
                 </listitem>
               </itemizedlist>
             </listitem>
@@ -26897,9 +26915,9 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
                 <listitem>
                   <para><literal>OverrideResponseLocale</literal>: Specifies
-                  if we should override the <literal>contentType</literal>
-                  that's already set (i.e., non-<literal>null</literal>) in
-                  the <literal>HttpServletResponse</literal>. Earlier, we have
+                  if we should override the <literal>locale</literal> that's
+                  already set (i.e., non-<literal>null</literal>) in the
+                  <literal>HttpServletResponse</literal>. Earlier, we have
                   always set it, but now this behavior can be changed so that
                   we only set it if it wasn't already set.</para>
                 </listitem>
@@ -26946,15 +26964,17 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <para>Fixes and improvements in the <quote>object
               builder</quote> mini-language used for configuring FreeMarker
               from <literal>java.util.Properties</literal> or other
-              string-only sources (not used in templates). This is not to be
-              confused with the template language syntax, which has nothing to
-              do with the <quote>object builder</quote> syntax we are writing
-              about here. The improvements are:</para>
+              string-only sources (not used in templates). This is
+              <emphasis>not to be confused with the template language
+              syntax</emphasis>, which has nothing to do with the
+              <quote>object builder</quote> syntax we are writing about here.
+              The improvements are:</para>
 
               <itemizedlist>
                 <listitem>
-                  <para>For nested builder expressions, the top-level result
-                  class restriction were applied accidentally.</para>
+                  <para>Bug fixed: For nested builder expressions, the
+                  top-level result class restriction were applied
+                  accidentally.</para>
                 </listitem>
 
                 <listitem>
@@ -26997,7 +27017,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <literal>Integer</literal>, <literal>Long</literal>, or
                   <literal>BigInteger</literal>, depending on the size of the
                   number. Earlier all numbers were parsed to
-                  <literal>BigDecimal</literal>-s, but it had little
+                  <literal>BigDecimal</literal>-s, but that had little
                   importance before lists and maps were added, as the number
                   was converted to the constructor or setter parameter type
                   anyway.</para>
@@ -27219,6 +27239,18 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Due to the above change again, the return type of
+              <literal>freemarker.core.DebugBreak.accept()</literal> and
+              <literal>freemarker.core.TextBlock.accept()</literal> has
+              changed from <literal>void</literal> to
+              <literal>TemplateElement[]</literal>. This again is highly
+              unlikely to affect anyone, and these meant to be internal API-s
+              anyway, but as these two <literal>accept</literal> methods has
+              wider than package visibility for historical reasons, we mention
+              this change.</para>
+            </listitem>
+
+            <listitem>
               <para>The non-public AST API of
               <literal>freemarker.core.StringLiteral</literal>-s has been
               changed. In principle it doesn't mater as it isn't a public API,
@@ -27246,8 +27278,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
             <listitem>
               <para>Build script and distribution artifact changes to conform
-              to Apache release policy, most notably separate source and
-              binary releases.</para>
+              to Apache release policy, most notably it produces separate
+              source and binary releases.</para>
             </listitem>
           </itemizedlist>
         </section>


[31/32] incubator-freemarker git commit: Merge branch '2.3.24-gae-stabilization' into 2.3-gae

Posted by dd...@apache.org.
Merge branch '2.3.24-gae-stabilization' into 2.3-gae


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

Branch: refs/heads/2.3
Commit: 92990367797e06dda1bddbdaef608f64a06108a1
Parents: 5f9292f 4b8df1f
Author: ddekany <dd...@apache.org>
Authored: Sat Mar 26 15:45:59 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Mar 26 15:45:59 2016 +0100

----------------------------------------------------------------------
 .classpath                                      |   60 -
 .gitignore                                      |    4 +
 .project                                        |   41 -
 .settings/edu.umd.cs.findbugs.core.prefs        |  143 --
 .../edu.umd.cs.findbugs.plugin.eclipse.prefs    |    4 -
 .settings/org.eclipse.core.resources.prefs      |    2 -
 .settings/org.eclipse.core.runtime.prefs        |    2 -
 .settings/org.eclipse.jdt.core.prefs            |  409 ------
 .settings/org.eclipse.jdt.ui.prefs              |   71 -
 .../org.eclipse.ltk.core.refactoring.prefs      |    2 -
 NOTICE                                          |   12 +-
 README                                          |   96 +-
 RELEASE-NOTES                                   |    4 +-
 build.xml                                       |   44 +-
 codestyle.xml                                   |  313 ----
 src/dist/bin/NOTICE                             |   68 +-
 src/dist/jar/META-INF/NOTICE                    |   22 +
 src/dist/javadoc/META-INF/NOTICE                |    5 +
 .../Formatter-profile-FreeMarker.xml            |  313 ++++
 .../freemarker/cache/MultiTemplateLoader.java   |   61 +-
 .../cache/StatefulTemplateLoader.java           |    2 +-
 .../freemarker/cache/StringTemplateLoader.java  |   13 +
 .../freemarker/cache/WebappTemplateLoader.java  |    2 +-
 .../core/CommonTemplateMarkupOutputModel.java   |    9 +-
 .../freemarker/core/MarkupOutputFormat.java     |   26 +-
 src/main/java/freemarker/core/OutputFormat.java |    2 +-
 .../freemarker/core/TemplateConfiguration.java  |    4 +-
 .../core/TemplateMarkupOutputModel.java         |   21 +-
 src/main/java/freemarker/core/TextBlock.java    |    4 +
 .../ext/servlet/FreemarkerServlet.java          |    3 -
 .../java/freemarker/template/Configuration.java |   24 +-
 .../template/DefaultObjectWrapper.java          |    2 +-
 .../template/TemplateExceptionHandler.java      |    9 +-
 .../freemarker/template/utility/StringUtil.java |    8 +-
 .../resources/freemarker/version.properties     |    8 +-
 src/manual/en_US/book.xml                       | 1356 ++++++++----------
 .../cache/MultiTemplateLoaderTest.java          |   85 ++
 .../core/AppMetaTemplateDateFormatFactory.java  |    2 -
 .../java/freemarker/core/OutputFormatTest.java  |    2 +-
 .../config/WebappLocalFreemarkerServlet.java    |   25 +
 .../freemarker/manual/CustomFormatsExample.java |    3 +-
 .../manual/UnitAwareTemplateNumberModel.java    |    1 -
 .../CopyrightCommentRemoverTemplateLoader.java  |    4 -
 .../freemarker/test/ResourcesExtractor.java     |  296 ++++
 .../freemarker/test/servlet/WebAppTestCase.java |  175 ++-
 .../ext/jsp/webapps/basic/CONTENTS.txt          |   33 +
 .../ext/jsp/webapps/config/CONTENTS.txt         |   33 +
 .../lib/WebappLocalFreemarkerServlet.jar        |  Bin 936 -> 0 bytes
 .../webapps/config/WEB-INF/lib/templates.jar    |  Bin 1018 -> 0 bytes
 .../WEB-INF/lib/templates.jar/sub/test2.ftl     |   19 +
 .../ext/jsp/webapps/config/WEB-INF/web.xml      |    4 +-
 .../ext/jsp/webapps/errors/CONTENTS.txt         |   28 +
 .../jsp/webapps/multipleLoaders/CONTENTS.txt    |   24 +
 .../ext/jsp/webapps/tldDiscovery/CONTENTS.txt   |   37 +
 .../tldDiscovery/WEB-INF/lib/taglib-foo.jar     |  Bin 1221 -> 0 bytes
 .../lib/taglib-foo.jar/META-INF/foo bar.tld     |   32 +
 .../webapps/tldDiscovery/WEB-INF/taglib 2.jar   |  Bin 1179 -> 0 bytes
 .../WEB-INF/taglib 2.jar/META-INF/taglib.tld    |   31 +
 58 files changed, 1962 insertions(+), 2041 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/92990367/src/main/java/freemarker/template/Configuration.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/92990367/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --cc src/manual/en_US/book.xml
index 35ca1a5,e3d86c5..471b82d
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@@ -26409,53 -26489,10 +26489,48 @@@ TemplateModel x = env.getVariable("x")
      <appendix xml:id="app_versions">
        <title>Version history</title>
  
 +      <section xml:id="versions_2_3_25">
 +        <title>2.3.25</title>
 +
 +        <section>
 +          <title>Changes on the FTL side</title>
 +
 +          <itemizedlist>
 +            <listitem>
 +              <para>[TODO]</para>
 +            </listitem>
 +          </itemizedlist>
 +        </section>
 +
 +        <section>
 +          <title>Changes on the Java side</title>
 +
 +          <itemizedlist>
 +            <listitem>
 +              <para>Lazy imports: With the new boolean
 +              <literal>Configuration</literal>-level settings,
 +              <literal>lazy_imports</literal> and
 +              <literal>lazy_auto_imports</literal>, you can request imports
 +              (as in <literal>&lt;#import "lib/utils.ftl" as u&gt;</literal>)
 +              and/or auto-imports to be lazy. When the import is lazy, the
 +              namespace variable (<literal>u</literal> in this example) will
 +              be created immediately, just like before, but the template will
 +              be imported and processed only when (and if ever) the content of
 +              the imported namespace is accessed. The main application of this
 +              is with auto-imports, where you don't want the overhead of
 +              importing templates that aren't actually used in a template.
 +              (Also, a new <literal>Environment.importLib</literal> method
 +              overload was added, where you can specify if you want a lazy or
 +              an eager import.)</para>
 +            </listitem>
 +          </itemizedlist>
 +        </section>
 +      </section>
 +
        <section xml:id="versions_2_3_24">
-         <title>2.3.24 Release Candidate 1</title>
- 
-         <para>Date of release for Release Candidate 1: 2015-01-12</para>
- 
-         <para>Planned final release date: around 2016-02-20</para>
+         <title>2.3.24</title>
  
-         <para>Please test for backward compatibility, and help polishing the
-         new features!</para>
+         <para>Release date: 2016-03-20 + release process delay</para>
  
          <section>
            <title>Legal changes</title>


[19/32] incubator-freemarker git commit: (JavaDoc typos)

Posted by dd...@apache.org.
(JavaDoc 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/a925da5d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/a925da5d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/a925da5d

Branch: refs/heads/2.3
Commit: a925da5dafec3db731bf41a75e755c42a3de00fb
Parents: da3b1a6
Author: ddekany <dd...@apache.org>
Authored: Mon Mar 14 14:52:58 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Mar 14 14:52:58 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/TemplateConfiguration.java    | 4 ++--
 src/main/java/freemarker/template/DefaultObjectWrapper.java | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a925da5d/src/main/java/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/TemplateConfiguration.java b/src/main/java/freemarker/core/TemplateConfiguration.java
index 2c89d01..50ebc8f 100644
--- a/src/main/java/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/freemarker/core/TemplateConfiguration.java
@@ -38,11 +38,11 @@ import freemarker.template.utility.NullArgumentException;
  * <p>
  * Note on the {@code locale} setting: When used with the standard template loading/caching mechanism (
  * {@link Configuration#getTemplate(String)} and its overloads), localized lookup happens before the {@code locale}
- * specified here could have effect. The {@code locale} will be only set in the template that the localized looks has
+ * specified here could have effect. The {@code locale} will be only set in the template that the localized lookup has
  * already found.
  * 
  * <p>
- * Note on encoding setting {@code encoding}: See {@link #setEncoding(String)}.
+ * Note on the encoding setting {@code encoding}: See {@link #setEncoding(String)}.
  * 
  * <p>
  * Note that the result value of the reader methods (getter and "is" methods) is usually not useful unless the value of

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a925da5d/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 bda6f32..8753ebb 100644
--- a/src/main/java/freemarker/template/DefaultObjectWrapper.java
+++ b/src/main/java/freemarker/template/DefaultObjectWrapper.java
@@ -226,7 +226,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
     }
     
     /**
-     * Called for an object that aren't considered to be of a "basic" Java type, like for an application specific type,
+     * Called for an object that isn't considered to be of a "basic" Java type, like for an application specific type,
      * or for a W3C DOM node. In its default implementation, W3C {@link Node}-s will be wrapped as {@link NodeModel}-s
      * (allows DOM tree traversal), Jython objects will be delegated to the {@code JythonWrapper}, others will be
      * wrapped using {@link BeansWrapper#wrap(Object)}.


[24/32] incubator-freemarker git commit: Updating version number for 2.3.24

Posted by dd...@apache.org.
Updating version number for 2.3.24


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

Branch: refs/heads/2.3
Commit: 3f9de1c1918ff447f1f0b86f2f5dfa662b93794b
Parents: 9c68f49
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 19:30:44 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 19:30:44 2016 +0100

----------------------------------------------------------------------
 src/main/resources/freemarker/version.properties | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/3f9de1c1/src/main/resources/freemarker/version.properties
----------------------------------------------------------------------
diff --git a/src/main/resources/freemarker/version.properties b/src/main/resources/freemarker/version.properties
index e209196..11cca04 100644
--- a/src/main/resources/freemarker/version.properties
+++ b/src/main/resources/freemarker/version.properties
@@ -57,11 +57,11 @@
 #   continue working without modification or recompilation.
 # - When the major version number is increased, major backward
 #   compatibility violations are allowed, but still should be avoided.
-version=2.3.24-rc01-incubating
+version=2.3.24-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".
-mavenVersion=2.3.24-rc01-incubating
+mavenVersion=2.3.24-incubating
 
 # Version string that conforms to OSGi
 # ------------------------------------
@@ -75,7 +75,7 @@ mavenVersion=2.3.24-rc01-incubating
 #   2.4.0.pre01
 #   2.4.0.nightly_@timestampInVersion@
 # During Apache Incubation, "-incubating" is added to this string.
-versionForOSGi=2.3.24.rc01-incubating
+versionForOSGi=2.3.24.stable-incubating
 
 # Version string that conforms to legacy MF
 # -----------------------------------------
@@ -93,7 +93,7 @@ versionForOSGi=2.3.24.rc01-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.23.99.1
+versionForMf=2.3.24
 
 # The date of the build.
 # This should be automatically filled by the building tool (Ant).


[27/32] incubator-freemarker git commit: Binary release extracted directory name adjustment

Posted by dd...@apache.org.
Binary release extracted directory name adjustment


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

Branch: refs/heads/2.3
Commit: 1d4064d4adb349de6b040b2b8468f4d57a405548
Parents: 4bc1ce1
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 21:09:46 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 21:09:46 2016 +0100

----------------------------------------------------------------------
 build.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1d4064d4/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index ff0030d..09a46be 100644
--- a/build.xml
+++ b/build.xml
@@ -95,7 +95,7 @@
   
   <property name="dist.dir" value="build/dist" />
   <property name="dist.archiveBaseName" value="apache-${mavenArtifactId}-${version}" />
-  <property name="dist.bin.dir" value="${dist.dir}/bin/${dist.archiveBaseName}" />
+  <property name="dist.bin.dir" value="${dist.dir}/bin/${dist.archiveBaseName}-bin" />
   <property name="dist.src.dir" value="${dist.dir}/src/${dist.archiveBaseName}-src" />
   
   <!-- ================================================================== -->


[20/32] incubator-freemarker git commit: (Manual: Ellipsis wasn't visible.)

Posted by dd...@apache.org.
(Manual: Ellipsis wasn't visible.)


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

Branch: refs/heads/2.3
Commit: 021d95d2746616ea623a941bedec9120ff92b357
Parents: a925da5
Author: ddekany <dd...@apache.org>
Authored: Mon Mar 14 15:27:21 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Mar 14 15:27:21 2016 +0100

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


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/021d95d2/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 770418e..638c695 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -13396,10 +13396,10 @@ String BEAN_NAME = "${beanName?j_string}";</programlisting>
 
             <listitem>
               <para>Control characters in <link linkend="gloss.UCS">UCS</link>
-              code point ranges U+0000…U+001f and U+007f…U+009f are escaped as
-              <literal>\r</literal>, <literal>\n</literal>, etc., or as
-              <literal>\x<replaceable>XX</replaceable></literal> where there's
-              no special escape for them in JavaScript.</para>
+              code point ranges U+0000...U+001f and U+007f...U+009f are
+              escaped as <literal>\r</literal>, <literal>\n</literal>, etc.,
+              or as <literal>\x<replaceable>XX</replaceable></literal> where
+              there's no special escape for them in JavaScript.</para>
             </listitem>
 
             <listitem>


[11/32] incubator-freemarker git commit: Added Eclipse files to .gitignore

Posted by dd...@apache.org.
Added Eclipse files to .gitignore


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

Branch: refs/heads/2.3
Commit: 6c4888bfbd943a5abb890503202b0c3afb34d2b0
Parents: 6215839
Author: ddekany <dd...@apache.org>
Authored: Tue Jan 26 00:31:00 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Jan 26 00:31:46 2016 +0100

----------------------------------------------------------------------
 .gitignore | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/6c4888bf/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 3bc5db4..b7d0502 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,10 @@
 /bin/
 /target/
 
+.classpath
+.project
+.settings
+
 .idea/
 *.iml
 *.iws


[32/32] 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

Conflicts:
	.project


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

Branch: refs/heads/2.3
Commit: 8eada2e9d7865bc70d65062b120cb838380f8b1b
Parents: b9ca91d 9299036
Author: ddekany <dd...@apache.org>
Authored: Sat Mar 26 16:40:32 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Mar 26 16:40:32 2016 +0100

----------------------------------------------------------------------
 .classpath                                      |    60 -
 .gitignore                                      |     4 +
 .project                                        |    41 -
 .settings/edu.umd.cs.findbugs.core.prefs        |   143 -
 .../edu.umd.cs.findbugs.plugin.eclipse.prefs    |     4 -
 .settings/org.eclipse.core.resources.prefs      |     2 -
 .settings/org.eclipse.core.runtime.prefs        |     2 -
 .settings/org.eclipse.jdt.core.prefs            |   409 -
 .settings/org.eclipse.jdt.ui.prefs              |    71 -
 .../org.eclipse.ltk.core.refactoring.prefs      |     2 -
 NOTICE                                          |    12 +-
 README                                          |    96 +-
 RELEASE-NOTES                                   |     4 +-
 build.xml                                       |     5 +-
 codestyle.xml                                   |   313 -
 .../Formatter-profile-FreeMarker.xml            |   313 +
 .../freemarker/cache/MultiTemplateLoader.java   |    61 +-
 .../cache/StatefulTemplateLoader.java           |     2 +-
 .../freemarker/cache/StringTemplateLoader.java  |    13 +
 .../freemarker/cache/WebappTemplateLoader.java  |     2 +-
 src/main/java/freemarker/cache/_CacheAPI.java   |    11 +-
 .../core/CommonTemplateMarkupOutputModel.java   |     9 +-
 src/main/java/freemarker/core/Configurable.java |    10 +
 src/main/java/freemarker/core/Environment.java  |   333 +-
 src/main/java/freemarker/core/LibraryLoad.java  |    16 +-
 .../freemarker/core/MarkupOutputFormat.java     |    26 +-
 src/main/java/freemarker/core/OutputFormat.java |     2 +-
 .../freemarker/core/TemplateConfiguration.java  |     4 +-
 .../core/TemplateMarkupOutputModel.java         |    21 +-
 src/main/java/freemarker/core/TextBlock.java    |     4 +
 .../ext/servlet/FreemarkerServlet.java          |     3 -
 .../java/freemarker/template/Configuration.java |   117 +-
 .../template/DefaultObjectWrapper.java          |     2 +-
 .../template/TemplateExceptionHandler.java      |     9 +-
 .../freemarker/template/utility/StringUtil.java |     8 +-
 .../resources/freemarker/version.properties     |     8 +-
 src/manual/en_US/book.xml                       |  1396 +-
 src/manual/zh_CN/book.xml                       | 31353 +++++++++++++++++
 src/manual/zh_CN/docgen-help/README             |     2 +
 .../zh_CN/docgen-misc/googleAnalytics.html      |     9 +
 .../zh_CN/docgen-originals/figures/README       |     2 +
 src/manual/zh_CN/docgen.cjson                   |   130 +
 src/manual/zh_CN/favicon.png                    |   Bin 0 -> 1291 bytes
 src/manual/zh_CN/figures/model2sketch.png       |   Bin 0 -> 21425 bytes
 src/manual/zh_CN/figures/overview.png           |   Bin 0 -> 11837 bytes
 src/manual/zh_CN/figures/tree.png               |   Bin 0 -> 4699 bytes
 src/manual/zh_CN/logo.png                       |   Bin 0 -> 10134 bytes
 src/manual/zh_CN/placeholder.txt                |    24 -
 .../cache/MultiTemplateLoaderTest.java          |    85 +
 .../core/AppMetaTemplateDateFormatFactory.java  |     2 -
 .../freemarker/core/IncludeAndImportTest.java   |   173 +-
 .../java/freemarker/core/OutputFormatTest.java  |     2 +-
 .../config/WebappLocalFreemarkerServlet.java    |    25 +
 .../freemarker/manual/CustomFormatsExample.java |     3 +-
 .../manual/UnitAwareTemplateNumberModel.java    |     1 -
 .../freemarker/template/ConfigurationTest.java  |    22 +
 .../CopyrightCommentRemoverTemplateLoader.java  |     4 -
 .../freemarker/test/ResourcesExtractor.java     |   296 +
 .../freemarker/test/servlet/WebAppTestCase.java |   175 +-
 .../ext/jsp/webapps/basic/CONTENTS.txt          |    33 +
 .../ext/jsp/webapps/config/CONTENTS.txt         |    33 +
 .../lib/WebappLocalFreemarkerServlet.jar        |   Bin 936 -> 0 bytes
 .../webapps/config/WEB-INF/lib/templates.jar    |   Bin 1018 -> 0 bytes
 .../WEB-INF/lib/templates.jar/sub/test2.ftl     |    19 +
 .../ext/jsp/webapps/config/WEB-INF/web.xml      |     4 +-
 .../ext/jsp/webapps/errors/CONTENTS.txt         |    28 +
 .../jsp/webapps/multipleLoaders/CONTENTS.txt    |    24 +
 .../ext/jsp/webapps/tldDiscovery/CONTENTS.txt   |    37 +
 .../tldDiscovery/WEB-INF/lib/taglib-foo.jar     |   Bin 1221 -> 0 bytes
 .../lib/taglib-foo.jar/META-INF/foo bar.tld     |    32 +
 .../webapps/tldDiscovery/WEB-INF/taglib 2.jar   |   Bin 1179 -> 0 bytes
 .../WEB-INF/taglib 2.jar/META-INF/taglib.tld    |    31 +
 72 files changed, 34004 insertions(+), 2083 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8eada2e9/build.xml
----------------------------------------------------------------------

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


[06/32] incubator-freemarker git commit: Complete the Chinese translation of manual - versions 2.3.22

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen-help/editors-readme.txt
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-help/editors-readme.txt b/src/manual/zh_CN/docgen-help/editors-readme.txt
new file mode 100644
index 0000000..5280d97
--- /dev/null
+++ b/src/manual/zh_CN/docgen-help/editors-readme.txt
@@ -0,0 +1,105 @@
+Guide to FreeMarker Manual for Editors
+======================================
+
+Non-technical
+-------------
+
+- The Template Author's Guide is for Web designers. Assume that a
+  designer is not a programmer, (s)he doesn't even know what is Java.
+  Forget that FM is implemented in Java when you edit the Template
+  Author's Guide. Try to avoid technical writing.
+
+- In the Guide chapters, be careful not to mention things that were
+  not explained earlier. The Guide chapters should be understandable
+  if you read them continuously.
+
+- If you add a new topic or term, don't forget to add it to the Index.
+  Also, consider adding entries for it to the Glossary.
+
+- Don't use too sophisticated English. Use basic words and grammar.
+
+
+Technical
+---------
+
+- For the editing use XXE (XMLmind XML Editor), with its default XML
+  *source* formatting settings (identation, max line length and like).
+  You should install the "DocBook 5 for Freemarker" addon, which you can
+  find inside the "docgen" top-level SVN module.
+
+- The HTML is generated with Docgen (docgen.jar), which will check some
+  of the rules described here. To invoke it, issue "ant manual" from
+  the root of the "freemarker" module. (Note: you may need to check out
+  and build "docgen" first.)
+
+- Understand all document conventions in the Preface chapter. Note that
+  all "programlisting"-s should have a "role" attribute with a value that
+  is either: "template", "dataModel", "output", "metaTemplate" or
+  "unspecified". (If you miss this, the XXE addon will show the
+  "programlisting" in red.)
+
+- Verbatim content in flow text:
+
+  * In flow text, all data object names, class names, FTL fragments,
+    HTML fragments, and all other verbatim content is inside "literal"
+    element.
+
+  * Use replaceable element inside literal element for replaceable
+    parts and meta-variables like:
+    <literal&lt;if <replaceable>condition</replaceable>></literal>
+    <literal><replaceable>templateDir</replaceable>/copyright.ftl</literal>
+
+- Hierarchy:
+
+  * The hierarchy should look like:
+
+      book -> part -> chapter -> section -> section -> section -> section
+
+    where the "part" and the "section"-s are optional.
+    Instead of chapter you may have "preface" or "appendix".
+
+  * Don't use "sect1", "sect2", etc. Instead nest "section"-s into each other,
+    but not deeper than 3 levels.
+
+  * Use "simplesect" if you want to divide up something visually, but
+    you don't want those sections to appear in the ToC, or go into their own
+    HTML page. "simplesect"-s can appear under all "section" nesting
+    levels, and they always look the same regardless of the "section"
+    nesting levels.
+
+- Lists:
+
+  * When you have list where the list items are short (a few words),
+    you should give spacing="compact" to the "itemizedlist" or
+    "orderedlist" element.
+
+  * Don't putting listings inside "para"-s. Put them between "para"-s instead.
+
+- Xrefs, id-s, links:
+
+  * id-s of parts, chapters, sections and similar elements must
+    contain US-ASCII lower case letters, US-ASCII numbers, and
+    underscore only. id-s of parts and chapters are used as the
+    filenames of HTML-s generated for that block.
+    When you find out the id, deduce it from the position in the ToC
+    hierarchy. The underscore is used as the separator between the path
+    steps.
+
+  * All other id-s must use prefix:
+    - example: E.g.: id="example.foreach"
+    - ref: Reference information...
+      * directive: about a directive. E.g.: "ref.directive.foreach"
+      * builtin
+    - gloss: Term in the Glossary
+    - topic: The recommended point of document in a certain topic
+      * designer: for designers.
+          E.g.: id="topic.designer.methodDataObject"
+      * programmer: for programmers
+      * or omit the secondary category if it is for everybody
+    - misc: Anything doesn't fit in the above categories
+
+  * When you refer to a part, chapter or section, often you should use
+    xref, not link. The xreflabel attribute of the link-end should not be set;
+    then it's deduced from the titles.
+
+- The "book" element must have this attribute: conformance="docgen"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen-misc/googleAnalytics.html
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-misc/googleAnalytics.html b/src/manual/zh_CN/docgen-misc/googleAnalytics.html
new file mode 100644
index 0000000..bf440f2
--- /dev/null
+++ b/src/manual/zh_CN/docgen-misc/googleAnalytics.html
@@ -0,0 +1,9 @@
+<script>
+  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
+
+  ga('create', 'UA-55420501-1', 'auto');
+  ga('send', 'pageview');
+</script>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png b/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png
new file mode 100644
index 0000000..ce120cc
Binary files /dev/null and b/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt b/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt
new file mode 100644
index 0000000..1db294c
--- /dev/null
+++ b/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt
@@ -0,0 +1,24 @@
+Converting to SVG:
+1. Open the ODG file with Libeoffice/OpenOffice Draw
+2. Ctrl+A to select all objects
+3. File/Export..., chose SVG format, and then tick "Selection"
+4. Check the result. If contour lines at the right and bottom edge of the
+   figure are partically clipped (stroke width is halved), set a stroke with
+   other than 0 for all shapes.
+   
+Converting to a decent quality (though non-transparent) PNG:
+1. Open the ODG file with Libeoffice/OpenOffice Draw
+2. Export to PDF
+3. Open PDF in Adobe Acrobat Reader
+4. Go to Adobe Acrobat Reader preferences and set it to not use subpixel
+   anti-aliasing, just normal anti-aliasing. They used to call this LCD vs
+   Monitor mode.
+5. Zoom in/out until you get the desired size in pixels, take a
+   screen shot, crop it in some image editor, save it as PNG.
+   
+Converting to transparent but somewhat ugly PNG:
+1. Convert to SVG as described earlier
+2. Use Apache Batik Rasterizer command line utility like:
+   $BARIK_INSTALLATION\batik-rasterizer-1.8.jar -dpi 72 -m image/png ${FIGURE}.svg
+   If Batik fails (as it doesn't support all SVG features), use Inkscape.
+   Of course avoid supixel anti-aliasing, as it's not device independent.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen-originals/figures/overview.odg
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/overview.odg b/src/manual/zh_CN/docgen-originals/figures/overview.odg
new file mode 100644
index 0000000..0533b7c
Binary files /dev/null and b/src/manual/zh_CN/docgen-originals/figures/overview.odg differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png b/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png
new file mode 100644
index 0000000..dc4fba8
Binary files /dev/null and b/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/docgen.cjson
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen.cjson b/src/manual/zh_CN/docgen.cjson
new file mode 100644
index 0000000..7bd3a78
--- /dev/null
+++ b/src/manual/zh_CN/docgen.cjson
@@ -0,0 +1,118 @@
+//charset: UTF-8
+
+deployUrl: "http://freemarker.org/docs/"
+onlineTrackerHTML: "docgen-misc/googleAnalytics.html"
+searchKey: "014728049242975963158:8awjt03uofm"
+validation: {
+  programlistingsRequireRole
+  // programlistingsRequireLanguage
+  maximumProgramlistingWidth: 100
+}
+showXXELogo
+generateEclipseTOC
+// eclipse: {
+//  link_to: "freemarker-toc.xml#ManualLink"
+// }
+
+removeNodesWhenOnline: [ "preface" ]
+
+copyrightHolder: "The FreeMarker Project"
+copyrightStartYear: 1999
+
+seoMeta: {
+  "dgui_quickstart": {
+    "title": "Getting Started with template writing"
+  }
+  "pgui_quickstart": {
+    "title": "Getting Started with the Java API"
+  }
+}
+
+logo: {
+  href: "http://freemarker.org"
+  src: logo.png,
+  alt: "FreeMarker"
+}
+
+olinks: {
+  homepage: "http://freemarker.org/"
+  api: "api/index.html"
+  
+  // Homepage links:
+  freemarkerdownload: "http://freemarker.org/freemarkerdownload.html"
+  contribute: "http://freemarker.org/contribute.html"
+  history: "http://freemarker.org/history.html"
+  what-is-freemarker: "http://freemarker.org/index.html"
+  mailing-lists: "http://freemarker.org/mailing-lists.html"
+  
+  // Manual links:
+  templateAuthorsGuide: "id:dgui_quickstart_basics"
+  license: "id:app_license"
+  versionHistory: "id:app_versions"
+  freemarkerServlet: "id:pgui_misc_servlet"
+  
+  // External URL-s:
+  onlineTemplateTester: "http://freemarker-online.kenshoo.com/"
+  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/"
+  newStackOverflowQuestion: "http://stackoverflow.com/questions/ask?tags=freemarker"
+}
+
+internalBookmarks: {
+  "Alpha. index": alphaidx
+  "Glossary": gloss
+  "Expressions": exp_cheatsheet
+  "?builtins": ref_builtins_alphaidx
+  "#directives": ref_directive_alphaidx
+  ".spec_vars": ref_specvar
+  "FAQ": app_faq
+}
+
+tabs: {
+  "Home": "olink:homepage"
+  "Manual": ""  // Empty => We are here
+  "Java API": "olink:api"
+}
+
+// Available icons:
+// .icon-heart
+// .icon-bug
+// .icon-download
+// .icon-star
+secondaryTabs: {
+  "Contribute": { class: "icon-heart", href: "olink:contribute" }
+  "Report a Bug": { class: "icon-bug", href: "olink:newBugReport" }
+  "Download": { class: "icon-download", href: "olink:freemarkerdownload" }
+}
+
+footerSiteMap: {
+  "Overview": {
+    "What is FreeMarker?": "olink:what-is-freemarker"
+    "Download": "olink:freemarkerdownload"
+    "Version history": "id:app_versions"
+    "About us": "olink:history"
+    "License": "id:app_license"
+  }
+  "Handy stuff": {
+    "Try template online": "olink:onlineTemplateTester"
+    "Expressions cheatsheet": "id:exp_cheatsheet"
+    "#directives": "id:ref_directive_alphaidx"
+    "?built_ins": "id:ref_builtins_alphaidx"
+    ".special_vars": "id:ref_specvar"
+  }
+  "Community": {
+    "FreeMarker on Github": "olink:githubProject"
+    "Follow us on Twitter": "olink:twitter"
+    "Report a bug": "olink:newBugReport"
+    "Ask a question": "olink:newStackOverflowQuestion"
+    "Mailing lists": "olink:mailing-lists"
+  }
+}
+
+socialLinks: {
+  "Github": { class: "github", href: "olink:githubProject" }
+  "Twitter": { class: "twitter", href: "olink:twitter" }
+  "Stack Overflow": { class: "stack-overflow", href: "olink:newStackOverflowQuestion" }
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/favicon.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/favicon.png b/src/manual/zh_CN/favicon.png
new file mode 100644
index 0000000..ce0de20
Binary files /dev/null and b/src/manual/zh_CN/favicon.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/figures/model2sketch.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/figures/model2sketch.png b/src/manual/zh_CN/figures/model2sketch.png
new file mode 100644
index 0000000..93f9a6b
Binary files /dev/null and b/src/manual/zh_CN/figures/model2sketch.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/figures/overview.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/figures/overview.png b/src/manual/zh_CN/figures/overview.png
new file mode 100644
index 0000000..b32e0bd
Binary files /dev/null and b/src/manual/zh_CN/figures/overview.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/figures/tree.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/figures/tree.png b/src/manual/zh_CN/figures/tree.png
new file mode 100644
index 0000000..dcd9bf3
Binary files /dev/null and b/src/manual/zh_CN/figures/tree.png differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/logo.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/logo.png b/src/manual/zh_CN/logo.png
new file mode 100644
index 0000000..193dc11
Binary files /dev/null and b/src/manual/zh_CN/logo.png differ


[25/32] incubator-freemarker git commit: Missing copyright header.

Posted by dd...@apache.org.
Missing copyright header.


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

Branch: refs/heads/2.3
Commit: 677cdf94231a4b8bb9ca864f50f75ce8aae0340e
Parents: 3f9de1c
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 19:42:54 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 19:42:54 2016 +0100

----------------------------------------------------------------------
 .../freemarker/cache/MultiTemplateLoaderTest.java | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/677cdf94/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java b/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
index c67ca76..e4b14f3 100644
--- a/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
+++ b/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
@@ -1,3 +1,21 @@
+/*
+ * 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.cache;
 
 import static org.junit.Assert.*;


[12/32] incubator-freemarker git commit: Chinese Manual: Added copyright headers to the XML and the CJSON. Updated CJSON. Deleted non-localized image sources and README-like texts.

Posted by dd...@apache.org.
Chinese Manual: Added copyright headers to the XML and the CJSON. Updated CJSON. Deleted non-localized image sources and README-like texts.


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

Branch: refs/heads/2.3
Commit: 5f9292fb98bfdcb000c3f0d77cc67b2d895c5da8
Parents: 8bab1aa
Author: ddekany <dd...@apache.org>
Authored: Tue Jan 26 23:04:43 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Tue Jan 26 23:04:43 2016 +0100

----------------------------------------------------------------------
 src/manual/zh_CN/book.xml                       |  18 ++++
 src/manual/zh_CN/docgen-help/README             |   2 +
 src/manual/zh_CN/docgen-help/editors-readme.txt | 105 -------------------
 .../zh_CN/docgen-originals/figures/README       |   2 +
 .../figures/model2sketch_with_alpha.png         | Bin 61463 -> 0 bytes
 .../figures/odg-convert-howto.txt               |  24 -----
 .../zh_CN/docgen-originals/figures/overview.odg | Bin 11939 -> 0 bytes
 .../figures/tree_with_alpha.png                 | Bin 10304 -> 0 bytes
 src/manual/zh_CN/docgen.cjson                   |  28 +++--
 src/manual/zh_CN/placeholder.txt                |  24 -----
 10 files changed, 42 insertions(+), 161 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/book.xml b/src/manual/zh_CN/book.xml
index f092b95..327b239 100644
--- a/src/manual/zh_CN/book.xml
+++ b/src/manual/zh_CN/book.xml
@@ -1,4 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
 <book conformance="docgen" version="5.0" xml:lang="en"
       xmlns="http://docbook.org/ns/docbook"
       xmlns:xlink="http://www.w3.org/1999/xlink"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-help/README
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-help/README b/src/manual/zh_CN/docgen-help/README
new file mode 100644
index 0000000..6ebc928
--- /dev/null
+++ b/src/manual/zh_CN/docgen-help/README
@@ -0,0 +1,2 @@
+Put the locale-specific or translated guides to editors here.
+For the non-localized guides see the similar folder of the en_US Manual.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-help/editors-readme.txt
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-help/editors-readme.txt b/src/manual/zh_CN/docgen-help/editors-readme.txt
deleted file mode 100644
index 5280d97..0000000
--- a/src/manual/zh_CN/docgen-help/editors-readme.txt
+++ /dev/null
@@ -1,105 +0,0 @@
-Guide to FreeMarker Manual for Editors
-======================================
-
-Non-technical
--------------
-
-- The Template Author's Guide is for Web designers. Assume that a
-  designer is not a programmer, (s)he doesn't even know what is Java.
-  Forget that FM is implemented in Java when you edit the Template
-  Author's Guide. Try to avoid technical writing.
-
-- In the Guide chapters, be careful not to mention things that were
-  not explained earlier. The Guide chapters should be understandable
-  if you read them continuously.
-
-- If you add a new topic or term, don't forget to add it to the Index.
-  Also, consider adding entries for it to the Glossary.
-
-- Don't use too sophisticated English. Use basic words and grammar.
-
-
-Technical
----------
-
-- For the editing use XXE (XMLmind XML Editor), with its default XML
-  *source* formatting settings (identation, max line length and like).
-  You should install the "DocBook 5 for Freemarker" addon, which you can
-  find inside the "docgen" top-level SVN module.
-
-- The HTML is generated with Docgen (docgen.jar), which will check some
-  of the rules described here. To invoke it, issue "ant manual" from
-  the root of the "freemarker" module. (Note: you may need to check out
-  and build "docgen" first.)
-
-- Understand all document conventions in the Preface chapter. Note that
-  all "programlisting"-s should have a "role" attribute with a value that
-  is either: "template", "dataModel", "output", "metaTemplate" or
-  "unspecified". (If you miss this, the XXE addon will show the
-  "programlisting" in red.)
-
-- Verbatim content in flow text:
-
-  * In flow text, all data object names, class names, FTL fragments,
-    HTML fragments, and all other verbatim content is inside "literal"
-    element.
-
-  * Use replaceable element inside literal element for replaceable
-    parts and meta-variables like:
-    <literal&lt;if <replaceable>condition</replaceable>></literal>
-    <literal><replaceable>templateDir</replaceable>/copyright.ftl</literal>
-
-- Hierarchy:
-
-  * The hierarchy should look like:
-
-      book -> part -> chapter -> section -> section -> section -> section
-
-    where the "part" and the "section"-s are optional.
-    Instead of chapter you may have "preface" or "appendix".
-
-  * Don't use "sect1", "sect2", etc. Instead nest "section"-s into each other,
-    but not deeper than 3 levels.
-
-  * Use "simplesect" if you want to divide up something visually, but
-    you don't want those sections to appear in the ToC, or go into their own
-    HTML page. "simplesect"-s can appear under all "section" nesting
-    levels, and they always look the same regardless of the "section"
-    nesting levels.
-
-- Lists:
-
-  * When you have list where the list items are short (a few words),
-    you should give spacing="compact" to the "itemizedlist" or
-    "orderedlist" element.
-
-  * Don't putting listings inside "para"-s. Put them between "para"-s instead.
-
-- Xrefs, id-s, links:
-
-  * id-s of parts, chapters, sections and similar elements must
-    contain US-ASCII lower case letters, US-ASCII numbers, and
-    underscore only. id-s of parts and chapters are used as the
-    filenames of HTML-s generated for that block.
-    When you find out the id, deduce it from the position in the ToC
-    hierarchy. The underscore is used as the separator between the path
-    steps.
-
-  * All other id-s must use prefix:
-    - example: E.g.: id="example.foreach"
-    - ref: Reference information...
-      * directive: about a directive. E.g.: "ref.directive.foreach"
-      * builtin
-    - gloss: Term in the Glossary
-    - topic: The recommended point of document in a certain topic
-      * designer: for designers.
-          E.g.: id="topic.designer.methodDataObject"
-      * programmer: for programmers
-      * or omit the secondary category if it is for everybody
-    - misc: Anything doesn't fit in the above categories
-
-  * When you refer to a part, chapter or section, often you should use
-    xref, not link. The xreflabel attribute of the link-end should not be set;
-    then it's deduced from the titles.
-
-- The "book" element must have this attribute: conformance="docgen"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-originals/figures/README
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/README b/src/manual/zh_CN/docgen-originals/figures/README
new file mode 100644
index 0000000..f3a8221
--- /dev/null
+++ b/src/manual/zh_CN/docgen-originals/figures/README
@@ -0,0 +1,2 @@
+Put the translated originals (sources) of the figures used in the manual here.
+For figures that aren't translated, see the similar folder of the en_US Manual.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png b/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png
deleted file mode 100644
index ce120cc..0000000
Binary files a/src/manual/zh_CN/docgen-originals/figures/model2sketch_with_alpha.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt b/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt
deleted file mode 100644
index 1db294c..0000000
--- a/src/manual/zh_CN/docgen-originals/figures/odg-convert-howto.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-Converting to SVG:
-1. Open the ODG file with Libeoffice/OpenOffice Draw
-2. Ctrl+A to select all objects
-3. File/Export..., chose SVG format, and then tick "Selection"
-4. Check the result. If contour lines at the right and bottom edge of the
-   figure are partically clipped (stroke width is halved), set a stroke with
-   other than 0 for all shapes.
-   
-Converting to a decent quality (though non-transparent) PNG:
-1. Open the ODG file with Libeoffice/OpenOffice Draw
-2. Export to PDF
-3. Open PDF in Adobe Acrobat Reader
-4. Go to Adobe Acrobat Reader preferences and set it to not use subpixel
-   anti-aliasing, just normal anti-aliasing. They used to call this LCD vs
-   Monitor mode.
-5. Zoom in/out until you get the desired size in pixels, take a
-   screen shot, crop it in some image editor, save it as PNG.
-   
-Converting to transparent but somewhat ugly PNG:
-1. Convert to SVG as described earlier
-2. Use Apache Batik Rasterizer command line utility like:
-   $BARIK_INSTALLATION\batik-rasterizer-1.8.jar -dpi 72 -m image/png ${FIGURE}.svg
-   If Batik fails (as it doesn't support all SVG features), use Inkscape.
-   Of course avoid supixel anti-aliasing, as it's not device independent.

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-originals/figures/overview.odg
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/overview.odg b/src/manual/zh_CN/docgen-originals/figures/overview.odg
deleted file mode 100644
index 0533b7c..0000000
Binary files a/src/manual/zh_CN/docgen-originals/figures/overview.odg and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png b/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png
deleted file mode 100644
index dc4fba8..0000000
Binary files a/src/manual/zh_CN/docgen-originals/figures/tree_with_alpha.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/docgen.cjson
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/docgen.cjson b/src/manual/zh_CN/docgen.cjson
index 7bd3a78..ecff859 100644
--- a/src/manual/zh_CN/docgen.cjson
+++ b/src/manual/zh_CN/docgen.cjson
@@ -1,5 +1,22 @@
 //charset: UTF-8
 
+// 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.
+
 deployUrl: "http://freemarker.org/docs/"
 onlineTrackerHTML: "docgen-misc/googleAnalytics.html"
 searchKey: "014728049242975963158:8awjt03uofm"
@@ -16,8 +33,9 @@ generateEclipseTOC
 
 removeNodesWhenOnline: [ "preface" ]
 
-copyrightHolder: "The FreeMarker Project"
+copyrightHolder: "The Apache Software Foundation"
 copyrightStartYear: 1999
+copyrightCommentFile: "../en_US/docgen-misc/copyrightComment.txt"
 
 seoMeta: {
   "dgui_quickstart": {
@@ -42,15 +60,9 @@ olinks: {
   freemarkerdownload: "http://freemarker.org/freemarkerdownload.html"
   contribute: "http://freemarker.org/contribute.html"
   history: "http://freemarker.org/history.html"
-  what-is-freemarker: "http://freemarker.org/index.html"
+  what-is-freemarker: "http://freemarker.org/"
   mailing-lists: "http://freemarker.org/mailing-lists.html"
   
-  // Manual links:
-  templateAuthorsGuide: "id:dgui_quickstart_basics"
-  license: "id:app_license"
-  versionHistory: "id:app_versions"
-  freemarkerServlet: "id:pgui_misc_servlet"
-  
   // External URL-s:
   onlineTemplateTester: "http://freemarker-online.kenshoo.com/"
   twitter: "https://twitter.com/freemarker"

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/5f9292fb/src/manual/zh_CN/placeholder.txt
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/placeholder.txt b/src/manual/zh_CN/placeholder.txt
deleted file mode 100644
index a33e358..0000000
--- a/src/manual/zh_CN/placeholder.txt
+++ /dev/null
@@ -1,24 +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.
- */
-
-Add the Chinese Manual here, then delete this file.
-You can use these to test if the Manual is generated succesfully:
-
-  ant manualOffline_zh_CN
-  ant manualFreemarkerOrg_zh_CN


[03/32] incubator-freemarker git commit: FREEMARKER-15 fixed: Got rid of jar-s (and class binaries inside) in the test source code. I haven't implemented this as part of the build script, to help migrating to other build tools later. Instead, the JUnit t

Posted by dd...@apache.org.
FREEMARKER-15 fixed: Got rid of jar-s (and class binaries inside) in the test source code. I haven't implemented this as part of the build script, to help migrating to other build tools later. Instead, the JUnit test itself builds the required jar-s on the fly.


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

Branch: refs/heads/2.3
Commit: 99d939c99ab062a3be8491f5f64100bcc931b100
Parents: ec3d461
Author: ddekany <dd...@apache.org>
Authored: Sun Jan 24 19:18:50 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Jan 24 19:18:50 2016 +0100

----------------------------------------------------------------------
 NOTICE                                          |   4 -
 .../config/WebappLocalFreemarkerServlet.java    |  25 ++
 .../freemarker/test/ResourcesExtractor.java     | 296 +++++++++++++++++++
 .../freemarker/test/servlet/WebAppTestCase.java | 175 +++++++----
 .../ext/jsp/webapps/basic/CONTENTS.txt          |  33 +++
 .../ext/jsp/webapps/config/CONTENTS.txt         |  33 +++
 .../lib/WebappLocalFreemarkerServlet.jar        | Bin 936 -> 0 bytes
 .../webapps/config/WEB-INF/lib/templates.jar    | Bin 1018 -> 0 bytes
 .../WEB-INF/lib/templates.jar/sub/test2.ftl     |  19 ++
 .../ext/jsp/webapps/config/WEB-INF/web.xml      |   4 +-
 .../ext/jsp/webapps/errors/CONTENTS.txt         |  28 ++
 .../jsp/webapps/multipleLoaders/CONTENTS.txt    |  24 ++
 .../ext/jsp/webapps/tldDiscovery/CONTENTS.txt   |  37 +++
 .../tldDiscovery/WEB-INF/lib/taglib-foo.jar     | Bin 1221 -> 0 bytes
 .../lib/taglib-foo.jar/META-INF/foo bar.tld     |  32 ++
 .../webapps/tldDiscovery/WEB-INF/taglib 2.jar   | Bin 1179 -> 0 bytes
 .../WEB-INF/taglib 2.jar/META-INF/taglib.tld    |  31 ++
 17 files changed, 672 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
index af3d669..4c7b803 100644
--- a/NOTICE
+++ b/NOTICE
@@ -25,9 +25,5 @@ license of the FreeMarker project:
 
     src/main/misc/overloadedNumberRules/prices.ods
     src/manual/en_US/docgen-originals/figures/overview.odg
-    src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar
-    src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar
-    src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar
-    src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar
 
 =========================================================================

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java b/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java
new file mode 100644
index 0000000..9411633
--- /dev/null
+++ b/src/test/java/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.java
@@ -0,0 +1,25 @@
+/*
+ * 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.ext.jsp.webapps.config;
+
+import freemarker.ext.servlet.FreemarkerServlet;
+
+public class WebappLocalFreemarkerServlet extends FreemarkerServlet {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/java/freemarker/test/ResourcesExtractor.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/test/ResourcesExtractor.java b/src/test/java/freemarker/test/ResourcesExtractor.java
new file mode 100644
index 0000000..88e1bed
--- /dev/null
+++ b/src/test/java/freemarker/test/ResourcesExtractor.java
@@ -0,0 +1,296 @@
+/*
+ * 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 java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Files;
+
+import freemarker.template.utility.StringUtil;
+
+/**
+ * Extracts a collection of resources from a Java package into a file system directory, based on the {@value ResourcesExtractor#CONTENTS_TXT}
+ * resource in it. It won't scan to find resources automatically, so everything has to be added to this file.
+ * 
+ * <p>Regarding the content of {@value ResourcesExtractor#CONTENTS_TXT}:
+ * <ul>
+ *   <li>Lines starting with {code //} or {code /*} or {code *} are comments.
+ *   <li>Each non-empty line in the {@value ResourcesExtractor#CONTENTS_TXT} that isn't comment, there must be
+ *       a resource path relative to the "directory" that contains {@value ResourcesExtractor#CONTENTS_TXT}. Only the
+ *       files referred this way will be copied. (Referring to directories doesn't copy the files in them.)
+ *   <li>If the entry ends with {@code "/"}, then it denotes a directory that must be created even if there will be
+ *       no files in it. Otherwise it's redundant to add such entries. 
+ *   <li>The content of "subdirectories" whose name ends with  {@value ResourcesExtractor#SUFFIX_JAR} will be copied
+ *       into a jar file with similar name, instead of into a directory.
+ *   <li>An line may contains {@value #ARROW}, in which case the left side of the {@value #ARROW} is the
+ *       <em>absolute</em> path of the copied resource, and the right side of the {@value #ARROW} is the target
+ *       relative path (like the path in the usual lines). This is useful for copying class files generated by
+ *       the normal Java compilation mechanism into target subdirectories like {@code WEB-INF\classes\com\example}.
+ * </ul>
+ */
+public final class ResourcesExtractor {
+    
+    private static final String ARROW = "->";
+    private static final String DOT_TMP = ".tmp";
+    public static final String CONTENTS_TXT = "CONTENTS.txt";
+    public static final String SUFFIX_JAR = ".jar";
+
+    private static final Logger LOG = LoggerFactory.getLogger(ResourcesExtractor.class);
+    
+    private ResourcesExtractor() {
+        // Not meant to be instantiated
+    }
+    
+    /**
+     * @param resolverClass
+     *            The class with which the resources are loaded.
+     * @param srcDirResourcePath
+     *            The resource path to which the paths in {@value ResourcesExtractor#CONTENTS_TXT} are relative to. If
+     *            the value of this parameter doesn't start with {@code "/"}, then it's relative to the package of the
+     *            {@code resolverClass}.
+     * 
+     * @return The temporary directory into which the resource where extracted to. Don't forget to delete it when it's
+     *         not used anymore.
+     */
+    public static File extract(Class resolverClass, String srcDirResourcePath, File dstRootDir) throws IOException {
+        if (!srcDirResourcePath.endsWith("/")) {
+            srcDirResourcePath += "/";
+        }
+        
+        String contResource = srcDirResourcePath + CONTENTS_TXT;
+        InputStream contIn = resolverClass.getResourceAsStream(contResource);
+        if (contIn == null) {
+            throw new IOException("Can't find resource: class=" + resolverClass + ", path=" + contResource);
+        }
+        
+        boolean deleteDstRootDir;
+        if (dstRootDir == null) {
+            dstRootDir = Files.createTempDir();
+            deleteDstRootDir = true;
+        } else {
+            deleteDstRootDir = !dstRootDir.exists();
+        }
+        try {
+            BufferedReader contR = new BufferedReader(new InputStreamReader(contIn, "UTF-8"));
+            try {
+                String contLine;
+                while ((contLine = contR.readLine()) != null) {
+                    processLine(contLine, resolverClass, srcDirResourcePath, dstRootDir, contResource);
+                }
+            } finally {
+                contR.close();
+            }
+            jarMarkedSubdirectories(dstRootDir);
+            deleteDstRootDir = false;
+        } finally {
+            if (deleteDstRootDir) {
+                try {
+                    if (dstRootDir.getParentFile() == null) {
+                        throw new IOException("Won't delete the root directory");
+                    }
+                    FileUtils.deleteDirectory(dstRootDir);
+                } catch (IOException e) {
+                    LOG.error("Failed to delete destination directory: " + dstRootDir, e);
+                }
+            }
+        }
+        
+        return dstRootDir;
+    }
+    
+    private static void processLine(String contLine, Class<?> resolverClass, String srcDirResourcePath, File dstRootDir,
+            String contResource) throws IOException {
+        contLine = contLine.trim();
+        if (contLine.isEmpty() || contLine.startsWith("//") || contLine.startsWith("/*")
+                || contLine.startsWith("*")) {
+            return;
+        }
+        
+        String contSrcPath = contLine;
+        String contDstPath = contLine;
+        boolean contSrcPathRelative;
+        int arrowIdx = contLine.indexOf(ARROW);
+        if (arrowIdx != -1) {
+            if (!contLine.startsWith("/")) {
+                throw new IOException("In " + StringUtil.jQuote(contResource) + ", this line must start with "
+                        + "\"/\" as it uses the " + StringUtil.jQuote(ARROW) + " operator : "
+                        + contLine);
+            }
+            contSrcPath = contLine.substring(0, arrowIdx).trim();
+            contDstPath = contLine.substring(arrowIdx + ARROW.length()).trim();
+            contSrcPathRelative = false;
+        } else {
+            if (contLine.startsWith("/")) {
+                throw new IOException("In " + StringUtil.jQuote(contResource)
+                        + ", this line can't start with \"/\": " + contLine);
+            }
+            contSrcPathRelative = true;
+            contSrcPath = contLine;
+            contDstPath = contLine;
+        }
+        File dstFile = new File(dstRootDir, contDstPath);
+        if (contLine.endsWith("/")) {
+            if (!dstFile.mkdirs()) {
+                throw new IOException("Failed to create directory: " + dstFile);
+            }
+        } else {
+            String srcEntryPath = contSrcPathRelative ? srcDirResourcePath + contSrcPath : contSrcPath;
+            InputStream entryIn = resolverClass.getResourceAsStream(srcEntryPath);
+            if (entryIn == null) {
+                throw new IOException("Can't find resource: class=" + resolverClass + ", path=" + srcEntryPath);
+            }
+            try {
+                if (dstFile.exists()) {
+                    throw new IOException(
+                            "Destination already exists; check if " + StringUtil.jQuote(contDstPath)
+                            + " occurs for multiple times in \"" + CONTENTS_TXT + "\".");
+                }
+                FileUtils.copyInputStreamToFile(entryIn, dstFile);
+            } catch (IOException e) {
+                File parent = dstFile;
+                while ((parent = dstFile.getParentFile()) != null) {
+                    if (parent.isFile()) {
+                        throw new IOException("An ancestor directory of " + StringUtil.jQuote(dstFile) + ", "
+                        + StringUtil.jQuote(parent) + " already exists, but as a file, not as a directory. "
+                        + "Check if you have accidentally added the directory itself to \"" + CONTENTS_TXT
+                        + "\". Only files should be listed there.");
+                    }
+                }
+                throw e;
+            } finally {
+                entryIn.close();
+            }
+        }
+    }
+    
+    /**
+     * @param extension
+     *            The file extension of the resulting jar archive, or {@code null} if the archive name will be the same
+     *            as the directory name.
+     */
+    private static File replaceDirectoryWithJar(File srcDir, String extension) throws IOException {
+        String workJarFileName;
+        String finalJarFileName;
+        if (extension == null) {
+            finalJarFileName = srcDir.getName();
+            workJarFileName = finalJarFileName + DOT_TMP;
+        } else {
+            finalJarFileName = srcDir.getName() + "." + extension;
+            workJarFileName = finalJarFileName;
+        }
+        
+        File workJarFile = new File(srcDir.getParentFile(), workJarFileName);
+        jarDirectory(srcDir, workJarFile);
+        
+        if (srcDir.getParentFile() == null) {
+            throw new IOException("Won't delete the root directory");
+        }
+        FileUtils.deleteDirectory(srcDir);
+        
+        File finalJarFile;
+        if (!workJarFileName.equals(finalJarFileName)) {
+            finalJarFile = new File(workJarFile.getParentFile(), finalJarFileName);
+            FileUtils.moveFile(workJarFile, finalJarFile);
+        } else {
+            finalJarFile = workJarFile; 
+        }
+        
+        return finalJarFile;        
+    }
+
+    private static void jarDirectory(File srcDir, File jarFile) throws FileNotFoundException, IOException {
+        boolean finished = false;
+        try {
+            FileOutputStream fileOut = new FileOutputStream(jarFile);
+            try {
+                JarOutputStream jarOut = new JarOutputStream(fileOut);
+                try {
+                    addFilesToJar("", srcDir, jarOut);
+                } finally {
+                    jarOut.close();
+                }
+            } finally {
+                fileOut.close();
+            }
+            finished = true;
+        } finally {
+            if (!finished) {
+                if (!jarFile.delete()) {
+                    LOG.error("Failed to delete file: {}", jarFile);
+                }
+            }
+        }
+    }
+
+    private static void jarMarkedSubdirectories(File dir) throws IOException {
+        File[] entries = dir.listFiles();
+        if (entries == null) {
+            throw new IOException("Failed to list directory: " + dir);
+        }
+        for (File entry : entries) {
+            if (entry.isDirectory()) {
+                jarMarkedSubdirectories(entry);
+                if (entry.getName().endsWith(SUFFIX_JAR)) {
+                    replaceDirectoryWithJar(entry, null);
+                }
+            }
+        }
+    }
+
+    private static void addFilesToJar(String entryBasePath, File dir, JarOutputStream jarOut) throws IOException {
+        File[] entries = dir.listFiles();
+        if (entries == null) {
+            throw new IOException("Couldn't list directory: " + dir);
+        }
+        for (File entry : entries) {
+            if (entry.isFile()) {
+                jarOut.putNextEntry(new ZipEntry(entryBasePath + entry.getName()));
+                FileInputStream fileIn = new FileInputStream(entry);
+                try {
+                    IOUtils.copy(fileIn, jarOut);
+                } finally {
+                    fileIn.close();
+                }
+                jarOut.closeEntry();
+            } else if (entry.isDirectory()) {
+                String dirPath = entryBasePath + entry.getName() + "/";
+                jarOut.putNextEntry(new ZipEntry(dirPath));
+                jarOut.closeEntry();
+                addFilesToJar(dirPath, entry, jarOut);
+            } else {
+                throw new IOException("Couldn't open source entry: " + entry);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/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 223c696..6bd7f44 100644
--- a/src/test/java/freemarker/test/servlet/WebAppTestCase.java
+++ b/src/test/java/freemarker/test/servlet/WebAppTestCase.java
@@ -21,17 +21,18 @@ package freemarker.test.servlet;
 
 import static org.junit.Assert.*;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@@ -42,10 +43,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import freemarker.test.ResourcesExtractor;
 import freemarker.test.TestUtil;
 
 public class WebAppTestCase {
-    
+
     public static final String IGNORED_MASK = "[IGNORED]";
 
     private static final Logger LOG = LoggerFactory.getLogger(WebAppTestCase.class);
@@ -53,32 +55,35 @@ public class WebAppTestCase {
     private static final String ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN
             = "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern";
 
-    private static final String EXPECTED_DIR = "/WEB-INF/expected/";
+    private static final String EXPECTED_DIR = "WEB-INF/expected/";
 
     private static Server server;
     private static ContextHandlerCollection contextHandlers;
-    private static Map<String, WebAppContext> deployedWebApps = new HashMap<String, WebAppContext>(); 
-    
+    private static Map<String, WebAppContext> deployedWebApps = new HashMap<String, WebAppContext>();
+    private static volatile File testTempDirectory;
+
     @BeforeClass
     public static void beforeClass() throws Exception {
         // Work around Java 5 bug(?) that causes Jasper to fail with "zip file closed" when it reads the JSTL jar:
         org.eclipse.jetty.util.resource.Resource.setDefaultUseCaches(false);
-        
+
         LOG.info("Starting embedded Jetty...");
-        
+
         server = new Server(0);
-        
+
         contextHandlers = new ContextHandlerCollection();
         server.setHandler(contextHandlers);
-        
+
         server.start();
     }
-    
+
     @AfterClass
     public static void afterClass() throws Exception {
         LOG.info("Stopping embedded Jetty...");
         server.stop();
-        server.join(); // TODO redundant?
+        server.join();
+        LOG.info("Jetty stopped.");
+        deleteTemporaryDirectories();
     }
 
     protected final String getResponseContent(String webAppName, String webAppRelURL) throws Exception {
@@ -95,7 +100,7 @@ public class WebAppTestCase {
         HTTPResponse resp = getHTTPResponse(webAppName, webAppRelURL);
         return resp.getStatusCode();
     }
-    
+
     protected final HTTPResponse getHTTPResponse(String webAppName, String webAppRelURL) throws Exception {
         if (webAppName.startsWith("/") || webAppName.endsWith("/")) {
             throw new IllegalArgumentException("\"webAppName\" can't start or end with \"/\": " + webAppName);
@@ -103,9 +108,9 @@ public class WebAppTestCase {
         if (webAppRelURL.startsWith("/") || webAppRelURL.endsWith("/")) {
             throw new IllegalArgumentException("\"webappRelURL\" can't start or end with \"/\": " + webAppRelURL);
         }
-        
+
         ensureWebAppIsDeployed(webAppName);
-        
+
         final URI uri = new URI("http://localhost:" + server.getConnectors()[0].getLocalPort()
                 + "/" + webAppName + "/" + webAppRelURL);
 
@@ -115,7 +120,7 @@ public class WebAppTestCase {
             LOG.debug("HTTP GET: {}", uri);
 
             final int responseCode = httpCon.getResponseCode();
-            
+
             final String content;
             if (responseCode == 200) {
                 InputStream in = httpCon.getInputStream();
@@ -127,7 +132,7 @@ public class WebAppTestCase {
             } else {
                 content = null;
             }
-            
+
             return new HTTPResponse(
                     responseCode, httpCon.getResponseMessage(),
                     content,
@@ -136,12 +141,13 @@ public class WebAppTestCase {
             httpCon.disconnect();
         }
     }
-    
+
     /**
      * Compares the output of the JSP and the FTL version of the same page, ignoring some of the whitespace differences.
-     * @param webAppRelURLWithoutExt something like {@code "tester?view=foo"}, which will be extended to
-     *          {@code "tester?view=foo.jsp"} and {@code "tester?view=foo.ftl"}, and then the output of these extended
-     *          URL-s will be compared.
+     * 
+     * @param webAppRelURLWithoutExt
+     *            something like {@code "tester?view=foo"}, which will be extended to {@code "tester?view=foo.jsp"} and
+     *            {@code "tester?view=foo.ftl"}, and then the output of these extended URL-s will be compared.
      */
     protected void assertJSPAndFTLOutputEquals(String webAppName, String webAppRelURLWithoutExt) throws Exception {
         assertOutputsEqual(webAppName, webAppRelURLWithoutExt + ".jsp", webAppRelURLWithoutExt + ".ftl");
@@ -163,7 +169,7 @@ public class WebAppTestCase {
             boolean compressWS) throws Exception {
         assertExpectedEqualsOutput(webAppName, expectedFileName, webAppRelURL, compressWS, null);
     }
-    
+
     /**
      * @param expectedFileName
      *            The name of the file that stores the expected content, relatively to
@@ -177,7 +183,9 @@ public class WebAppTestCase {
         final String actual = normalizeWS(getResponseContent(webAppName, webAppRelURL), compressWS);
         final String expected;
         {
-            final InputStream in = new URL(getWebAppDirURL(webAppName) + EXPECTED_DIR + expectedFileName).openStream();
+            ClassPathResource cpResource = findWebAppDirectoryResource(webAppName);
+            final InputStream in = cpResource.resolverClass.getResourceAsStream(
+                    cpResource.path + EXPECTED_DIR + expectedFileName);
             try {
                 expected = TestUtil.removeTxtCopyrightComment(normalizeWS(IOUtils.toString(in, "utf-8"), compressWS));
             } finally {
@@ -186,10 +194,10 @@ public class WebAppTestCase {
         }
         assertEquals(maskIgnored(expected, ignoredParts), maskIgnored(actual, ignoredParts));
     }
-    
+
     private String maskIgnored(String s, List<Pattern> ignoredParts) {
         if (ignoredParts == null) return s;
-        
+
         for (Pattern ignoredPart : ignoredParts) {
             s = ignoredPart.matcher(s).replaceAll(IGNORED_MASK);
         }
@@ -203,11 +211,11 @@ public class WebAppTestCase {
             context.start();
         }
     }
-    
-    private Pattern BR = Pattern.compile("\r\n|\r"); 
-    private Pattern MULTI_LINE_WS = Pattern.compile("[\t ]*[\r\n][\t \r\n]*", Pattern.DOTALL); 
-    private Pattern SAME_LINE_WS = Pattern.compile("[\t ]+", Pattern.DOTALL); 
-    
+
+    private Pattern BR = Pattern.compile("\r\n|\r");
+    private Pattern MULTI_LINE_WS = Pattern.compile("[\t ]*[\r\n][\t \r\n]*", Pattern.DOTALL);
+    private Pattern SAME_LINE_WS = Pattern.compile("[\t ]+", Pattern.DOTALL);
+
     private String normalizeWS(String s, boolean compressWS) {
         if (compressWS) {
             return SAME_LINE_WS.matcher(
@@ -223,65 +231,106 @@ public class WebAppTestCase {
         if (deployedWebApps.containsKey(webAppName)) {
             return;
         }
-        
-        final String webAppDirURL = getWebAppDirURL(webAppName);
-        
+
+        final String webAppDirURL = createWebAppDirAndGetURI(webAppName);
+
         WebAppContext context = new WebAppContext(webAppDirURL, "/" + webAppName);
-        
+
         // Pattern of jar file names scanned for META-INF/*.tld:
         context.setAttribute(
                 ATTR_JETTY_CONTAINER_INCLUDE_JAR_PATTERN,
                 ".*taglib.*\\.jar$");
-
         contextHandlers.addHandler(context);
         // As we add this after the Server was started, it has to be started manually:
         context.start();
-        
+
         deployedWebApps.put(webAppName, context);
         LOG.info("Deployed web app.: {}", webAppName);
     }
 
-    @SuppressFBWarnings(value="UI_INHERITANCE_UNSAFE_GETRESOURCE", justification="By design relative to subclass")
-    private String getWebAppDirURL(String webAppName) throws IOException {
-        final URL webXmlURL;
-        {
-            final String relResPath = "webapps/" + webAppName + "/WEB-INF/web.xml";
-            
-            Class<?> baseClass = this.getClass();
-            findWebXmlURL: do {
-                URL r = baseClass.getResource(relResPath);
-                if (r != null) {
-                    webXmlURL = r;
-                    break findWebXmlURL;
-                }
-                
-                baseClass = baseClass.getSuperclass();
-                if (!WebAppTestCase.class.isAssignableFrom(baseClass)) {
-                    throw new IOException("Can't find test class relative resource: " + relResPath);
-                }
-            } while (true);
+    private static void deleteTemporaryDirectories() throws IOException {
+        if (testTempDirectory.getParentFile() == null) {
+            throw new IOException("Won't delete the root directory");
         }
-        
         try {
-            return webXmlURL.toURI().resolve("..").toString();
-        } catch (URISyntaxException e) {
-            throw new RuntimeException("Failed to get grandparent URL for " + webXmlURL, e);
+            FileUtils.forceDelete(testTempDirectory);
+        } catch (IOException e) {
+            LOG.warn("Failed to delete temporary file or directory; will re-try on JVM shutdown: "
+                    + testTempDirectory);
+            FileUtils.forceDeleteOnExit(testTempDirectory);
         }
     }
+
+    @SuppressFBWarnings(value = "UI_INHERITANCE_UNSAFE_GETRESOURCE", justification = "By design relative to subclass")
+    private String createWebAppDirAndGetURI(String webAppName) throws IOException {
+        ClassPathResource resourceDir = findWebAppDirectoryResource(webAppName);
+        File temporaryDir = ResourcesExtractor.extract(
+                resourceDir.resolverClass, resourceDir.path, new File(getTestTempDirectory(), webAppName));
+        return temporaryDir.toURI().toString();
+    }
+
+    private ClassPathResource findWebAppDirectoryResource(String webAppName) throws IOException {
+        final String appRelResPath = "webapps/" + webAppName + "/";
+        final String relResPath = appRelResPath + "WEB-INF/web.xml";
+
+        Class<?> baseClass = this.getClass();
+        do {
+            URL r = baseClass.getResource(relResPath);
+            if (r != null) {
+                return new ClassPathResource(baseClass, appRelResPath);
+            }
+
+            baseClass = baseClass.getSuperclass();
+            if (!WebAppTestCase.class.isAssignableFrom(baseClass)) {
+                throw new IOException("Can't find test class relative resource: " + relResPath);
+            }
+        } while (true);
+    }
     
+    private File getTestTempDirectory() throws IOException {
+        if (testTempDirectory == null) {
+            // As at least on Windows we have problem deleting the directories once Jetty has used them (the file
+            // handles of the jars remain open), we always use the same name, so that at most one will remain there.
+            File d = new File(
+                    new File(System.getProperty("java.io.tmpdir")),
+                    "freemarker-jetty-junit-tests-(delete-it)");
+            if (d.exists()) {
+                FileUtils.deleteDirectory(d);
+            }
+            if (!d.mkdirs()) {
+               throw new IOException("Failed to create Jetty temp directory: " + d); 
+            }
+            testTempDirectory = d;
+        }
+        return testTempDirectory;
+    }
+
+    private static class ClassPathResource {
+
+        private final Class<?> resolverClass;
+        private final String path;
+
+        public ClassPathResource(Class<?> resolverClass, String path) {
+            this.resolverClass = resolverClass;
+            this.path = path;
+        }
+
+    }
+
     private static class HTTPResponse {
+
         private final int statusCode;
         private final String content;
         private final String statusMessage;
         private final URI uri;
-        
+
         public HTTPResponse(int statusCode, String statusMessage, String content, URI uri) {
             this.statusCode = statusCode;
             this.content = content;
             this.statusMessage = statusMessage;
             this.uri = uri;
         }
-        
+
         public String getStatusMessage() {
             return statusMessage;
         }
@@ -289,7 +338,7 @@ public class WebAppTestCase {
         public int getStatusCode() {
             return statusCode;
         }
-        
+
         public String getContent() {
             return content;
         }
@@ -297,7 +346,7 @@ public class WebAppTestCase {
         public URI getURI() {
             return uri;
         }
-        
+
     }
-    
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt
new file mode 100644
index 0000000..c3f6857
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/basic/CONTENTS.txt
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+ 
+// Only the files listed here will be part of the tested Web application deployment! 
+
+attributes.ftl
+customELFunctions1.ftl
+customELFunctions1.jsp
+customTags1.ftl
+trivial-jstl-@Ignore.ftl
+trivial.ftl
+trivial.jsp
+
+WEB-INF/el-functions.tld
+WEB-INF/expected
+WEB-INF/test.tld
+WEB-INF/web.xml

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt
new file mode 100644
index 0000000..3157059
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/CONTENTS.txt
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+ 
+// Only the files listed here will be part of the tested Web application deployment! 
+
+test.ftl
+
+WEB-INF/web.xml
+
+WEB-INF/classes/test.ftl
+
+WEB-INF/classes/sub/test.ftl
+
+WEB-INF/lib/templates.jar/sub/test2.ftl
+/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.class -> WEB-INF/lib/WebappLocalFreemarkerServlet.jar/freemarker/ext/jsp/webapps/config/WebappLocalFreemarkerServlet.class
+
+WEB-INF/templates/test.ftl

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar
deleted file mode 100644
index 5af54da..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/WebappLocalFreemarkerServlet.jar and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar
deleted file mode 100644
index 8e5f2e5..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar and /dev/null differ
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
new file mode 100644
index 0000000..71b1d86
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
@@ -0,0 +1,19 @@
+<#--
+  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.
+-->
+from WEB-INF/lib/templates.jar/sub
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
new file mode 100644
index 0000000..71b1d86
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/lib/templates.jar/sub/test2.ftl
@@ -0,0 +1,19 @@
+<#--
+  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.
+-->
+from WEB-INF/lib/templates.jar/sub
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
index a8328b4..8818368 100644
--- a/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
+++ b/src/test/resources/freemarker/ext/jsp/webapps/config/WEB-INF/web.xml
@@ -35,7 +35,7 @@
     <!-- Must use a webapp-local class for "class:", otherwise it won't find local resources. -->
     <servlet>
         <servlet-name>freemarker-class-root</servlet-name>
-        <servlet-class>webapps.cfg.WebappLocalFreemarkerServlet</servlet-class>
+        <servlet-class>freemarker.ext.jsp.webapps.config.WebappLocalFreemarkerServlet</servlet-class>
         <init-param>
             <param-name>TemplatePath</param-name>
             <param-value>class://</param-value>
@@ -43,7 +43,7 @@
     </servlet>
     <servlet>
         <servlet-name>freemarker-class-sub</servlet-name>
-        <servlet-class>webapps.cfg.WebappLocalFreemarkerServlet</servlet-class>
+        <servlet-class>freemarker.ext.jsp.webapps.config.WebappLocalFreemarkerServlet</servlet-class>
         <init-param>
             <param-name>TemplatePath</param-name>
             <param-value>class://sub</param-value>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt
new file mode 100644
index 0000000..62d711e
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/errors/CONTENTS.txt
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+ 
+// Only the files listed here will be part of the tested Web application deployment! 
+
+failing-parsetime.ftlnv
+failing-parsetime.jsp
+failing-runtime.ftl
+failing-runtime.jsp
+not-failing.ftl
+
+WEB-INF/web.xml
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt
new file mode 100644
index 0000000..5453db8
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/multipleLoaders/CONTENTS.txt
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+ 
+// Only the files listed here will be part of the tested Web application deployment! 
+
+WEB-INF/web.xml
+
+WEB-INF/templates/test.ftl

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt
new file mode 100644
index 0000000..d38119e
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/CONTENTS.txt
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+ 
+// Only the files listed here will be part of the tested Web application deployment! 
+
+test-noClasspath.ftl
+test1.ftl
+
+WEB-INF/fmtesttag 2.tld
+WEB-INF/fmtesttag4.tld
+WEB-INF/web.xml
+
+WEB-INF/taglib 2.jar/META-INF/taglib.tld
+
+WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
+
+WEB-INF/subdir-with-tld/fmtesttag3.tld
+
+not-auto-scanned/fmtesttag.tld
+
+subdir/test-rel.ftl

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar
deleted file mode 100644
index aa6c542..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar and /dev/null differ
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
new file mode 100644
index 0000000..3f2e096
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld	
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+  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.
+-->
+<!DOCTYPE taglib
+        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+        "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+  <tlibversion>2.0</tlibversion>
+  <jspversion>1.2</jspversion>
+  <shortname>FreeMarker JUnit Test Support 3</shortname>
+  <uri>http://freemarker.sf.net/taglibs/freemarker-junit-test-tag-2.2-foo</uri>
+  <tag>
+    <name>testtag</name>
+    <tagclass>freemarker.ext.jsp.taglibmembers.TestTag3</tagclass>
+  </tag>
+</taglib>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld
new file mode 100644
index 0000000..3f2e096
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/lib/taglib-foo.jar/META-INF/foo bar.tld	
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+  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.
+-->
+<!DOCTYPE taglib
+        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+        "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+  <tlibversion>2.0</tlibversion>
+  <jspversion>1.2</jspversion>
+  <shortname>FreeMarker JUnit Test Support 3</shortname>
+  <uri>http://freemarker.sf.net/taglibs/freemarker-junit-test-tag-2.2-foo</uri>
+  <tag>
+    <name>testtag</name>
+    <tagclass>freemarker.ext.jsp.taglibmembers.TestTag3</tagclass>
+  </tag>
+</taglib>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar
deleted file mode 100644
index a915da1..0000000
Binary files a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar and /dev/null differ
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
new file mode 100644
index 0000000..ce5d873
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld	
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+  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.
+-->
+<!DOCTYPE taglib
+        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+        "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+  <tlibversion>2.0</tlibversion>
+  <jspversion>1.2</jspversion>
+  <shortname>FreeMarker JUnit Test Support 2</shortname>
+  <tag>
+    <name>testtag</name>
+    <tagclass>freemarker.ext.jsp.taglibmembers.TestTag2</tagclass>
+  </tag>
+</taglib>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/99d939c9/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld
new file mode 100644
index 0000000..ce5d873
--- /dev/null
+++ b/src/test/resources/freemarker/ext/jsp/webapps/tldDiscovery/WEB-INF/taglib 2.jar/META-INF/taglib.tld	
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!--
+  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.
+-->
+<!DOCTYPE taglib
+        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
+        "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd">
+<taglib>
+  <tlibversion>2.0</tlibversion>
+  <jspversion>1.2</jspversion>
+  <shortname>FreeMarker JUnit Test Support 2</shortname>
+  <tag>
+    <name>testtag</name>
+    <tagclass>freemarker.ext.jsp.taglibmembers.TestTag2</tagclass>
+  </tag>
+</taglib>
\ No newline at end of file


[05/32] incubator-freemarker git commit: Test fix: Avoiding strange rounding difference on Java 8 (Double 10.305 0.## half-up is 10.31 on Java 6, but 10.3 on Java 8.)

Posted by dd...@apache.org.
Test fix: Avoiding strange rounding difference on Java 8 (Double 10.305 0.## half-up is 10.31 on Java 6, but 10.3 on Java 8.)


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

Branch: refs/heads/2.3
Commit: e4510739bae639366126dc3dc46e71b93aff4e19
Parents: 738b16b
Author: ddekany <dd...@apache.org>
Authored: Mon Jan 25 00:57:18 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Jan 25 00:57:18 2016 +0100

----------------------------------------------------------------------
 src/test/java/freemarker/manual/CustomFormatsExample.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/e4510739/src/test/java/freemarker/manual/CustomFormatsExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/CustomFormatsExample.java b/src/test/java/freemarker/manual/CustomFormatsExample.java
index e438b54..2f8778e 100644
--- a/src/test/java/freemarker/manual/CustomFormatsExample.java
+++ b/src/test/java/freemarker/manual/CustomFormatsExample.java
@@ -19,6 +19,7 @@
 package freemarker.manual;
 
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
@@ -53,7 +54,7 @@ public class CustomFormatsExample extends ExamplesTest {
         cfg.setCustomDateFormats(customDateFormats);
 
         addToDataModel("p", 10000);
-        addToDataModel("w", 10.305);
+        addToDataModel("w", new BigDecimal("10.305"));
         addToDataModel("fd", new Date(1450904944213L));
         addToDataModel("let", new Date(1450904944213L));
         


[28/32] incubator-freemarker git commit: RELEASE-NOTES adjustment.

Posted by dd...@apache.org.
RELEASE-NOTES adjustment.


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

Branch: refs/heads/2.3
Commit: aa00a775f1fce304745b1fafb49b62cc18ac2278
Parents: 1d4064d
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 22:02:34 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 22:02:34 2016 +0100

----------------------------------------------------------------------
 RELEASE-NOTES | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/aa00a775/RELEASE-NOTES
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index dcf7a88..b9fc1cf 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -4,5 +4,5 @@ Where to find the change log:
   http://freemarker.org/docs/app_versions.html
 
 - Offline:
-  In the binary release, open documentation/index.html, and you will find the
-  link.
\ No newline at end of file
+  In the binary release, open documentation/index.html, click "Manual", then
+  find "Version history" in table of contents.


[18/32] incubator-freemarker git commit: FREEMARKER-16: Fixed incorrect js_string and json_string documentation.

Posted by dd...@apache.org.
FREEMARKER-16: Fixed incorrect js_string and json_string 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/da3b1a68
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/da3b1a68
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/da3b1a68

Branch: refs/heads/2.3
Commit: da3b1a6811a3db1dff276b840c0147718bc9c4ea
Parents: 6b51f59
Author: ddekany <dd...@apache.org>
Authored: Mon Mar 14 14:52:35 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Mon Mar 14 14:52:35 2016 +0100

----------------------------------------------------------------------
 .../freemarker/template/utility/StringUtil.java |   8 +-
 src/manual/en_US/book.xml                       | 100 +++++++++++++------
 2 files changed, 76 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/da3b1a68/src/main/java/freemarker/template/utility/StringUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/utility/StringUtil.java b/src/main/java/freemarker/template/utility/StringUtil.java
index 58d5ffb..88811f4 100644
--- a/src/main/java/freemarker/template/utility/StringUtil.java
+++ b/src/main/java/freemarker/template/utility/StringUtil.java
@@ -1331,12 +1331,12 @@ public class StringUtil {
      * output. Note that for JSON, the quotation marks must be {@code "}, not {@code '}, because JSON doesn't escape
      * {@code '}.
      * 
-     * <p>The escaping rules guarantee that if the inside
-     * of the literal is from one or more touching sections of strings escaped with this, no character sequence will
-     * occur that closes the string literal or has special meaning in HTML/XML that can terminate the script section.
+     * <p>The escaping rules guarantee that if the inside of the JavaScript/JSON string literal is from one or more
+     * touching pieces that were escaped with this, no character sequence can occur that closes the
+     * JavaScript/JSON string literal, or has a meaning in HTML/XML that causes the HTML script section to be closed.
      * (If, however, the escaped section is preceded by or followed by strings from other sources, this can't be
      * guaranteed in some rare cases. Like <tt>x = "&lt;/${a?js_string}"</tt> might closes the "script"
-     * element if {@code a} is is {@code "script>"}.)
+     * element if {@code a} is {@code "script>"}.)
      * 
      * The escaped characters are:
      * 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/da3b1a68/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index c47f5d9..770418e 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -13328,23 +13328,12 @@ String BEAN_NAME = "${beanName?j_string}";</programlisting>
           quotation marks around the inserted value; you meant to use this
           <emphasis>inside</emphasis> the string literal.</para>
 
-          <para>Both quotation mark (<literal>"</literal>) and
-          apostrophe-quoate (<literal>'</literal>) are escaped. It also
-          escapes <literal>&gt;</literal> as <literal>\&gt;</literal> (to
-          avoid <literal>&lt;/script&gt;</literal>).</para>
-
-          <para>All characters under <link linkend="gloss.UCS">UCS</link> code
-          point 0x20 will be escaped. When they have no dedicated escape
-          sequence in JavaScript (like <literal>\n</literal>,
-          <literal>\t</literal>, etc.), they will be replaced with a UNICODE
-          escape
-          (<literal>\u<replaceable>XXXX</replaceable></literal>).</para>
-
           <warning>
             <para>When inserting into a JavaScript string literal that's
             inside a HTML attribute, you also must escape the value with HTML
-            escaping. Thus, of you don't have automatic HTML escaping, this is
-            WRONG: <literal>&lt;p
+            escaping. Thus, of you don't have <link
+            linkend="pgui_config_outputformatsautoesc">automatic HTML
+            escaping</link>, this is WRONG: <literal>&lt;p
             onclick="alert('${message?js_string}')"&gt;</literal>, and this is
             good: <literal>&lt;p
             onclick="alert('${message?js_string?html}')"&gt;</literal>.</para>
@@ -13362,6 +13351,65 @@ String BEAN_NAME = "${beanName?j_string}";</programlisting>
           <programlisting role="output">&lt;script&gt;
   alert("Welcome Big Joe\'s \"right hand\"!");
 &lt;/script&gt;</programlisting>
+
+          <para>The exact escaping rules are:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>"</literal> is escaped as
+              <literal>\"</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><literal>'</literal> is escaped as
+              <literal>\'</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><literal>\</literal> is escaped as
+              <literal>\\</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><literal>/</literal> is escaped as <literal>\/</literal>
+              if the <literal>/</literal> is directly after
+              <literal>&lt;</literal> in the escaped string, or if it's at the
+              beginning of the escaped string</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>&gt;</literal> is escaped as
+              <literal>\&gt;</literal> if the <literal>&gt;</literal> is
+              directly after <literal>]]</literal> or <literal>--</literal> in
+              the escaped string, or if it's at the beginning of the escaped
+              string, or if there's only a <literal>]</literal> or
+              <literal>-</literal> before it at the beginning of the escaped
+              string</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>&lt;</literal> is escaped as
+              <literal>\u003C</literal> if it's followed by
+              <literal>?</literal> or <literal>!</literal> in the escaped
+              string, or if it's at the end of the escaped string</para>
+            </listitem>
+
+            <listitem>
+              <para>Control characters in <link linkend="gloss.UCS">UCS</link>
+              code point ranges U+0000…U+001f and U+007f…U+009f are escaped as
+              <literal>\r</literal>, <literal>\n</literal>, etc., or as
+              <literal>\x<replaceable>XX</replaceable></literal> where there's
+              no special escape for them in JavaScript.</para>
+            </listitem>
+
+            <listitem>
+              <para>Control characters with <link
+              linkend="gloss.UCS">UCS</link> code point U+2028 (Line
+              separator) and U+2029 (Paragraph separator) are escaped as
+              <literal>\u<replaceable>XXXX</replaceable></literal>, as they
+              are source code line-breaks in ECMAScript.</para>
+            </listitem>
+          </itemizedlist>
         </section>
 
         <section xml:id="ref_builtin_json_string">
@@ -13378,20 +13426,16 @@ String BEAN_NAME = "${beanName?j_string}";</programlisting>
           <emphasis>inside</emphasis> the string literal.</para>
 
           <para>This will not escape <literal>'</literal> characters, since
-          JSON strings must be quoted with <literal>"</literal>. It will,
-          however escape the <literal>/</literal> (slash) characters as
-          <literal>\/</literal> where they occur directly after a
-          <literal>&lt;</literal>, to avoid <literal>&lt;/script&gt;</literal>
-          and such. It will also escape the <literal>&gt;</literal> characters
-          as <literal>\u003E</literal> where they occur directly after
-          <literal>]]</literal>, to avoid exiting an XML
-          <literal>CDATA</literal> section.</para>
-
-          <para>All characters under <link linkend="gloss.UCS">UCS</link> code
-          point 0x20 will be escaped. When they have no dedicated escape
-          sequence in JSON (like <literal>\n</literal>, <literal>\t</literal>,
-          etc.), they will be replaced with a UNICODE escape
-          (<literal>\u<replaceable>XXXX</replaceable></literal>).</para>
+          JSON strings must be quoted with <literal>"</literal>.</para>
+
+          <para>The escaping rules are almost identical to those <link
+          linkend="ref_builtin_j_string">documented for
+          <literal>js_string</literal></link>. The differences are that
+          <literal>'</literal> is not escaped at all, that &gt; is escaped as
+          \u003E (not as \&gt;), and that
+          <literal>\u<replaceable>XXXX</replaceable></literal> escapes are
+          used instead of <literal>\x<replaceable>XX</replaceable></literal>
+          escapes.</para>
         </section>
 
         <section xml:id="ref_builtin_keep_after">


[02/32] incubator-freemarker git commit: Added note about copying ivy.jar to the Ant lib folder.

Posted by dd...@apache.org.
Added note about copying ivy.jar to the Ant lib folder.


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

Branch: refs/heads/2.3
Commit: ec3d4618bd1f69b79366d2b94fbd1362200db3fb
Parents: 0c71d8f
Author: ddekany <dd...@apache.org>
Authored: Fri Jan 22 20:00:10 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Fri Jan 22 20:00:10 2016 +0100

----------------------------------------------------------------------
 README | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ec3d4618/README
----------------------------------------------------------------------
diff --git a/README b/README
index 5f479a4..ee86845 100644
--- a/README
+++ b/README
@@ -114,7 +114,8 @@ First of all, if you haven't yet, download the source release, or check
 out FreeMarker from the source code repository.
 
 You need JDK 8(!), Apache Ant and Ivy to be installed. (As of this writing
-it was tested with Ant 1.8.1 and Ivy 2.3.0.)
+it was tested with Ant 1.8.1 and Ivy 2.3.0.) Note that the ivy-<version>.jar
+should be copied to your Ant home directory "lib" subfolder.
 
 If you need to ensure compliance with certain J2SE versions, copy
 build.properties.sample into build.properties, and edit it


[08/32] incubator-freemarker git commit: Complete the Chinese translation of manual - versions 2.3.22

Posted by dd...@apache.org.
Complete the Chinese translation of manual - versions 2.3.22


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

Branch: refs/heads/2.3
Commit: 8bab1aabb506c81ac2eb7012ae81ebd9296ddb2d
Parents: 6bdb716
Author: nanlei <na...@apache.org>
Authored: Mon Jan 25 10:52:18 2016 +0800
Committer: nanlei <na...@apache.org>
Committed: Mon Jan 25 10:52:18 2016 +0800

----------------------------------------------------------------------
 src/manual/zh_CN/book.xml                       | 31335 +++++++++++++++++
 src/manual/zh_CN/docgen-help/editors-readme.txt |   105 +
 .../zh_CN/docgen-misc/googleAnalytics.html      |     9 +
 .../figures/model2sketch_with_alpha.png         |   Bin 0 -> 61463 bytes
 .../figures/odg-convert-howto.txt               |    24 +
 .../zh_CN/docgen-originals/figures/overview.odg |   Bin 0 -> 11939 bytes
 .../figures/tree_with_alpha.png                 |   Bin 0 -> 10304 bytes
 src/manual/zh_CN/docgen.cjson                   |   118 +
 src/manual/zh_CN/favicon.png                    |   Bin 0 -> 1291 bytes
 src/manual/zh_CN/figures/model2sketch.png       |   Bin 0 -> 21425 bytes
 src/manual/zh_CN/figures/overview.png           |   Bin 0 -> 11837 bytes
 src/manual/zh_CN/figures/tree.png               |   Bin 0 -> 4699 bytes
 src/manual/zh_CN/logo.png                       |   Bin 0 -> 10134 bytes
 13 files changed, 31591 insertions(+)
----------------------------------------------------------------------



[07/32] incubator-freemarker git commit: Complete the Chinese translation of manual - versions 2.3.22

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8bab1aab/src/manual/zh_CN/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/zh_CN/book.xml b/src/manual/zh_CN/book.xml
new file mode 100644
index 0000000..f092b95
--- /dev/null
+++ b/src/manual/zh_CN/book.xml
@@ -0,0 +1,31335 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<book conformance="docgen" version="5.0" xml:lang="en"
+      xmlns="http://docbook.org/ns/docbook"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      xmlns:ns5="http://www.w3.org/1999/xhtml"
+      xmlns:ns4="http://www.w3.org/2000/svg"
+      xmlns:ns3="http://www.w3.org/1998/Math/MathML"
+      xmlns:ns="http://docbook.org/ns/docbook">
+  <info>
+    <title>FreeMarker 手册</title>
+
+    <titleabbrev>Manual</titleabbrev>
+
+    <productname>Freemarker 2.3.23</productname>
+  </info>
+
+  <preface role="index.html" xml:id="preface">
+    <title>什么是 FreeMarker?</title>
+
+    <para>FreeMarker 是一款 <emphasis>模板引擎</emphasis>: 即一种基于模板和要改变的数据,
+	并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。
+	它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。</para>
+
+    <para>模板编写为FreeMarker Template Language (FTL)。它是简单的,专用的语言,
+    <emphasis>不是</emphasis> 像PHP那样成熟的编程语言。
+	那就意味着要准备数据在真实编程语言中来显示,比如数据库查询和业务运算,
+	之后模板显示已经准备好的数据。在模板中,你可以专注于如何展现数据,
+	而在模板之外可以专注于要展示什么数据。</para>
+
+    <mediaobject>
+      <imageobject>
+        <imagedata fileref="figures/overview.png"/>
+      </imageobject>
+    </mediaobject>
+
+    <para>这种方式通常被称为 <link
+    linkend="gloss.MVC">MVC (模型 视图 控制器) 模式</link>,对于动态网页来说,是一种特别流行的模式。
+    它帮助从开发人员(Java 程序员)中分离出网页设计师(HTML设计师)。设计师无需面对模板中的复杂逻辑,
+	在没有程序员来修改或重新编译代码时,也可以修改页面的样式。</para>
+
+    <para>而FreeMarker最初的设计,是被用来在MVC模式的Web开发框架中生成HTML页面的,它没有被绑定到
+	Servlet或HTML或任意Web相关的东西上。它也可以用于非Web应用环境中。</para>
+
+    <para>FreeMarker 是 <link
+    xlink:href="http://www.fsf.org/philosophy/free-sw.html">免费的</link>,
+    基于Apache许可证2.0版本发布。</para>
+
+	<para>如果你发现 <emphasis>任何错误</emphasis> (包括
+    <emphasis>语法错误</emphasis>, <emphasis>错别字</emphasis>,
+    排版错误) 或者是在文档中找到 <emphasis>误导或混淆</emphasis> ,或有其他建议,请联系原作者! 
+	Email: ddekany at users.sourceforge.net</para>
+
+
+    <para>文档翻译的任何问题(包括语法错误,错别字)或中文技术交流,可以联系译者:nanlei1987 at gmail.com,
+    或在FreeMarker的Github上Fork一份,修改之后提交Pull Request。我们共同研究,共同进步。</para>
+
+	<para>英文版文档的作者(也是FreeMarker项目的维护者)是匈牙利人,其母语非英语,那么在这种情况下,
+	翻译过程难免会有错误存在,译者结合自身多年对FreeMarker的实践力争精准,译文力求信达雅。
+	但因个人才疏学浅,水平有限,恳请广大读者批评指正。最好的方式就是使用Github了</para>
+
+	<para>手册的更新根据原作者更新,大家的反馈随时进行。但只在有阶段性成果时才会提交发布修正版本。</para>
+
+	<para>本翻译是免费的,您可以自由下载和传播,但不可用于任何商业行为。文档版权归译者本人所有,
+	原版归FreeMarker项目组所有,您可以引用其中的描述,但必须指明出处。如需用于商业行为,
+	您必须和原作者取得联系。</para>
+  </preface>
+
+  <part xml:id="dgui">
+    <title>模板开发指南</title>
+
+    <chapter xml:id="dgui_quickstart">
+      <title>入门</title>
+
+      <para>本章内容只是对 FreeMarker 进行简略的介绍,在后续章节中将会详细展开讲述。
+      不过没有关系,在阅读了本章节的内容后,就能够编写简单,但却很有用的FreeMarker模板程序了。</para>
+
+      <section xml:id="dgui_quickstart_basics">
+        <title>模板 + 数据模型 = 输出</title>
+
+        <para>假设在一个在线商店的应用系统中需要一个HTML页面,和下面这个页面类似:</para>
+
+        <programlisting role="output">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome <emphasis>John Doe</emphasis>!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="<emphasis>products/greenmouse.html</emphasis>"&gt;<emphasis>green mouse</emphasis>&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+        <para>这里的用户名(上面的"Big Joe"),应该是登录这个网页的访问者的名字,
+		并且最新产品的数据应该来自于数据库,这样它才能随时更新。那么不能直接在HTML页面中输入它们,
+		不能使用静态的HTML代码。此时,可以使用要求输出的 <emphasis role="term">模板</emphasis>。
+		模板和静态HTML是相同的,只是它会包含一些 FreeMarker 将它们变成动态内容的指令:</para>
+
+        <programlisting role="template" xml:id="example.first">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Welcome <emphasis>${user}</emphasis>!&lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="<emphasis>${latestProduct.url}</emphasis>"&gt;<emphasis>${latestProduct.name}</emphasis>&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+        <para>模板文件存放在Web服务器上,就像通常存放静态HTML页面那样。当有人来访问这个页面,
+		FreeMarker将会介入执行,然后动态转换模板,用最新的数据内容替换模板中
+        <literal>${<replaceable>...</replaceable>}</literal> 的部分,
+		之后将结果发送到访问者的Web浏览器中。访问者的Web浏览器就会接收到例如第一个HTML示例那样的内容
+		(也就是没有FreeMarker指令的HTML代码),访问者也不会察觉到服务器端使用的FreeMarker。
+		(当然,存储在Web服务器端的模板文件是不会被修改的;替换也仅仅出现在Web服务器的响应中。)</para>
+
+        <para>请注意,模板并没有包含程序逻辑来查找当前的访问者是谁,或者去查询数据库获取最新的产品。
+		显示的数据是在 FreeMarker 之外准备的,通常是一些 <quote>真正的</quote> 编程语言(比如Java)
+		所编写的代码。模板作者无需知道这些值是如何计算出的。事实上,这些值的计算方式可以完全被修改,
+		而模板可以保持不变,而且页面的样式也可以完全被修改而无需改动模板。
+		当模板作者(设计师)和程序员不是同一人时,显示逻辑和业务逻辑相分离的做法是非常有用的,
+		即便模板作者和程序员是一个人,这么来做也会帮助管理应用程序的复杂性。
+		保证模板专注于显示问题(视觉设计,布局和格式化)是高效使用模板引擎的关键。</para>
+
+        <para><indexterm>
+            <primary>data-model</primary>
+          </indexterm>为模板准备的数据整体被称作为 <emphasis role="term">数据模型</emphasis>。
+		  模板作者要关心的是,数据模型是树形结构(就像硬盘上的文件夹和文件),在视觉效果上,
+		  数据模型可以是:</para>
+
+        <programlisting role="dataModel">(root)
+  |
+  +- <emphasis>user</emphasis> = "Big Joe"
+  |
+  +- <emphasis>latestProduct</emphasis>
+      |
+      +- <emphasis>url</emphasis> = "products/greenmouse.html"
+      |
+      +- <emphasis>name</emphasis> = "green mouse"</programlisting>
+
+        <note>
+          <para>上面只是一个形象化显示;数据模型不是文本格式,它来自于Java对象。
+		  对于Java程序员来说,root就像一个有 <literal>getUser()</literal> 
+		  和 <literal>getLatestProduct()</literal> 方法的Java对象,
+		  也可以有 <literal>"user"</literal> 和 <literal>"latestProducts"</literal> 
+		  键值的Java <literal>Map</literal>对象。相似地,<literal>latestProduct</literal>
+		  就像是有 <literal>getUrl()</literal> 和  <literal>getName()</literal> 方法的Java对象。</para>
+        </note>
+
+        <para>早期版本中,可以从数据模型中选取这些值,使用 <literal>user</literal> 
+		和 <literal>latestProduct.name</literal> 表达式即可。如果我们继续类推,
+		数据模型就像一个文件系统,那么 <quote>(root)</quote> 和 <literal>latestProduct</literal>
+		就对应着目录(文件夹),而 <literal>user</literal>, <literal>url</literal> 和
+        <literal>name</literal> 就是这些目录中的文件。</para>
+
+        <para>总的来说,模板和数据模型是FreeMarker来生成输出(比如第一个展示的HTML)所必须的:</para>
+
+        <para><phrase role="markedTemplate">模板</phrase> + <phrase
+        role="markedDataModel">数据模型</phrase> = <phrase
+        role="markedOutput">输出</phrase></para>
+      </section>
+
+      <section xml:id="dgui_quickstart_datamodel">
+        <title>数据模型一览</title>
+
+        <para>正如已经看到的,数据模型的基本结构是树状的。
+		这棵树可以很复杂,并且可以有很大的深度,比如:</para>
+
+        <programlisting role="dataModel"
+                        xml:id="example.qStart.dataModelWithHashes">(root)
+  |
+  +- animals
+  |   |
+  |   +- mouse
+  |   |   |   
+  |   |   +- size = "small"
+  |   |   |   
+  |   |   +- price = 50
+  |   |
+  |   +- elephant
+  |   |   |   
+  |   |   +- size = "large"
+  |   |   |   
+  |   |   +- price = 5000
+  |   |
+  |   +- python
+  |       |   
+  |       +- size = "medium"
+  |       |   
+  |       +- price = 4999
+  |
+  +- message = "It is a test"
+  |
+  +- misc
+      |
+      +- foo = "Something"</programlisting>
+
+        <para>上图中的变量扮演目录的角色(比如 root,
+        <literal>animals</literal>, <literal>mouse</literal>,
+        <literal>elephant</literal>, <literal>python</literal>,
+        <literal>misc</literal>) 被称为 <emphasis
+        role="term">hashes</emphasis> (哈希表或哈希,译者注)。哈希表存储其他变量(被称为 
+        <anchor xml:id="topic.dataModel.subVar"/><emphasis>子变量</emphasis>),
+		它们可以通过名称来查找(比如 <quote>animals</quote>,
+        <quote>mouse</quote> 或 <quote>price</quote>)。</para>
+
+        <para>存储单值的变量
+        (<literal>size</literal>, <literal>price</literal>,
+        <literal>message</literal> 和 <literal>foo</literal>) 称为
+        <emphasis role="term">scalars</emphasis> (标量,译者注)。</para>
+
+        <para><anchor xml:id="topic.qStart.accessVariables"/>如果要在模板中使用子变量,
+		那应该从根root开始指定它的路径,每级之间用点来分隔开。要访问 <literal>mouse</literal> 的
+        <literal>price</literal> ,要从root开始,首先进入到 <literal>animals</literal> ,之后访问
+        <literal>mouse</literal> ,最后访问 <literal>price</literal> 。就可以这样来写 
+		<literal>animals.mouse.price</literal>。</para>
+
+        <para>另外一种很重要的变量是 <emphasis role="term">sequences</emphasis> (序列,译者注)。
+		它们像哈希表那样存储子变量,但是子变量没有名字,它们只是列表中的项。
+		比如,在下面这个数据模型中, <literal>animals</literal> 和
+        <literal>misc.fruits</literal> 就是序列:</para>
+
+        <programlisting role="dataModel"
+                        xml:id="example.qStart.dataModelWithSequences">(root)
+  |
+  +- animals
+  |   |
+  |   +- (1st)
+  |   |   |
+  |   |   +- name = "mouse"
+  |   |   |
+  |   |   +- size = "small"
+  |   |   |
+  |   |   +- price = 50
+  |   |
+  |   +- (2nd)
+  |   |   |
+  |   |   +- name = "elephant"
+  |   |   |
+  |   |   +- size = "large"
+  |   |   |
+  |   |   +- price = 5000
+  |   |
+  |   +- (3rd)
+  |       |
+  |       +- name = "python"
+  |       |
+  |       +- size = "medium"
+  |       |
+  |       +- price = 4999
+  |
+  +- misc
+      |
+      +- fruits
+          |
+          +- (1st) = "orange"
+          |
+          +- (2nd) = "banana"</programlisting>
+
+        <para>要访问序列的子变量,可以使用方括号形式的数字索引下标。
+		索引下标从0开始(从0开始也是程序员的传统),那么第一项的索引就是0,
+		第二项的索引就是1等等。要得到第一个动物的名称的话,可以这么来写代码 
+		<literal>animals[0].name</literal>。要得到 <literal>misc.fruits</literal> 
+		中的第二项(字符串<literal>"banana"</literal>)可以这么来写 
+		<literal>misc.fruits[1]</literal>。(实践中,通常按顺序遍历序列,而不用关心索引,
+		这点会在 <link linkend="topic.tutorial.list">后续介绍</link>。)</para>
+
+        <para>标量类型可以分为如下的类别:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>字符串:就是文本,也就是任意的字符序列,比如上面提到的
+			''m'', ''o'', ''u'', ''s'', ''e''。比如 <literal>name</literal> 
+			和 <literal>size</literal> 也是字符串。</para>
+          </listitem>
+
+          <listitem>
+            <para>数字:这是数值类型,就像上面的 <literal>price</literal>。
+			在FreeMarker中,字符串 <literal>"50"</literal> 和数字 
+			<literal>50</literal> 是两种完全不同的东西。前者是两个字符的序列
+			(这恰好是人们可以读的一个数字),而后者则是可以在数学运算中直接被使用的数值。</para>
+          </listitem>
+
+          <listitem>
+            <para>日期/时间: 可以是日期-时间格式(存储某一天的日期和时间),
+			或者是日期(只有日期,没有时间),或者是时间(只有时间,没有日期)。</para>
+          </listitem>
+
+          <listitem>
+            <para>布尔值:对应着对/错(是/否,开/关等值)类似的值。
+			比如动物可以有一个 <literal>protected</literal> (受保护的,译者注) 的子变量,
+			该变量存储这个动物是否被保护起来的值。</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>总结:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>数据模型可以被看成是树形结构。</para>
+          </listitem>
+
+          <listitem>
+            <para>标量用于存储单一的值。这种类型的值可以是字符串,数字,日期/时间或者是布尔值。</para>
+          </listitem>
+
+          <listitem>
+            <para>哈希表是一种存储变量及其相关且有唯一标识名称的容器。</para>
+          </listitem>
+
+          <listitem>
+            <para>序列是存储有序变量的容器。存储的变量可以通过数字索引来检索,索引通常从0开始。</para>
+          </listitem>
+        </itemizedlist>
+
+        <note>
+          <para>还有一些其它更为高级的类型,在这里我们并没有涉及到,比如方法和指令。</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_quickstart_template">
+        <title>模板一览</title>
+
+        <para>最简单的模板通常是普通的HTML文件(或者是其他任何文本文件;
+		FreeMarker本身不属于HTML)。当客户端访问某个页面时,
+		FreeMarker要发送HTML代码至客户端浏览器中去显示。如果想要页面动起来
+		(这里指动态网页技术,译者注),那么就要在HTML中放置能被FreeMarker所解析的特殊代码片段:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><literal>${<replaceable>...</replaceable>}</literal>:
+            FreeMarker将会输出真实的值来替换大括号内的表达式,这样的表达式被称为 <emphasis
+            role="term">interpolation</emphasis>(插值,译者注)。</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">FTL 标签</emphasis> (FreeMarker模板的语言标签):
+			FTL标签和HTML标签有一些相似之处,但是它们是FreeMarker的指令,是不会在输出中打印的。
+			这些标签的名字以 <literal>#</literal> 开头。(用户自定义的FTL标签则需要使用
+            <literal>@</literal> 来代替 <literal>#</literal>,但这属于更高级的话题了。)</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">注释:</emphasis> 注释和HTML的注释也很相似,
+			但是它们使用 <literal>&lt;#--</literal> and <literal>--&gt;</literal> 来标识。
+			不像HTML注释那样,FTL注释不会出现在输出中(不出现在访问者的页面中),
+			因为 FreeMarker会跳过它们。</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>其他任何不是FTL标签,插值或注释的内容将被视为静态文本,
+		这些东西不会被FreeMarker所解析;会被按照原样输出出来。</para>
+
+        <para>FTL标签也被称为 <emphasis role="term">指令</emphasis>。
+		这些指令在HTML的标签 (比如: <literal>&lt;table&gt;</literal> 和
+        <literal>&lt;/table&gt;</literal>) 和HTML元素 (比如:
+        <literal>table</literal> 元素) 中的关系是相同的。(如果现在还没有感觉到它们的不同,
+		那么把“FTL标签”和“指令”看做是同义词即可。)</para>
+
+        <note>
+          <para>可以在 <link
+          xlink:href="http://freemarker-online.kenshoo.com/">http://freemarker-online.kenshoo.com/</link>
+		  上很方便的尝试编写模板</para>
+        </note>
+
+        <section>
+          <title>基本指令</title>
+
+          <para>这里我们仅仅来看一些非常常用的指令,当然
+          (<link linkend="ref_directives">指令还有很多</link>)。</para>
+
+          <section>
+            <title>if 指令</title>
+
+            <para>使用 <literal>if</literal> 指令可以有条件地跳过模板的一些片段。
+			比如,假设在 <link linkend="example.first">最初的示例</link> 中,
+			想向你的老板Big Joe特别地问好,可其他人不同:</para>
+
+            <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Welcome!&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;
+    Welcome ${user}<emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>, our beloved leader<emphasis>&lt;/#if&gt;</emphasis>!
+  &lt;/h1&gt;
+  &lt;p&gt;Our latest product:
+  &lt;a href="${latestProduct.url}"&gt;${latestProduct.name}&lt;/a&gt;!
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>此时,告诉 FreeMarker,当和 <literal>"Big Joe"</literal> 相同时
+			<quote>, our beloved leader</quote> (我们最尊敬的领导,译者注) 
+			才是if条件中那唯一的 <literal>user</literal> 变量的值。
+			通常来讲,如果 <literal><replaceable>condition</replaceable></literal> 
+			是false(布尔值),那么介于 <literal>&lt;#if
+            <replaceable>condition</replaceable>&gt;</literal> 和
+            <literal>&lt;/#if&gt;</literal> 标签中的内容会被略过。</para>
+
+            <para>我们来详细说说
+            <literal><replaceable>condition</replaceable></literal> 的使用:
+			<literal>==</literal> 是用来判断它两侧的值是否相等的操作符,
+			比较的结果是布尔值,也就是true或者false。在 <literal>==</literal> 
+			的左侧,是 <link linkend="topic.qStart.accessVariables">被引用的变量</link>,
+			我们很熟悉这样的语法结构;最终它会被变量的值所替代。通常来说,
+			在指令或插值中没有被引号标注的内容都被视为变量的引用。右侧则是指定的字符串,
+			在模板中的字符串 <emphasis>只能</emphasis> 放在引号内。</para>
+
+            <para>当价格为0时,就会打印出 <quote>Pythons are free today!</quote>:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price == <emphasis>0</emphasis>&gt;
+  Pythons are free today!
+&lt;/#if&gt;</programlisting>
+
+            <para>和之前示例中,字符串被直接指定相似,
+			但这里则是数字(<literal>0</literal>)被直接指定了。
+			请注意,这里的数字 <emphasis>没有</emphasis> 放在引号内。
+			如果将(<literal>"0"</literal>)放在引号中,
+			那么FreeMarker就会将其误判为字符串了(也就是字符串0,译者注)。</para>
+
+            <para>当价格不为0时,则会打印出"Pythons are not free today!":</para>
+
+            <programlisting role="template">&lt;#if animals.python.price <emphasis>!=</emphasis> 0&gt;
+  Pythons are not free today!
+&lt;/#if&gt;</programlisting>
+
+            <para>你也许就会猜测了, <literal>!=</literal> 就是<quote>不等于</quote>。</para>
+
+            <para>同时,也可以这样编来写代码(使用 <link
+            linkend="example.qStart.dataModelWithHashes">数据模型来描述哈希表</link>):</para>
+
+            <programlisting role="template">&lt;#if <emphasis>animals.python.price &lt; animals.elephant.price</emphasis>&gt;
+  Pythons are cheaper than elephants today.
+&lt;/#if&gt;</programlisting>
+
+            <para>使用 <literal>&lt;#else&gt;</literal> 
+			标签可以指定当条件为false时程序所要执行的内容。比如:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
+  Pythons are cheaper than elephants today.
+<emphasis>&lt;#else&gt;</emphasis>
+  Pythons are not cheaper than elephants today.
+&lt;/#if&gt;</programlisting>
+
+            <para>这个示例中,如果蟒蛇的价格比大象的价格低的话,
+			程序将会打印出 <quote>Pythons are cheaper than elephants today.</quote>。
+			否则会打印 <quote>Pythons are not cheaper than elephants today.</quote>。
+			后面也可以使用 <literal>elseif</literal> 来完善它:</para>
+
+            <programlisting role="template">&lt;#if animals.python.price &lt; animals.elephant.price&gt;
+  Pythons are cheaper than elephants today.
+<emphasis>&lt;#elseif animals.elephant.price &lt; animals.python.price&gt;</emphasis>
+  Elephants are cheaper than pythons today.
+&lt;#else&gt;
+  Elephants and pythons cost the same today.
+&lt;/#if&gt;</programlisting>
+
+            <para>如果变量本身就是布尔值(true/false),则可以直接让其作为 
+			<literal>if</literal> 的 <literal><replaceable>condition</replaceable></literal>
+			(判断条件,译者注):</para>
+
+            <programlisting role="template">&lt;#if animals.python.protected&gt;
+  Pythons are protected animals!
+&lt;/#if&gt;</programlisting>
+          </section>
+
+          <section>
+            <title>list 指令</title>
+
+            <anchor xml:id="topic.tutorial.list"/>
+
+            <para>当需要列表显示内容时,list指令是必须的。比如:
+			如果合并该模板到 <link
+            linkend="example.qStart.dataModelWithSequences">前面描述序列的数据模型</link> 
+			中:</para>
+
+            <programlisting role="template">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+  <emphasis>&lt;#list animals as animal&gt;</emphasis>
+    &lt;tr&gt;&lt;td&gt;${<emphasis>animal</emphasis>.name}&lt;td&gt;${<emphasis>animal</emphasis>.price} Euros
+  <emphasis>&lt;/#list&gt;</emphasis>
+&lt;/table&gt;</programlisting>
+
+            <para>那么输出结果将会是这样的:</para>
+
+            <programlisting role="output">&lt;p&gt;We have these animals:
+&lt;table border=1&gt;
+    <emphasis>&lt;tr&gt;&lt;td&gt;mouse&lt;td&gt;50 Euros
+    &lt;tr&gt;&lt;td&gt;elephant&lt;td&gt;5000 Euros
+    &lt;tr&gt;&lt;td&gt;python&lt;td&gt;4999 Euros</emphasis>
+&lt;/table&gt;</programlisting>
+
+            <para> <literal>list</literal> 指令的一般格式为:
+            <literal> &lt;#list <replaceable>sequence</replaceable> as
+            <replaceable>loopVariable</replaceable>&gt;<replaceable>repeatThis</replaceable>&lt;/#list&gt;</literal>。
+            <literal><replaceable>repeatThis</replaceable></literal> 部分将会在给定的
+            <literal><replaceable>sequence</replaceable></literal> 遍历时在每一项中重复,
+			从第一项开始,一个接着一个。在所有的重复中,
+            <literal><replaceable>loopVariable</replaceable></literal> 将持有当前遍历项的值。
+			这个变量仅存在于 <literal>&lt;#list
+            <replaceable>...</replaceable>&gt;</literal> 和
+            <literal>&lt;/#list&gt;</literal> 标签内。</para>
+
+            <para><literal><replaceable>sequence</replaceable></literal> 可以是任意表达式,
+			比如我们可以列表显示示例数据模型中的水果,就像这样:</para>
+
+            <programlisting role="template">&lt;ul&gt;
+<emphasis>&lt;#list misc.fruits as fruit&gt;</emphasis>
+  &lt;li&gt;${fruit}
+<emphasis>&lt;/#list&gt;</emphasis>
+&lt;/ul&gt;</programlisting>
+
+            <para>你应该很熟悉表达式 <literal>misc.fruits</literal> 了; 它 <link
+            linkend="topic.qStart.accessVariables">引用了数据模型中的变量</link>。</para>
+
+            <para>上面示例中的一个问题是如果我们有0个水果,它仍然会输出一个空的
+            <literal>&lt;ul&gt;&lt;/ul&gt;</literal>,而不是什么都没有。
+			要避免这样的情况,可以这么来使用 <literal>list</literal>:</para>
+
+            <programlisting role="template">&lt;#list misc.fruits&gt;
+  &lt;ul&gt;
+   <emphasis> &lt;#items as fruit&gt;</emphasis>
+      &lt;li&gt;${fruit}
+ <emphasis>   &lt;/#items&gt;</emphasis>
+  &lt;/ul&gt;
+&lt;/#list&gt;</programlisting>
+
+            <para>此时, <literal>list</literal> 指令将列表视为一个整体,
+			在 <literal>items</literal> 指令中的部分才会为每个水果重复。
+			如果我们有0个水果,那么在 <literal>list</literal> 中的所有东西都被略过了,
+			因此就不会有 <literal>ul</literal> 标签了。</para>
+
+            <para>另一个列表相关的常见任务是:使用一些分隔符来列出水果,比如逗号:</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>
+
+            <programlisting role="output">&lt;p&gt;Fruits: orange, banana</programlisting>
+
+            <para>被 <literal>sep</literal> 覆盖的部分(我们也可以这么来写:
+            <literal><replaceable>...</replaceable>&lt;#sep&gt;,
+            &lt;/#sep&gt;&lt;/#list&gt;</literal>) 只有当还有下一项时才会被执行。
+			因此最后一个水果后面不会有逗号。</para>
+
+            <para>再次回到这个话题,如果我们有0个水果,会怎么样?只是打印 
+            <quote>Fruits:</quote> 也没有什么不方便。
+            <literal>list</literal> 指令,也像 <literal>if</literal> 指令那样,可以有 
+            <literal>else</literal> 部分,如果列表中有0个元素时就会被执行:</para>
+
+            <programlisting role="template">&lt;p&gt;Fruits: &lt;#list misc.fruits as fruit&gt;${fruit}&lt;#sep&gt;, <emphasis>&lt;#else&gt;None</emphasis>&lt;/#list&gt;</programlisting>
+
+            <note>
+              <para>事实上,这个过于简单的示例可以这么来写,
+			  但是它使用了本主题中没有介绍的语言特性:</para>
+
+              <programlisting role="template">&lt;p&gt;Fruits: ${fruits?join(", ", "None")}</programlisting>
+            </note>
+
+            <para>所有的这些指令(<literal>list</literal>,
+            <literal>items</literal>, <literal>sep</literal>,
+            <literal>else</literal>)可以联合起来使用:</para>
+
+            <programlisting role="template">&lt;#list misc.fruits&gt;
+  &lt;p&gt;Fruits:
+  &lt;ul&gt;
+    &lt;#items as fruit&gt;
+      &lt;li&gt;${fruit}&lt;#sep&gt; and&lt;/#sep&gt;
+    &lt;/#items&gt;
+  &lt;/ul&gt;
+&lt;#else&gt;
+  &lt;p&gt;We have no fruits.
+&lt;/#list&gt;</programlisting>
+
+            <note>
+              <para>在 <link linkend="ref_directive_list">指令参考</link> 中,
+			  可以获取到更多关于这些指令的内容。</para>
+            </note>
+          </section>
+
+          <section>
+            <title>include 指令</title>
+
+            <para>使用 <literal>include</literal> 指令,
+			我们可以在模板中插入其他文件的内容。</para>
+
+            <para>假设要在一些页面中显示版权声明的信息。那么可以创建一个文件来单独包含这些版权声明,
+			之后在需要它的地方插入即可。比方说,我们可以将版权信息单独存放在页面文件
+            <literal>copyright_footer.html</literal> 中:</para>
+
+            <programlisting role="template">&lt;hr&gt;
+&lt;i&gt;
+Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
+&lt;br&gt;
+All Rights Reserved.
+&lt;/i&gt;</programlisting>
+
+            <para>当需要用到这个文件时,可以使用 <literal>include</literal> 指令来插入:</para>
+
+            <programlisting role="template">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Test page&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Test page&lt;/h1&gt;
+  &lt;p&gt;Blah blah...
+<emphasis>  &lt;#include "/copyright_footer.html"&gt;</emphasis>
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>此时,输出的内容为:</para>
+
+            <programlisting role="output">&lt;html&gt;
+&lt;head&gt;
+  &lt;title&gt;Test page&lt;/title&gt;
+&lt;/head&gt;
+&lt;body&gt;
+  &lt;h1&gt;Test page&lt;/h1&gt;
+  &lt;p&gt;Blah blah...
+<emphasis>&lt;hr&gt;
+&lt;i&gt;
+Copyright (c) 2000 &lt;a href="http://www.acmee.com"&gt;Acmee Inc&lt;/a&gt;,
+&lt;br&gt;
+All Rights Reserved.
+&lt;/i&gt;</emphasis>
+&lt;/body&gt;
+&lt;/html&gt;</programlisting>
+
+            <para>当修改了 <literal>copyright_footer.html</literal> 文件,
+            那么访问者在所有页面都会看到版权声明的新内容。</para>
+
+            <note>
+              <para>重用代码片段的一个更有力的方式是使用宏,但是只是更为高级的话题了,
+			  将会在 <link linkend="dgui_misc_userdefdir">后续讨论</link>。</para>
+            </note>
+          </section>
+        </section>
+
+        <section>
+          <title>联合使用指令</title>
+
+          <para>在页面上也可以多次使用指令,而且指令间也可以很容易地相互嵌套。
+		  比如,在 <literal>list</literal> 指令中嵌套 <literal>if</literal> 指令:</para>
+
+          <programlisting role="template"><emphasis>&lt;#list animals as animal&gt;</emphasis>
+      &lt;div<emphasis>&lt;#if animal.protected&gt;</emphasis><emphasis> </emphasis>class="protected"<emphasis>&lt;/#if&gt;</emphasis>&gt;
+        ${animal.name} for ${animal.price} Euros
+      &lt;/div&gt;
+<emphasis>&lt;/#list&gt;</emphasis></programlisting>
+
+          <para>请注意,FreeMarker并不解析FTL标签以外的文本、插值和注释,
+		  上面示例在HTML属性中使用FTL标签也不会有问题。</para>
+        </section>
+
+        <section>
+          <title>使用内建函数</title>
+
+          <para>内建函数很像子变量(如果了解Java术语的话,也可以说像方法),
+		  它们并不是数据模型中的东西,是 FreeMarker 在数值上添加的。
+		  为了清晰子变量是哪部分,使用 <literal>?</literal>(问号)代替 
+		  <literal>.</literal>(点)来访问它们。<anchor
+          xml:id="topic.commonlyUsedBuiltIns"/>常用内建函数的示例:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>user?html</literal> 给出 <literal>user</literal> 的HTML转义版本,
+			  比如 <literal>&amp;</literal> 会由 <literal>&amp;amp;</literal> 来代替。</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?upper_case</literal> 给出 <literal>user</literal> 值的大写版本
+			  (比如 <quote>JOHN DOE</quote> 来替代 <quote>John
+			  Doe</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animal.name?cap_first</literal> 给出 <literal>animal.name</literal> 
+			  的首字母大写版本(比如 <quote>Mouse</quote> 来替代 <quote>mouse</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?length</literal> 给出 <literal>user</literal> 值中 
+			  <emphasis>字符</emphasis>的数量(对于 <quote>John Doe</quote> 来说就是8)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animals?size</literal> 给出 <literal>animals</literal> 序列中
+			  <emphasis>项目</emphasis> 的个数(我们示例数据模型中是3个)</para>
+            </listitem>
+
+            <listitem>
+              <para>如果在 <literal>&lt;#list animals as animal&gt;</literal> 和对应的
+              <literal>&lt;/#list&gt;</literal> 标签中:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para><literal>animal?index</literal> 给出了在 <literal>animals</literal> 
+				  中基于0开始的 <literal>animal</literal>的索引值</para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>animal?counter</literal> 也像 <literal>index</literal>,
+				  但是给出的是基于1的索引值</para>
+                </listitem>
+
+                <listitem>
+                  <para><literal>animal?item_parity</literal> 基于当前计数的奇偶性,给出字符串
+                  <quote>odd</quote> 或 <quote>even</quote>。在给不同行着色时非常有用,比如在
+                  <literal>&lt;td class="${animal?item_parity}Row"&gt;</literal>中。</para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+          </itemizedlist>
+
+          <para>一些内建函数需要参数来指定行为,比如:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>animal.protected?string("Y", "N")</literal> 基于 
+			  <literal>animal.protected</literal> 的布尔值来返回字符串
+              <quote>Y</quote> 或 <quote>N</quote>。</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>animal?item_cycle('lightRow','darkRow')</literal> 是之前介绍的 
+			  <literal>item_parity</literal> 更为常用的变体形式。</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>fruits?join(", ")</literal> 通过连接所有项,将列表转换为字符串,
+			  在每个项之间插入参数分隔符(比如 <quote>orange,banana</quote>)</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>user?starts_with("J")</literal> 根据 <literal>user</literal> 
+			  的首字母是否是 <quote>J</quote> 返回布尔值true或false。</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>内建函数应用可以链式操作,比如<literal>user?upper_case?html</literal> 
+		  会先转换用户名到大写形式,之后再进行HTML转义。(这就像可以链式使用
+		  <literal>.</literal>(点)一样)</para>
+
+          <para>可以阅读 <link linkend="ref_builtins">全部内建函数参考</link>。</para>
+        </section>
+
+        <section>
+          <title>处理不存在的变量</title>
+
+          <para>数据模型中经常会有可选的变量(也就是说有时并不存在)。
+		  除了一些典型的人为原因导致失误外,FreeMarker 绝不能容忍引用不存在的变量,
+		  除非明确地告诉它当变量不存在时如何处理。这里来介绍两种典型的处理方法。</para>
+
+          <para><phrase role="forProgrammers">这部分对程序员而言: 
+		  一个不存在的变量和一个是 <literal>null</literal> 值的变量,
+		  对于FreeMarker来说是一样的,所以这里所指的"丢失"包含这两种情况。</phrase></para>
+
+          <para>不论在哪里引用变量,都可以指定一个默认值来避免变量丢失这种情况,
+		  通过在变量名后面跟着一个 <literal>!</literal>(叹号,译者注)和默认值。
+		  就像下面的这个例子,当 <literal>user</literal> 不存在于数据模型时,
+		  模板将会将 <literal>user</literal> 的值表示为字符串 
+		  <literal>"visitor"</literal>。(当 <literal>user</literal> 存在时,
+		  模板就会表现出 <literal>${user}</literal> 的值):</para>
+
+          <programlisting role="template">&lt;h1&gt;Welcome ${user<emphasis>!"visitor"</emphasis>}!&lt;/h1&gt;</programlisting>
+
+          <para>也可以在变量名后面通过放置 <literal>??</literal> 
+		  来询问一个变量是否存在。将它和 <literal>if</literal> 指令合并,
+		  那么如果 <literal>user</literal> 变量不存在的话将会忽略整个问候的代码段:</para>
+
+          <programlisting role="template">&lt;#if <emphasis>user??</emphasis>&gt;&lt;h1&gt;Welcome ${user}!&lt;/h1&gt;&lt;/#if&gt;</programlisting>
+
+          <para>关于多级访问的变量,比如 <literal>animals.python.price</literal>,
+		  书写代码:<literal>animals.python.price!0</literal> 
+		  当且仅当 <literal>animals.python</literal> 永远存在,
+		  而仅仅最后一个子变量 <literal>price</literal> 可能不存在时是正确的
+		  (这种情况下我们假设价格是 <literal>0</literal>)。
+		  如果 <literal>animals</literal> 或 <literal>python</literal> 不存在,
+		  那么模板处理过程将会以"未定义的变量"错误而停止。为了防止这种情况的发生,
+		  可以如下这样来编写代码 <literal>(animals.python.price)!0</literal>。
+		  这种情况就是说 <literal>animals</literal> 或 <literal>python</literal> 不存在时,
+		  表达式的结果是 <literal>0</literal>。对于 <literal>??</literal> 
+		  也是同样用来的处理这种逻辑的; 将 <literal>animals.python.price??</literal> 对比 
+		  <literal>(animals.python.price)??</literal>来看。</para>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_datamodel">
+      <title>数值,类型</title>
+
+      <section xml:id="dgui_datamodel_basics">
+        <title>基本内容</title>
+
+        <note>
+          <para>这里假设你已经阅读完 <xref linkend="dgui_quickstart"/> 章节的内容了。</para>
+        </note>
+
+        <para>理解数值和类型的概念是理解数据模型的关键和基础。
+		但数值和类型的概念并不局限于数据模型,下面你就会看到了。</para>
+
+        <section xml:id="topic.value">
+          <title>什么是数值?</title>
+
+          <indexterm>
+            <primary>value</primary>
+          </indexterm>
+
+          <para><phrase role="forProgrammers">这部分对于程序员来说可以直接跳过的。</phrase></para>
+
+          <para>正如你知道的,来自于每天所使用的数字,比如16,0.5等这些用语就是 
+		  <emphasis>数值</emphasis> 的示例,也就是数字。在计算机语言中,
+		  这些用语有着更广泛的含义,比如数值并不一定是数字类型值,比如面这个数据模型:</para>
+
+          <programlisting role="dataModel" xml:id="example.stdDataModel">(root)
+ |
+ +- user = "Big Joe"
+ |
+ +- today = Jul 6, 2007
+ |
+ +- todayHoliday = false
+ |
+ +- lotteryNumbers
+ |   |
+ |   +- (1st) = 20
+ |   |
+ |   +- (2st) = 14
+ |   |
+ |   +- (3rd) = 42
+ |   |
+ |   +- (4th) = 8
+ |   |
+ |   +- (5th) = 15
+ |
+ +- cargo
+     |
+     +- name = "coal"
+     |
+     +- weight = 40
+</programlisting>
+
+          <para>变量 <literal>user</literal> 的 <emphasis>value</emphasis> 
+		  是"Big Joe"(字符串), <literal>today</literal> 的 <emphasis>value</emphasis> 
+		  是 Jul 6, 2007 (日期),<literal>todayHoliday</literal> 的 
+		  <emphasis>value</emphasis> 是false(布尔值,比如yes/no等值)。
+          <literal>lotteryNumbers</literal> 的 <emphasis>value</emphasis> 
+		  是包含20,14, 42, 8, 15的序列。当然在这种意义上,
+		  <literal>lotteryNumbers</literal> 是多值类型。它 <emphasis>包含</emphasis> 
+		  多个值(比如,其中的第二项的 <emphasis>value</emphasis> 是14),但是 
+		  <literal>lotteryNumbers</literal> 本身还是单值。它就像一个装有其它很多东西的盒子
+		  (或称之为容器,译者注),但盒子作为整体还是视作单独的。最后还有一个数值 
+		  <literal>cargo</literal>,它的 <emphasis>value</emphasis> 是一个哈希表
+		  (也是类似盒子一样的东西)。所以说,数值就是存储在变量中的(比如,在 
+		  <literal>user</literal> 或 <literal>cargo</literal> 或 
+		  <literal>cargo.name</literal> 中)的那个东西。但是,
+		  不需要存储于变量之中的数值也可以称之为数值,比如下面的数字100:</para>
+
+          <programlisting role="template">&lt;#if cargo.weight &lt; <emphasis>100</emphasis>&gt;Light cargo&lt;/#if&gt;</programlisting>
+
+          <para>当模板被执行时,计算出的临时结果也称为数值,比如这里的20和120(它会打印120):</para>
+
+          <programlisting role="template">${cargo.weight / 2 + 100}</programlisting>
+
+          <para>这里针对最后一种表示进行解释:有两个数,40(货物的重量)和2,
+		  相除的结果是20,这是一个新计算出来的数值。然后,把它和100相加,
+		  那么120就计算出来了,接着就打印出来。
+		  (<literal>${<replaceable>...</replaceable>}</literal>),之后模板继续向下执行,
+		  直到所有结果都计算出来。</para>
+
+          <para>现在你应该能体会到数值这个词的含义了。</para>
+        </section>
+
+        <section>
+          <title>什么是类型?</title>
+
+          <para>数值中非常重要的一个概念就是类型。比方说,变量 
+		  <literal>user</literal> 的类型是字符串,变量 <literal>lotteryNumbers</literal> 
+		  的类型是序列。数值的类型这个概念非常的重要,因为它决定了这些数值可以在哪里使用的最大限度。
+		  比如说,使用 <literal>${user / 2}</literal> 就是错误的,但是使用 
+		  <literal>${cargo.weight / 2}</literal> 就能计算出结果,为20,
+		  因为算术中的除法仅对数字类型的值有效,而不能用于字符串。
+		  仅当 <literal>cargo</literal> 是一个哈希表变量时,表达式 <literal>cargo.name</literal> 
+		  才可以使用点。也可以用 <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal> 
+		  指令来遍历序列。而 <literal>&lt;#if ...&gt;</literal> 指令的条件只能是布尔值等。</para>
+
+          <note>
+            <para>这里说一点点的术语:称 "布尔" 或 "布尔值" 或 "布尔类型" 都是相同的含义。</para>
+          </note>
+
+          <para xml:id="topic.multitype"><indexterm>
+              <primary>Multi-typed value</primary>
+            </indexterm>数值同时也可以含有多种类型,尽管很少这么使用。看一下下面这个数据模型
+          <literal>mouse</literal> 它本身就又是字符串,又是哈希表:</para>
+
+          <programlisting role="dataModel">(root)
+ |
+ +- mouse = "Yerri"
+     |
+     +- age = 12
+     |
+     +- color = "brown"</programlisting>
+
+          <para>如果用上面的数据模型合并到下面的模板中:</para>
+
+          <programlisting role="template">${mouse}       &lt;#-- uses mouse as a string --&gt;
+${mouse.age}   &lt;#-- uses mouse as a hash --&gt;
+${mouse.color} &lt;#-- uses mouse as a hash --&gt;</programlisting>
+
+          <para>将会输出:</para>
+
+          <programlisting role="output">Yerri
+12
+brown</programlisting>
+        </section>
+
+        <section>
+          <title>数据模型是哈希表</title>
+
+          <para>注意观察每个数据模型的例子你也许能发现:被"(root)"所标识的内容就是哈希表类型的值。
+		  当编写如 <literal>user</literal> 这样的代码时,那就意味着要把"user"变量存储在哈希表的根上。
+		  就像编写 <literal>root.user</literal>一样,这里但并没有名"root"为的变量,
+		  那么这就起不到任何作用了。</para>
+
+          <para>某些人也许会被这种数据模型的例子所困惑,也就是说,根哈希表包含更多的哈希表或序列
+          (<literal>lotteryNumbers</literal> and <literal>cargo</literal>)。其它就没有更特殊的内容了。
+		  哈希表包含其他变量,那些变量包含其它值,这些数值可以是字符串,数字等变量,
+		  当然也可以是哈希表或序列变量。最初我们解释过的,就像字符串和数字,
+		  序列或哈希表也是一种值的表示形式。</para>
+        </section>
+      </section>
+
+      <section xml:id="dgui_datamodel_types">
+        <title>类型</title>
+
+        <para>支持的类型有:</para>
+
+        <itemizedlist spacing="compact">
+          <listitem>
+            <para><link linkend="dgui_datamodel_scalar"
+            os="">标量:</link></para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para>字符串</para>
+              </listitem>
+
+              <listitem>
+                <para>数字</para>
+              </listitem>
+
+              <listitem>
+                <para>布尔值</para>
+              </listitem>
+
+              <listitem>
+                <para>日期/时间 (日期,时间或日期时间)</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para><link
+            linkend="dgui_datamodel_container">容器:</link></para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para>哈希表</para>
+              </listitem>
+
+              <listitem>
+                <para>序列</para>
+              </listitem>
+
+              <listitem>
+                <para>集合</para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>子程序:</para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para><link linkend="dgui_datamodel_method">方法和函数</link></para>
+              </listitem>
+
+              <listitem>
+                <para><link linkend="dgui_datamodel_userdefdir">用户自定义指令</link></para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+
+          <listitem>
+            <para>其它/很少使用:</para>
+
+            <itemizedlist spacing="compact">
+              <listitem>
+                <para><link linkend="dgui_datamodel_node">结点</link></para>
+              </listitem>
+            </itemizedlist>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="dgui_datamodel_scalar">
+          <title>标量</title>
+
+          <anchor xml:id="topic.designer.scalarVariable"/>
+
+          <para>标量是最基本,最简单的数值类型,它们可以是:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><indexterm>
+                  <primary>string</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>字符串:表示简单的文本,例如:产品的名称。</para>
+
+              <para>如果想在模板中直接给出字符串值,而不是使用数据模型中的变量,
+			  那么将文本内容写在引号内即可,比如 <literal>"green mouse"</literal> 
+			  或 <literal>'green mouse'</literal>。(关于语法的更多细节可以在 
+			  <link linkend="dgui_template_exp_direct_string" xml:lang="">后续章节</link>中找到。)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>number</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>数值:比如说,产品的价格。
+              <phrase role="forProgrammers">整数和非整数是不区分的;只有单一的数字类型。比如使用了计算器,
+			  计算3/2的结果是1.5而不是1。</phrase></para>
+
+              <para>如果要在模板中直接给出数字的值,那么可以这么来写:
+			  <literal>150</literal> 或 <literal>-90.05</literal> 
+			  或 <literal>0.001</literal>。(关于语法的更多细节可以在 <link
+              linkend="dgui_template_exp_direct_number" xml:lang="">后续章节</link>中找到。)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>boolean</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>布尔值:布尔值代表了逻辑上的对或错(是或否)。比如:用户是否登录了。
+				典型的应用是使用布尔值作为  <literal>if</literal> 指令的条件,
+				比如 <literal>&lt;#if loggedIn &gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal> 或者
+              <literal>&lt;#if price == 0&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>;
+			  后面这个 <literal>price == 0</literal> 部分的结果就是布尔值。</para>
+
+              <para>在模板中可以使用保留字 <literal>true</literal> 
+			  和 <literal>false</literal> 来指定布尔值。</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>date</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm><indexterm>
+                  <primary>time</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm><indexterm>
+                  <primary>date-time</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>日期:日期变量可以存储和日期/时间相关的数据。
+				一共有三种变化:</para>
+
+              <itemizedlist>
+                <listitem>
+                  <para>日期:精确到天的日期,没有时间部分。比如April 4, 2003。</para>
+                </listitem>
+
+                <listitem>
+                  <para>时间:精确到毫秒,没有日期部分。比如10:19:18 PM。</para>
+                </listitem>
+
+                <listitem>
+                  <para>日期-时间(有时也被称为"时间戳"),比如April 4,2003 10:19:18 PM。
+				  有日期和时间两部分,时间部分的存储精确到毫秒。</para>
+                </listitem>
+              </itemizedlist>
+
+              <para>不幸的是,受到Java平台的限制,FreeMarker 有时是不能决定日期的部哪分被使用
+			  (也就是说,是日期-时间格式,日期格式还是时间格式)。
+			  这个问题的解决方法是一个的高级话题,将会在 
+			  <link linkend="ref_builtin_date_datetype">后续章节</link>讨论。</para>
+
+              <para>模板中直接定义日期数值是可以的,但这也是高级话题,将会在
+              <link linkend="ref_builtin_string_date">后续章节</link> 中进行解释。</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>要记住,FreeMarker区别字符串,数字,布尔值和日期类型的值。比如,
+          字符串 <literal>"150"</literal> 看起来很像数字 <literal>150</literal>,
+		  字符串只是字符的任意序列,不能将它用于计算目的,也不能和其它数字进行比较等等。</para>
+        </section>
+
+        <section xml:id="dgui_datamodel_container">
+          <title>容器</title>
+
+          <remark>站在一个比之前更''专业''的视角上来重新解释哈希表和序列,
+		  还有一些深入的思考。</remark>
+
+          <para>这些值存在的目的是为了包含其他变量;它们只是容器。
+		  它们包含的变量通常视为  <emphasis>subvariables</emphasis>
+		  (子变量,译者注)。容器的类型有:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><indexterm>
+                  <primary>hash</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>哈希表:每个子变量都可以通过一个唯一的名称来查找。
+				这个名称是不受限制的字符串。哈希表 <emphasis>并不确定其中子变量的顺序</emphasis>。
+				也就是说没有第一个子变量,第二个子变量这样的说法等;变量仅仅是通过名称来访问的。
+				(就像Java语言中的HashMap一样,是实现了Hash算法的Map,不记录内部元素的顺序,
+				仅仅通过名称来访问。译者注)</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>sequence</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>序列:每个子变量通过一个整数来标识。第一个子变量的标识符是0,
+				第二个是1,第三个是2,这样来类推,而且子变量是有顺序的。这些数次通常被称为 
+				<emphasis>indexes</emphasis>(索引,译者注)。序列通常比较密集,也就是所有的索引,
+				包括最后一个子变量的,它们和子变量都是相关联的,但不是绝对必要的。
+				子变量的类型也并不需要完全一致。</para>
+            </listitem>
+
+            <listitem>
+              <para><indexterm>
+                  <primary>collection</primary>
+
+                  <secondary>FTL 值类型</secondary>
+                </indexterm>集合:从模板设计者角度来看,集合是有限制的序列。不能获取集合的大小,
+				也不能通过索引取出集合中的子变量,但是它们仍然可以通过 
+				<link linkend="ref.directive.list"><literal>list</literal> 指令</link>来遍历。</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>请注意,一个值也可有多种类型 
+		  <link linkend="topic.multitype">一个值也可有多种类型</link>,
+		  对于一个值可能同时存在哈希表和序列这两种类型,这时,
+		  该变量就支持索引和名称两种访问方式。
+		  不过容器基本是当作哈希表或者序列来使用的,而不是两者同时使用。</para>
+
+          <para>尽管存储在哈希表,序列(集合)中的变量可以是任意类型的,
+		  这些变量也可以是哈希表,序列(或集合)。这样就可以构建任意深度的数据结构。</para>
+
+          <para>数据模型本身(最好说成是它的根root)也是哈希表。</para>
+        </section>
+
+        <section>
+          <title>子程序</title>
+
+          <section xml:id="dgui_datamodel_method">
+            <title>方法和函数</title>
+
+            <anchor xml:id="topic.designer.methodVariable"/>
+
+            <indexterm>
+              <primary>method</primary>
+
+              <secondary>FTL 值类型</secondary>
+            </indexterm>
+
+            <para>当一个值是方法或函数的时候,那么它就可以计算其他值,结果取决于传递给它的参数。</para>
+
+            <para><phrase role="forProgrammers">这部分是对程序员来说的:方法/函数是一等类型值,
+			就像函数化的编程语言。也就是说函数/方法也可以是其他函数/方法的参数或者返回值,
+			并可以把它们定义成变量等。</phrase></para>
+
+            <para>假设程序员在数据模型中放置了一个方法变量 <literal>avg</literal>,
+			该变量用来计算数字的平均值。如果给定3和5作为参数,访问 
+			<literal>avg</literal> 时就能得到结果4。</para>
+
+            <para>方法的使用将会在 <link 
+			linkend="dgui_template_exp_methodcall">后续章节</link> 中进行解释,
+			下面这个示例会帮助我们理解方法的使用:</para>
+
+            <programlisting role="template">The average of 3 and 5 is: ${avg(3, 5)}
+The average of 6 and 10 and 20 is: ${avg(6, 10, 20)}
+The average of the price of a python and an elephant is:
+${avg(animals.python.price, animals.elephant.price)}</programlisting>
+
+            <para>将会输出:</para>
+
+            <programlisting role="output">The average of 3 and 5 is: 4
+The average of 6 and 10 and 20 is: 12
+The average of the price of a python and an elephant is:
+4999.5</programlisting>
+
+            <para>那么方法和函数有什么区别呢?这是模板作者所关心的,
+			它们没有关系,但也不是一点关系都没有。
+			方法是来自于数据模型 (<phrase 
+			role="forProgrammers">它们反射了Java对象的方法</phrase>)
+			而函数是定义在模板内的 (使用 <link 
+			linkend="ref.directive.function"><literal>function</literal> 
+			指令</link> -- 也是高级话题),但二者可以用同一种方式来使用。</para>
+          </section>
+
+          <section xml:id="dgui_datamodel_userdefdir">
+            <title>用户自定义指令</title>
+
+            <indexterm>
+              <primary>macro</primary>
+
+              <secondary>FTL 值类型</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>directive</primary>
+
+              <secondary>FTL 值类型</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>user-defined directive</primary>
+
+              <secondary>FTL 值类型</secondary>
+            </indexterm>
+
+            <para>这种类型的值可以作为用户自定义指令(换句话说,就是FreeMarker的标签)
+			用户自定义指令是一种子程序,一种可以复用的模板代码段。但这也是一个高级话题,
+			将会在 <link linkend="dgui_misc_userdefdir">后续章节</link> 中进行解释。</para>
+
+            <para><phrase role="forProgrammers">这部分是对程序员来说的:
+			用户自定义指令(比如宏)也是一等值类型,就像函数/方法一样。</phrase></para>
+
+            <para>这里仅仅对用户自定义指令有一个认识即可(如果现在还不能理解可以先忽略它)。
+			假设现在有一个变量 <literal>box</literal>,它的值是用户自定义的指令,
+			用来打印一些特定的HTML信息,包含标题和一条信息。那么,
+			<literal>box</literal> 变量就可以在模板中使用(示例如下):</para>
+
+            <programlisting role="template">&lt;@<emphasis>box</emphasis> title="Attention!"&gt;
+  Too much copy-pasting may leads to
+  maintenance headaches.
+&lt;/@<emphasis>box</emphasis>&gt;</programlisting>
+          </section>
+
+          <section>
+            <title>函数/方法和用户自定义指令的比较</title>
+
+            <para>这部分内容也是对高级用户来说的(如果还不能理解可以先忽略它)。
+			如果要使用函数/方法或自定义指令去实现一些东西的时候,
+			二者之间的选择是两难的。按经验来说,如果能够实现需求,
+			请先用自定义指令而不要用函数/方法。如果:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>... 输出(返回值)的是标记(HTML,XML等)。
+				主要原因是函数的返回结果可以自动进行XML转义(这是因为
+                <literal>${<replaceable>...</replaceable>}</literal> 的特性),
+				而用户自定义指令的输出则不是
+				(这是因为 <literal>&lt;@<replaceable>...</replaceable>&gt;</literal> 的特性所致;
+				它的输出假定是标记,因此已经转义过了)。</para>
+              </listitem>
+
+              <listitem>
+                <para>... 副作用也是很重要的一点,它没有返回值。
+				例如一个指令的目的是往服务器日志中添加一条。
+				(事实上不能得到自定义指令的返回值,
+				但有些反馈的类型是有可能设置非本地变量的。)</para>
+              </listitem>
+
+              <listitem>
+                <para>... 会进行流程的控制(就像 <literal>list</literal> 
+				或 <literal>if</literal> 指令那样)。但是不能在函数/方法上这么做。</para>
+              </listitem>
+            </itemizedlist>
+
+            <para>在模板中,FreeMarker不知道的Java对象的方法通常是可以作为方法来使用的,
+			而不用考虑Java对象方法本身的特性,因为在这里没有其他的选择。</para>
+          </section>
+        </section>
+
+        <section>
+          <title>其它</title>
+
+          <section xml:id="dgui_datamodel_node">
+            <title>结点</title>
+
+            <indexterm>
+              <primary>node</primary>
+
+              <secondary>FTL 值类型</secondary>
+            </indexterm>
+
+            <para>结点变量代表了树状结构中的一个结点,而且通常是配合 
+			<link linkend="xgui">XML 处理</link>的,这是专业而且更高级的话题。</para>
+
+            <para>这里我们仅对 <emphasis>高级用户</emphasis> 进行一个概要说明:
+			结点和存储在其他结点中的序列很相似,通常也被当作为子结点。结点存储它所在的容器结点的引用,
+			也就是父结点。结点的主要作用是拓扑信息;其它数据必须通过使用多类型的值来存储。
+			就像一个值可以同时是一个结点和一个数字,这样它存储的数字可以作为如支付额来使用。
+			除了拓扑信息,结点也可以存储一些元信息(即metadata,译者注):如结点名称,它的类型(字符串), 
+			命名空间(字符串)。若一个结点象征XHTML文档中的 <literal>h1</literal> 元素,
+			那么它的名字可以是 <literal>"h1"</literal>,类型可以是 <literal>"element"</literal>,
+			命名空间可以是 <literal>"http://www.w3.org/1999/xhtml"</literal>。但对于数据模型设计者来说,
+			这些元信息,还有如何来使用它们又有什么意义呢。检索拓扑信息和元信息的方法将会在 
+			<link linkend="ref_builtins_node">后续章节</link> 中来说明(这里可以先不用理解它们)。</para>
+          </section>
+        </section>
+      </section>
+    </chapter>
+
+    <chapter xml:id="dgui_template">
+      <title>模板</title>
+
+      <indexterm>
+        <primary>template</primary>
+      </indexterm>
+
+      <note>
+        <para>这里假设你已经阅读完 <xref linkend="dgui_quickstart"/> 
+		和 <xref linkend="dgui_datamodel"/> 章节了。</para>
+      </note>
+
+      <section xml:id="dgui_template_overallstructure">
+        <title>总体结构</title>
+
+        <para>实际上用程序语言编写的程序就是模板。
+        <indexterm>
+            <primary>FTL</primary>
+          </indexterm><emphasis role="term">FTL</emphasis> (代表FreeMarker模板语言)。
+		  这是为编写模板设计的非常简单的编程语言。</para>
+
+        <para>模板(FTL编程)是由如下部分混合而成的:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para><emphasis role="term">文本</emphasis><indexterm>
+                <primary>text</primary>
+              </indexterm>:文本会照着原样来输出。</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">插值</emphasis><indexterm>
+                <primary>interpolation</primary>
+              </indexterm>:这部分的输出会被计算的值来替换。插值由 
+            <literal>${</literal> and <literal>}</literal> 所分隔(或者
+            <literal>#{</literal> and <literal>}</literal>,这种风格已经不建议再使用了;<link
+            linkend="ref_depr_numerical_interpolation">点击查看更多</link>)。</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">FTL 标签</emphasis><indexterm>
+                <primary>FTL tag</primary>
+              </indexterm>:FTL标签和HTML标签很相似,但是它们却是给FreeMarker的指示,
+			  而且不会打印在输出内容中。</para>
+          </listitem>
+
+          <listitem>
+            <para><emphasis role="term">注释</emphasis><indexterm>
+                <primary>comment</primary>
+              </indexterm><indexterm>
+                <primary>&lt;#--...--&gt;</primary>
+              </indexterm><indexterm>
+                <primary>#</primary>
+              </indexterm>:注释和HTML的注释也很相似,但它们是由 
+			  <literal>&lt;#--</literal> 和
+            <literal>--&gt;</literal>来分隔的。注释会被FreeMarker直接忽略,
+			更不会在输出内容中显示。</para>
+          </listitem>
+        </itemizedlist>
+
+        <para>我们来看一个具体的模板。其中的内容已经用颜色来标记了: 
+		<phrase role="markedText">文本</phrase>,
+        <phrase role="markedInterpolation">插值</phrase>, <phrase
+        role="markedFTLTag">FTL 标签</phrase>, <phrase
+        role="markedComment">注释</phrase>。为了看到可见的 
+		<link linkend="gloss.lineBreak">换行符</link>,
+		这里使用了 <phrase role="markedInvisibleText">[BR]</phrase>。</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;html&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;title&gt;Welcome!&lt;/title&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/head&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedComment">&lt;#-- Greet the user with his/her name --&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;h1&gt;Welcome <phrase role="markedInterpolation">${user}</phrase>!&lt;/h1&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+  &lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;#list animals as animal&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+    &lt;li&gt;<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+              role="markedInvisibleText">[BR]</phrase>
+  <phrase role="markedFTLTag">&lt;/#list&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase>
+  &lt;/ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/body&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;/html&gt;</phrase></programlisting>
+
+        <para>FTL是区分大小写的。 <literal>list</literal> 是指令的名称而 
+		<literal>List</literal> 就不是。类似地 <literal>${name}</literal> 
+		和 <literal>${Name}</literal> 或 <literal>${NAME}</literal> 也是不同的。</para>
+
+        <para>请注意非常重要的一点: <phrase role="markedInterpolation">插值</phrase> 
+		仅仅可以在 <phrase role="markedText">文本</phrase> 中使用。
+		(也可以是字符串表达式;请参考 
+		<link linkend="dgui_template_exp_stringop_interpolation">后续内容</link>)</para>
+
+        <para><phrase role="markedFTLTag">FTL 标签</phrase> 不可以在其他
+		<phrase role="markedFTLTag">FTL 标签</phrase> 
+		和 <phrase role="markedInterpolation">插值</phrase>中使用。比如,
+		这样做是 <emphasis>错误</emphasis> 的: 
+		<literal>&lt;#if &lt;#include 'foo'&gt;='bar'&gt;...&lt;/#if&gt;</literal></para>
+
+        <para><phrase role="markedComment">注释</phrase> 可以放在
+		<phrase role="markedFTLTag">FTL 标签</phrase> 
+		和 <phrase role="markedInterpolation">插值</phrase>中。比如:</para>
+
+        <programlisting role="template"><phrase role="markedText">&lt;h1&gt;Welcome <phrase
+              role="markedInterpolation">${user <phrase role="markedComment">&lt;#-- The name of user --&gt;</phrase>}</phrase>!&lt;/h1&gt;<phrase
+              role="markedInvisibleText">[BR]</phrase>
+&lt;p&gt;We have these animals:<phrase role="markedInvisibleText">[BR]</phrase>
+&lt;ul&gt;<phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;#list <phrase role="markedComment">&lt;#-- some comment... --&gt;</phrase> animals as <phrase
+                role="markedComment">&lt;#-- again... --&gt;</phrase> animal&gt;</phrase><phrase
+              role="markedInvisibleText">[BR]</phrase></phrase>
+<replaceable>...</replaceable></programlisting>
+
+        <note>
+          <para>如果您已经自行尝试测试上面所有示例的话:那么也许会注意到,一些空格、
+		  制表符和换行符从模板的输出中都不见了,尽管我们之前已经说了 
+		  <phrase role="markedText">文本</phrase> 是按照原样输出的。
+		  现在不用为此而计较,这是由于FreeMarker的"空格剥离"特性在起作用,
+		  它当然会自动去除一些多余的空格,制表符和换行符了。
+		  这个特性在 <link linkend="dgui_misc_whitespace">后续内容</link> 中会解释到。</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_template_directives">
+        <title>指令</title>
+
+        <indexterm>
+          <primary>&lt;#...&gt;</primary>
+        </indexterm>
+
+        <indexterm>
+          <primary>#</primary>
+        </indexterm>
+
+        <anchor xml:id="term.designer.directive"/>
+
+        <remark>请注意,表达式章节是基于本章之上的,而插值章节是基于表达式章节的。
+		因此,指令指令章节就是基本内容后的第一部分内容。</remark>
+
+        <para><indexterm>
+            <primary>directive</primary>
+          </indexterm>使用 FTL标签来调用 <emphasis role="term">指令</emphasis>。
+		  在示例中已经调用了 <literal>list</literal> 指令。在语法上我们使用了两个标签:
+		  <literal>&lt;#list animals as animal&gt;</literal> 
+		  和 <literal>&lt;/#list&gt;</literal>。</para>
+
+        <para><indexterm>
+            <primary>FTL tag</primary>
+          </indexterm>FTL 标签分为两种:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>开始标签:
+            <literal>&lt;#<replaceable>directivename</replaceable>
+            <replaceable>parameters</replaceable>&gt;</literal></para>
+          </listitem>
+
+          <listitem>
+            <para>结束标签:
+            <literal>&lt;/#<replaceable>directivename</replaceable>&gt;</literal></para>
+          </listitem>
+        </itemizedlist>
+
+        <para>除了标签以 <literal>#</literal> 开头外,其他都和HTML,XML的语法很相似。
+		如果标签没有嵌套内容(在开始标签和结束标签之间的内容),那么可以只使用开始标签。
+		例如 <literal>&lt;#if
+        <replaceable>something</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>,
+        而FreeMarker知道 <literal>&lt;#include <replaceable>something</replaceable>&gt;</literal> 中的
+		<literal>include</literal> 指令没有可嵌套的内容。</para>
+
+        <para><literal><replaceable>parameters</replaceable></literal> 的格式由
+        <literal><replaceable>directivename</replaceable></literal>来决定。</para>
+
+        <para>事实上,指令有两种类型: <link 
+		linkend="gloss.predefinedDirective">预定义指令</link> 
+		和 <link linkend="gloss.userDefinedDirective">用户自定义指令</link>。
+		对于用户自定义的指令使用 <literal>@</literal> 来代替 
+		<literal>#</literal>,比如,<literal>&lt;@mydirective 
+		<replaceable>parameters</replaceable>&gt;<replaceable>...</replaceable>&lt;/@mydirective&gt;</literal>。
+		更深的区别在于如果指令没有嵌套内容,那么必须这么使用 <literal>&lt;@mydirective
+        <replaceable>parameters</replaceable> /&gt;</literal>,这和XML语法很相似
+		(例如 <literal>&lt;img <replaceable>...</replaceable> /&gt;</literal>)。
+		但用户自定义指令是更高级的话题,将会在 <link
+        linkend="dgui_misc_userdefdir">后续章节</link> 中继续讨论。</para>
+
+        <para>像HTML标签一样,FTL标签也必须正确地嵌套使用。下面这段示例代码就是错的,
+		因为 <literal>if</literal> 指令在 <literal>list</literal> 指令嵌套内容的内外都有:</para>
+
+        <programlisting role="template">&lt;ul&gt;
+<emphasis>&lt;#list animals as animal&gt;</emphasis>
+  &lt;li&gt;${animal.name} for ${animal.price} Euros
+  <emphasis>&lt;#if user == "Big Joe"&gt;</emphasis>
+     (except for you)
+<emphasis>&lt;/#list&gt;</emphasis> &lt;#-- WRONG! The "if" has to be closed first. --&gt;
+<emphasis>&lt;/#if&gt;</emphasis>
+&lt;/ul&gt;</programlisting>
+
+        <para>请注意,FreeMarker 仅仅关心FTL标签的嵌套而不关心HTML标签的嵌套。
+		它只会把HTML看做是文本,不会来解释HTML。</para>
+
+        <para>如果你尝试使用一个不存在的指令(比如,输错了指令的名称),
+		FreeMarker 就会拒绝执行模板,同时抛出错误信息。</para>
+
+        <para>FreeMarker会忽略FTL标签中多余的 <link 
+		linkend="gloss.whiteSpace">空白标记</link>,所以也可以这么来写代码:</para>
+
+        <programlisting role="template"><phrase role="markedText"><phrase
+              role="markedFTLTag">&lt;#list<phrase role="markedInvisibleText">[BR]</phrase>
+  animals       as<phrase role="markedInvisibleText">[BR]</phrase>
+     animal<phrase role="markedInvisibleText">[BR]</phrase>
+&gt;</phrase><phrase role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedInterpolation">${animal.name}</phrase> for <phrase
+              role="markedInterpolation">${animal.price}</phrase> Euros<phrase
+              role="markedInvisibleText">[BR]</phrase>
+<phrase role="markedFTLTag">&lt;/#list    &gt;</phrase></phrase></programlisting>
+
+        <para>当然,也不能在 <literal>&lt;</literal>,<literal>&lt;/</literal> 
+		和指令名中间入空白标记。</para>
+
+        <para>所有指令的详细介绍可以在 <xref linkend="ref_directives"/> 
+		中找到(但是建议您先看表达式章节)。</para>
+
+        <note>
+          <para>通过配置,FreeMarker 可以在FTL标签和FTL注释中,
+		  使用 <literal>[</literal> 和 <literal>]</literal> 来代替
+		  <literal>&lt;</literal> 和 <literal>&gt;</literal>,就像
+          <literal>[#if user == "Big Joe"]<replaceable>...</replaceable>[/#if]</literal>。
+		  要获取更多信息,请参考:<xref linkend="dgui_misc_alternativesyntax"/>。</para>
+        </note>
+
+        <note>
+          <para>通过配置,FreeMarker 可以不需要 <literal>#</literal> 
+		  来理解预定义指令(比如 <literal>&lt;if user
+          == "Big Joe"&gt;<replaceable>...</replaceable>&lt;/if&gt;</literal>)。
+		  而我们不建议这样来使用。要获取更多信息,请参考:<xref linkend="ref_depr_oldsyntax"/>。</para>
+        </note>
+      </section>
+
+      <section xml:id="dgui_template_exp">
+        <title>表达式</title>
+
+        <para><indexterm>
+            <primary>expression</primary>
+          </indexterm>当需要给插值或者指令参数提供值时,可以使用变量或其他复杂的表达式。
+		  例如,我们设x为8,y为5,那么 <literal>(x + y)/2</literal> 
+		  的值就会被处理成数字类型的值6.5。</para>
+
+        <para>在我们展开细节之前,先来看一些具体的例子:</para>
+
+        <itemizedlist>
+          <listitem>
+            <para>当给插值提供值时:插值的使用方式为 
+			<literal>${<replaceable>expression</replaceable>}</literal>,
+			把它放到你想输出文本的位置上,然后给值就可以打印出来了。
+			即 <literal>${(5 + 8)/2}</literal> 会打印出 ''6.5'' 来
+			(如果输出的语言不是美国英语,也可能打印出''6,5''来)。</para>
+          </listitem>
+
+          <listitem>
+            <para>当给指令参数提供值时:在入门章节我们已经看到 
+			<literal>if</literal> 指令的使用了。这个指令的语法是:<literal>&lt;#if 
+			<replaceable>expression</replaceable>&gt;<replaceable>...</replaceable>&lt;/#if&gt;</literal>。
+            这里的表达式计算结果必须是布尔类型的。比如 
+			<literal>&lt;#if 2 &lt; 3&gt;</literal> 中的 <literal>2 
+			&lt;3</literal> (2小于3)是结果为 <literal>true</literal> 的布尔表达式。</para>
+          </listitem>
+        </itemizedlist>
+
+        <section xml:id="exp_cheatsheet">
+          <title>快速浏览(备忘单)</title>
+
+          <para>这里给已经了解 FreeMarker 的人或有经验的程序员的提个醒:</para>
+
+          <itemizedlist spacing="compact">
+            <listitem>
+              <para><link linkend="dgui_template_exp_direct">直接指定值</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_string">字符串</link>:
+                  <literal>"Foo"</literal> 或者 <literal>'Foo'</literal> 或者
+                  <literal>"It's \"quoted\""</literal> 或者 <literal>'It\'s
+                  "quoted"'</literal> 或者
+                  <literal>r"C:\raw\string"</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_number">数字</link>:
+                  <literal>123.45</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_boolean">布尔值</link>:
+                  <literal>true</literal>, <literal>false</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_seuqence">序列</link>:
+                  <literal>["foo", "bar", 123.45]</literal>; 值域:
+                  <literal>0..9</literal>, <literal>0..&lt;10</literal> (或
+                  <literal>0..!10</literal>), <literal>0..</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_direct_hash">哈希表</link>:
+                  <literal>{"name":"green mouse",
+                  "price":150}</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_var">检索变量</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_var_toplevel">顶层变量</link>:
+				  <literal>user</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link linkend="dgui_template_exp_var_hash">从哈希表中检索数据</link>: <literal>user.name</literal>,
+                  <literal>user["name"]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_var_sequence">从序列中检索数据</link>:
+                  <literal>products[5]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link linkend="dgui_template_exp_var_special">特殊变量</link>: <literal>.main</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_stringop">字符串操作</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_stringop_interpolation">插值(或连接)</link>:
+                  <literal>"Hello ${user}!"</literal> (或 <literal>"Hello
+                  " + user + "!"</literal>)</para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_get_character">获取一个字符</link>:
+				  <literal>name[0]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_stringop_slice">字符串切分:</link> 包含结尾:
+				  <literal>name[0..4]</literal>,不包含结尾:
+				  <literal>name[0..&lt;5]</literal>,基于长度(宽容处理):
+				  <literal>name[0..*5]</literal>,去除开头:
+                  <literal>name[5..]</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_sequenceop">序列操作</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_sequenceop_cat">连接</link>:
+                  <literal>users + ["guest"]</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_seqenceop_slice">序列切分</link>:包含结尾:
+                  <literal>products[20..29]</literal>, 不包含结尾:
+                  <literal>products[20..&lt;30]</literal>,基于长度(宽容处理):
+                  <literal>products[20..*10]</literal>,去除开头:
+                  <literal>products[20..]</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_hashop">哈希表操作</link></para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_hashop_cat">连接</link>:
+                  <literal>passwords + { "joe": "secret42" }</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_arit">算术运算</link>:
+			  <literal>(x * 1.5 + 10) / 2 - y %
+              100</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link
+              linkend="dgui_template_exp_comparison">比较运算</link>:
+              <literal>x == y</literal>, <literal>x != y</literal>,
+              <literal>x &lt; y</literal>, <literal>x &gt; y</literal>,
+              <literal>x &gt;= y</literal>, <literal>x &lt;= y</literal>,
+              <literal>x lt y</literal>, <literal>x lte y</literal>,
+              <literal>x gt y</literal>, <literal>x gte y</literal>,
+              等等。。。。。。</para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_logicalop">逻辑操作</link>:
+			  <literal>!registered &amp;&amp; (firstVisit
+              || fromEurope)</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link
+              linkend="dgui_template_exp_builtin">内建函数</link>:
+              <literal>name?upper_case</literal>,
+              <literal>path?ensure_starts_with('/')</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_methodcall">方法调用</link>:
+			  <literal>repeat("What", 3)</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_missing">处理不存在的值</link>:</para>
+
+              <itemizedlist spacing="compact">
+                <listitem>
+                  <para><link
+                  linkend="dgui_template_exp_missing_default">默认值</link>:
+				  <literal>name!"unknown"</literal> 或者
+                  <literal>(user.name)!"unknown"</literal> 或者
+                  <literal>name!</literal> 或者
+                  <literal>(user.name)!</literal></para>
+                </listitem>
+
+                <listitem>
+                  <para><link linkend="dgui_template_exp_missing_test">检测不存在的值</link>: <literal>name??</literal> 或者
+                  <literal>(user.name)??</literal></para>
+                </listitem>
+              </itemizedlist>
+            </listitem>
+
+            <listitem>
+              <para><link linkend="dgui_template_exp_assignment">赋值操作</link>:
+			  <literal>=</literal>, <literal>+=</literal>,
+              <literal>-=</literal>, <literal>*=</literal>,
+              <literal>/=</literal>, <literal>%=</literal>,
+              <literal>++</literal>, <literal>--</literal></para>
+            </listitem>
+          </itemizedlist>
+
+          <para>请参考: <link
+          linkend="dgui_template_exp_precedence">运算符优先级</link></para>
+        </section>
+
+        <section xml:id="dgui_template_exp_direct">
+          <title>直接确定值</title>
+
+          <indexterm>
+            <primary>literal</primary>
+          </indexterm>
+
+          <indexterm>
+            <primary>constant</primary>
+          </indexterm>
+
+          <para>通常我们喜欢是使用直接确定的值而不是计算的结果。</para>
+
+          <section xml:id="dgui_template_exp_direct_string">
+            <title>字符串</title>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <para>在文本中确定字符串值的方法是看双引号,比如:
+			<literal>"some text"</literal>,或单引号,比如:
+			<literal>'some text'</literal>。这两种形式是等同的。
+			如果文本自身包含用于字符引用的引号
+			( <literal>"</literal> 或 <literal>'</literal>)或反斜杠时,
+			应该在它们的前面再加一个反斜杠;这就是转义。
+			转义允许直接在文本中输入任何字符,
+			也包括<link linkend="gloss.lineBreak">换行</link>。例如:</para>
+
+            <programlisting role="template">${"It's \"quoted\" and
+this is a backslash: \\"}
+
+${'It\'s "quoted" and
+this is a backslash: \\'}</programlisting>
+
+            <para>将会输出:</para>
+
+            <programlisting role="output">It's "quoted" and
+this is a backslash: \
+
+It's "quoted" and
+this is a backslash: \</programlisting>
+
+            <note>
+              <para>这里当然可以直接在模板中输入文本而不需要 
+			  <literal>${<replaceable>...</replaceable>}</literal>。
+			  但是我们在这里用它只是为了示例来说明表达式的使用。</para>
+            </note>
+
+            <anchor xml:id="topic.escapeSequence"/>
+
+            <indexterm>
+              <primary>escape sequences</primary>
+            </indexterm>
+
+            <para>下面的表格是FreeMarker支持的所有转义字符。
+			在字符串使用反斜杠的其他所有情况都是错误的,运行这样的模板都会失败。</para>
+
+            <informaltable border="1">
+              <thead>
+                <tr>
+                  <th>转义序列</th>
+
+                  <th>含义</th>
+                </tr>
+              </thead>
+
+              <tbody>
+                <tr>
+                  <td><literal>\"</literal></td>
+
+                  <td>引号 (u0022)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\'</literal></td>
+
+                  <td>单引号(又称为撇号) (u0027)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\{</literal></td>
+
+                  <td>起始花括号:<literal>{</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\\</literal></td>
+
+                  <td>反斜杠 (u005C)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\n</literal></td>
+
+                  <td>换行符 (u000A)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\r</literal></td>
+
+                  <td>回车 (u000D)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\t</literal></td>
+
+                  <td>水平制表符(又称为tab) (u0009)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\b</literal></td>
+
+                  <td>退格 (u0008)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\f</literal></td>
+
+                  <td>换页 (u000C)</td>
+                </tr>
+
+                <tr>
+                  <td><literal>\l</literal></td>
+
+                  <td>小于号:<literal>&lt;</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\g</literal></td>
+
+                  <td>大于号:<literal>&gt;</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\a</literal></td>
+
+                  <td>&amp;符:<literal>&amp;</literal></td>
+                </tr>
+
+                <tr>
+                  <td><literal>\x<replaceable>Code</replaceable></literal></td>
+
+                  <td>字符的16进制 <link linkend="gloss.unicode">Unicode</link> 码 (<link
+                  linkend="gloss.UCS">UCS</link> 码)</td>
+                </tr>
+              </tbody>
+            </informaltable>
+
+            <para>在 <literal>\x</literal> 之后的 
+			<literal><replaceable>Code</replaceable></literal> 
+			是1-4位的16进制码。下面这个示例中都是在字符串中放置版权符号:
+            <literal>"\xA9 1999-2001"</literal>,
+            <literal>"\x0A9 1999-2001"</literal>,
+            <literal>"\x00A9 1999-2001"</literal>。
+			如果紧跟16进制码后一位的字符也能解释成16进制码时,
+			就必须把4位补全,否则FreeMarker就会误解你的意图。</para>
+
+            <para>请注意,字符序列 <literal>${</literal> (和 <literal>#{</literal>) 
+			有特殊的含义,它们被用做插入表达式的数值(典型的应用是变量的值:
+			<literal>"Hello ${user}!"</literal>)。这将在 <link 
+			linkend="dgui_template_exp_stringop_interpolation">后续章节</link>中解释。
+			如果想要打印 <literal>${</literal> 或 <literal>#{</literal>,
+			就要使用下面所说的原生字符串,或者进行转义。就像 
+			<literal>"foo $\{bar}"</literal>中的 <literal>{</literal>。</para>
+
+            <indexterm>
+              <primary>raw string literal</primary>
+            </indexterm>
+
+            <para>原生字符串是一种特殊的字符串。在原生字符串中,
+			反斜杠和 <literal>${</literal> 没有特殊含义,
+			它们被视为普通的字符。为了表明字符串是原生字符串,
+			在开始的引号或单引号之前放置字母<literal>r</literal>,例如:</para>
+
+            <programlisting role="template">${r"${foo}"}
+${r"C:\foo\bar"}</programlisting>
+
+            <para>将会输出:</para>
+
+            <programlisting role="output">${foo}
+C:\foo\bar</programlisting>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_number">
+            <title>数字</title>
+
+            <indexterm>
+              <primary>number</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <para>输入不带引号的数字就可以直接指定一个数字,
+			必须使用点作为小数的分隔符而不能是其他的分组分隔符。
+			可以使用 <literal>-</literal> 或 <literal>+</literal> 
+			来表明符号 (<literal>+</literal> 是多余的)。
+			科学记数法暂不支持使用 (<literal>1E3</literal> 就是错误的),
+			而且也不能在小数点之前不写0(<literal>.5</literal> 也是错误的)。</para>
+
+            <para>下面的数字都是合法的:<literal>0.08</literal>,
+            <literal>-5.013</literal>,<literal>8</literal>,
+            <literal>008</literal>,<literal>11</literal>,
+            <literal>+11</literal></para>
+
+            <para>请注意,像 <literal>08</literal>、
+            <literal>+8</literal>、 <literal>8.00</literal> 和
+            <literal>8</literal> 这样的数值是完全等同的,它们都是数字8。
+			所以, <literal>${08}</literal>、<literal>${+8}</literal>、 
+			<literal>${8.00}</literal> 和 <literal>${8}</literal> 
+			的输出都是一样的。</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_boolean">
+            <title>布尔值</title>
+
+            <indexterm>
+              <primary>boolean</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>literal</primary>
+
+              <secondary>boolean</secondary>
+            </indexterm>
+
+            <para>直接写 <literal>true</literal> 或者 
+			<literal>false</literal> 就表示一个布尔值了,不需使用引号。</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_seuqence">
+            <title>序列</title>
+
+            <indexterm>
+              <primary>sequence</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>numerical sequence</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>numerical range expression</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>range expression</primary>
+            </indexterm>
+
+            <para>指定一个文字的序列,使用逗号来分隔其中的每个 <link 
+			linkend="topic.dataModel.subVar">子变量</link>,
+			然后把整个列表放到方括号中。例如:</para>
+
+            <programlisting role="template">&lt;#list <emphasis>["foo", "bar", "baz"]</emphasis> as x&gt;
+${x}
+&lt;/#list&gt;</programlisting>
+
+            <para>将会输出:</para>
+
+            <programlisting role="output">foo
+bar
+baz
+ </programlisting>
+
+            <para>列表中的项目是表达式,那么也可以这样做: 
+			<literal>[2 + 2, [1, 2, 3, 4], "foo"]</literal>。
+			其中第一个子变量是数字4,第二个子变量是一个序列,
+			第三个子变量是字符串"foo"。</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_ranges">
+            <title>值域</title>
+
+            <para>值域也是序列,但它们由指定包含的数字范围所创建,
+			而不需指定序列中每一项。比如:
+            <literal>0..&lt;m</literal>,这里假定 <literal>m</literal> 
+			变量的值是5,那么这个序列就包含  
+			<literal>[0, 1, 2, 3, 4]</literal>。值域的主要作用有:使用
+			<literal>&lt;#list<replaceable>...</replaceable>&gt;</literal>
+			来迭代一定范围内的数字,<link 
+			linkend="dgui_template_exp_seqenceop_slice">序列切分</link> 和 
+			<link linkend="dgui_template_exp_stringop_slice">字符串切分</link>。</para>
+
+            <para>值域表达式的通用形式是(
+            <literal><replaceable>start</replaceable></literal> 和
+            <literal><replaceable>end</replaceable></literal> 
+			可以是任意的结果为数字表达式):</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..<replaceable>end</replaceable></literal>:
+                包含结尾的值域。比如 <literal>1..4</literal> 就是 
+				<literal>[1, 2, 3, 4]</literal>, 而 <literal>4..1</literal> 
+				就是 <literal>[4, 3, 2, 1]</literal>。当心一点,
+				包含结尾的值域不会是一个空序列,所以 <literal>0..length-1</literal> 
+				就是 <emphasis>错误的</emphasis>,因为当长度是 <literal>0</literal> 时,
+				序列就成了 <literal>[0, -1]</literal>。</para>
+              </listitem>
+
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..&lt;<replaceable>end</replaceable></literal>
+                或
+                <literal><replaceable>start</replaceable>..!<replaceable>end</replaceable></literal>:
+				不包含结尾的值域。比如 <literal>1..&lt;4</literal> 就是 
+				<literal>[1, 2, 3]</literal>,<literal>4..&lt;1</literal> 
+				就是 <literal>[4, 3, 2]</literal>, 而 <literal>1..&lt;1</literal> 
+				表示 <literal>[]</literal>。请注意最后一个示例;
+				结果可以是空序列,和  <literal>..&lt;</literal> 
+				和 <literal>..!</literal> 没有区别; 最后这种形式在应用程序中使用了 
+				<literal>&lt;</literal> 字符而引发问题(如HTML编辑器等)。</para>
+              </listitem>
+
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..*<replaceable>length</replaceable></literal>:
+                限定长度的值域,比如 <literal>10..*4</literal> 就是 
+				<literal>[10, 11, 12, 13]</literal>,<literal>10..*-4</literal> 
+				就是 <literal>[10, 9, 8, 7]</literal>,而 <literal>10..*0</literal> 
+				表示 <literal>[]</literal>。当这些值域被用来切分时,
+				如果切分后的序列或者字符串结尾在指定值域长度之前,则切分不会有问题;请参考 
+				<link linkend="dgui_template_exp_seqenceop_slice">序列切分</link> 来获取更多信息。</para>
+
+                <note>
+                  <para>限定长度的值域是在 FreeMarker 2.3.21版本中引入的。</para>
+                </note>
+              </listitem>
+
+              <listitem>
+                <para><literal><replaceable>start</replaceable>..</literal>:
+				无右边界值域。这和限制长度的值域很像,只是长度是无限的。
+				比如 <literal>1..</literal> 就是
+                <literal>[1, 2, 3, 4, 5, 6, ... ]</literal>,直到无穷大。
+				但是处理(比如列表显示)这种值域时要万分小心,处理所有项时,
+				会花费很长时间,直到内存溢出应用程序崩溃。
+				和限定长度的值域一样,当它们被切分时,
+				遇到切分后的序列或字符串结尾时,切分就结束了。</para>
+
+                <warning>
+                  <para>无右边界值域在 FreeMarker 2.3.21 版本以前只能用于切分,
+				  若用于其它用途,它就像空序列一样了。要使用新的特性,
+				  使用 FreeMarker 2.3.21 版本是不够的,程序员要设置 
+				  <literal>incompatible_improvements</literal> 至少到2.3.21版本。</para>
+                </warning>
+              </listitem>
+            </itemizedlist>
+
+            <para>值域的进一步注意事项:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para>值域表达式本身并没有方括号,比如这样编写代码 
+				<literal>&lt;#assign myRange = 0..&lt;x&gt;</literal>,
+				而不是 <literal>&lt;#assign myRange = [0..&lt;x]&gt;</literal>。
+				后者会创建一个包含值域的序列。方括号是切分语法的一部分,就像 
+                <literal><replaceable>seq</replaceable>[<replaceable>myRange</replaceable>]</literal>。</para>
+              </listitem>
+
+              <listitem>
+                <para>可以在 <literal>..</literal> 的两侧编写算术表达式而不需要圆括号,
+				就像 <literal>n + 1 ..&lt; m / 2 - 1</literal>。</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>..</literal>,<literal>..&lt;</literal>,
+                <literal>..!</literal> 和 <literal>..*</literal> 是运算符,
+				所以它们中间不能有空格。就像 <literal>n .. &lt;m</literal> 
+				这样是错误的,但是 <literal>n ..&lt; m</literal> 这样就可以。</para>
+              </listitem>
+
+              <listitem>
+                <para>无右边界值域的定义大小是2147483647 (如果
+                <literal>incompatible_improvements</literal> 低于2.3.21版本,那么就是0),
+				这是由于技术上的限制(32位)。但当列表显示它们的时候,实际的长度是无穷大。</para>
+              </listitem>
+
+              <listitem>
+                <para>值域并不存储它们包含的数字,那么对于 <literal>0..1</literal> 和
+                <literal>0..100000000</literal> 来说,创建速度都是一样的,
+				并且占用的内存也是一样的。</para>
+              </listitem>
+            </itemizedlist>
+          </section>
+
+          <section xml:id="dgui_template_exp_direct_hash">
+            <title>哈希表</title>
+
+            <indexterm>
+              <primary>hash</primary>
+
+              <secondary>literal</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>literal</primary>
+
+              <secondary>hash</secondary>
+            </indexterm>
+
+            <para>在模板中指定一个哈希表,就可以遍历用逗号分隔开的"键/值"对,
+			把列表放到花括号内即可。键和值成对出现并以冒号分隔。比如:
+			<literal>{ "name": "green mouse", "price": 150 }</literal>。
+			请注意名和值都是表达式,但是用来检索的名称就必须是字符串类型,
+			而值可以是任意类型。</para>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_var">
+          <title>检索变量</title>
+
+          <section xml:id="dgui_template_exp_var_toplevel">
+            <title>顶层变量</title>
+
+            <indexterm>
+              <primary>subvariable</primary>
+
+              <secondary>accessing</secondary>
+            </indexterm>
+
+            <para>访问顶层的变量,可以简单地使用变量名。例如,
+			用表达式 <literal>user</literal> 就可以在根上获取以 
+			<quote>user</quote> 为名存储的变量值。然后打印出存储在里面的内容:</para>
+
+            <programlisting role="template">${user}</programlisting>
+
+            <para>如果没有顶层变量,那么 FreeMarker 在处理表达式时就会发生错误,
+			进而终止模板的执行(除非程序员事先配置了 FreeMarker)。</para>
+
+            <para>在这种表达式中,变量名只可以包含字母(也可以是非拉丁文),
+			数字(也可以是非拉丁数字),下划线 (<literal>_</literal>),
+			美元符号 (<literal>$</literal>),at符号 (<literal>@</literal>)。
+			此外,第一个字符不可以是ASCII码数字(<literal>0</literal>-<literal>9</literal>)。
+			从 FreeMarker 2.3.22 版本开始,变量名在任何位置也可以包含负号
+			(<literal>-</literal>),点(<literal>.</literal>)和冒号(<literal>:</literal>),
+			但这些必须使用前置的反斜杠(<literal>\</literal>)来转义,
+			否则它们将被解释成操作符。比如,读取名为<quote>data-id</quote>的变量,
+			表达式为 <literal>data\-id</literal>,因为 <literal>data-id</literal> 
+			将被解释成 <quote>data minus id</quote>。
+			(请注意,这些转义仅在标识符中起作用,而不是字符串中。)</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_var_hash">
+            <title>从哈希表中检索数据</title>
+
+            <indexterm>
+              <primary>subvariable</primary>
+
+              <secondary>accessing</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>hash</primary>
+
+              <secondary>accessing subvariable</secondary>
+            </indexterm>
+
+            <para>如果有一个表达式的结果是哈希表,
+			那么我们可以使用点和子变量的名字得到它的值,
+			假设我们有如下的数据模型:</para>
+
+            <programlisting role="dataModel">(root)
+ |
+ +- book
+ |   |
+ |   +- title = "Breeding green mouses"
+ |   |
+ |   +- author
+ |       |
+ |       +- name = "Julia Smith"
+ |       |
+ |       +- info = "Biologist, 1923-1985, Canada"
+ |
+ +- test = "title"</programlisting>
+
+            <para>现在,就可以通过<literal>book.title</literal> 
+			来读取 <literal>title</literal>,book表达式将返回一个哈希表
+			(就像上一章中解释的那样)。按这种逻辑进一步来说,我们可以使用表达式
+			<literal>book.author.name</literal> 来读取到auther的name。</para>
+
+            <para>如果我们想指定同一个表达式的子变量,那么还有另外一种语法格式:
+            <literal>book["title"]</literal>。在方括号中可以给出任意长度字符串的表达式。
+			在上面这个数据模型示例中还可以这么来获取title: <literal>book[test]</literal>。
+			下面这些示例它们含义都是相等的: <literal>book.author.name</literal>,
+            <literal>book["author"].name</literal>,
+            <literal>book.author.["name"]</literal>,
+            <literal>book["author"]["name"]</literal>。</para>
+
+            <para>当使用点式语法时,顶层变量名的命名也有相同的限制
+			(命名时只能使用字母,数字,<literal>_</literal>,<literal>$</literal>,
+			<literal>@</literal>,但是不能使用 <literal>0</literal>-<literal>9</literal>开头,
+			同时,从2.3.22版本开始,也可以使用 <literal>\-</literal>,<literal>\.</literal> 
+			和 <literal>\:</literal>)。当使用方括号语法时,则没有这样的限制,
+			因为名称可以是任意表达式的结果。(请注意,对于FreeMarker的XML支持来说,
+			如果子变量名称是 <literal>*</literal> (星号) 
+			或者 <literal>**</literal>,那么就不要使用方括号语法。)</para>
+
+            <para>对于顶层变量来说,如果尝试访问一个不存在的变量也会引起错误导致解析执行模板中断
+			(除非程序员事先配置过FreeMarker)。</para>
+          </section>
+
+          <section xml:id="dgui_template_exp_var_sequence">
+            <title>从序列中检索数据</title>
+
+            <indexterm>
+              <primary>subvariable</primary>
+
+              <secondary>accessing</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>sequence</primary>
+
+              <secondary>accessing subvariable</secondary>
+            </indexterm>
+
+            <para>这和从哈希表中检索是相同的,但是只能使用方括号语法形式来进行,
+			而且方括号内的表达式最终必须是一个数字而不是字符串。比如,要从 
+			<link linkend="example.stdDataModel">示例数据模型</link> 中获取第一个动物的名字
+			(记住第一项数字索引是0而不是1),可以这么来写: <literal>animals[0].name</literal></para>
+          </section>
+
+          <section xml:id="dgui_template_exp_var_special">
+            <title>特殊变量</title>
+
+            <indexterm>
+              <primary>special variables</primary>
+            </indexterm>
+
+            <para>特殊变量是由FreeMarker引擎本身定义的。
+			使用它们,可以按照如下语法形式来进行:
+            <literal>.<replaceable>variable_name</replaceable></literal>。.</para>
+
+            <para>通常情况下是不需使用特殊变量,而对专业用户来说可能用到。
+			所有特殊变量的说明可以参见 <link linkend="ref_specvar">参考手册</link>。</para>
+          </section>
+        </section>
+
+        <section xml:id="dgui_template_exp_stringop">
+          <title>字符串操作</title>
+
+          <indexterm>
+            <primary>string</primary>
+
+            <secondary>operations</secondary>
+          </indexterm>
+
+          <section xml:id="dgui_template_exp_stringop_interpolation">
+            <title>插值 (或连接)</title>
+
+            <indexterm>
+              <primary>interpolation</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>concatenate strings</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>joining strings</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>concatenate</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>interpolation</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>adding strings</primary>
+            </indexterm>
+
+            <para>如果要在字符串中插入表达式的值,可以在字符串的文字中使用 
+			<literal>${<replaceable>...</replaceable>}</literal> 
+			(已经废弃的 <literal>#{<replaceable>...</replaceable>}</literal>)。
+            <literal>${<replaceable>...</replaceable>}</literal> 在字符串中的作用和在 
+			<link linkend="dgui_template_valueinsertion"> <phrase role="markedText">文本</phrase> 
+			区是相同的</link> (它遵守相同的 <emphasis>本地化敏感</emphasis> 的数字和日期/时间格式),
+			而不是 <link linkend="ref.directive.escape">自动转义</link>。</para>
+
+            <para>示例 (假设user是 ''Big Joe''):</para>
+
+            <programlisting role="template">&lt;#assign s = "Hello ${user}!"&gt;
+${s} &lt;#-- Just to see what the value of s is --&gt;
+</programlisting>
+
+            <para>将会输出:</para>
+
+            <programlisting role="output">Hello Big Joe!</programlisting>
+
+            <warning>
+              <para>用户所犯的一个常见错误是将插值放在了不需要/不应该使用的地方。
+			  插值 <emphasis>仅</emphasis> 在 <link 
+			  linkend="dgui_template_overallstructure"><phrase 
+			  role="markedText">文本</phrase> 区</link> 中有效。(比如, 
+			  <literal>&lt;h1&gt;Hello ${name}!&lt;/h1&gt;</literal>) 还有在字符串值中 
+			  (比如, <literal>&lt;#include "/footer/${company}.html"&gt;</literal>)。
+			  典型的 <emphasis>错误</emphasis> 使用是 
+			  <literal>&lt;#if ${big}&gt;...&lt;/#if&gt;</literal>,
+			  这会导致语法错误。简单写为  
+			  <literal>&lt;#if big&gt;...&lt;/#if&gt;</literal>即可。
+			  而且, <literal>&lt;#if "${big}"&gt;...&lt;/#if&gt;</literal> 
+			  也是 <emphasis>错误的</emphasis>,
+			  因为它将参数值转换为字符串,但是  <literal>if</literal> 指令只接受布尔值,
+			  那么这将导致运行时错误。</para>
+            </warning>
+
+            <para>另外,也可以使用 <literal>+</literal> 号来达到类似的效果:</para>
+
+            <programlisting role="template">&lt;#assign s = "Hello " + user + "!"&gt;</programlisting>
+
+            <para>这样的效果和使用 <literal>${<replaceable>...</replaceable>}</literal> 是一样的。</para>
+
+            <warning>
+              <para>因为 <literal>+</literal> 和使用 
+			  <literal>${<replaceable>...</replaceable>}</literal> 
+			  的规则相同,附加的字符串受到 <literal>locale</literal>,
+              <literal>number_format</literal>,<literal>date_format</literal>, 
+			  <literal>time_format</literal>,<literal>datetime_format</literal> 和
+              <literal>boolean_format</literal> 等等设置的影响,
+			  这是对人来说的,而不是通常机器的解析。默认情况下,这会导致数字出问题,
+			  因为很多地区使用分组(千分位分隔符),那么 
+			  <literal>"someUrl?id=" + id</literal> 就可能会是 
+			  <literal>"someUrl?id=1 234"</literal>。
+			  要预防这种事情的发生,请使用 <literal>?c</literal> 
+			  (对计算机来说)内建函数,那么在 <literal>"someUrl?id=" + id?c</literal> 或
+              <literal>"someUrl?id=${id?c}"</literal>中,
+			  就会得到如 <literal>"someUrl?id=1234"</literal> 
+			  这样的输出, 而不管本地化和格式的设置是什么。</para>
+            </warning>
+          </section>
+
+          <section xml:id="dgui_template_exp_get_character">
+            <title>获取字符</title>
+
+            <indexterm>
+              <primary>charAt</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>get character</primary>
+            </indexterm>
+
+            <para>在给定索引值时可以获取字符串中的一个字符,这和 <link 
+			linkend="dgui_template_exp_var_sequence">序列的子变量</link>是相似的,
+			比如 <literal>user[0]</literal>。这个操作执行的结果是一个长度为1的字符串,
+			FTL并没有独立的字符类型。和序列中的子变量一样,这个索引也必须是数字,
+			范围是从0到字符串的长度,否则模板的执行将会发生错误并终止。</para>
+
+            <para>由于序列的子变量语法和字符的getter语法冲突,
+			那么只能在变量不是序列时使用字符的getter语法(因为FTL支持多类型值,所以它是可能的),
+			这种情况下使用序列方式就比较多。(为了变通,可以使用 <link 
+			linkend="ref_builtin_string_for_string"> 
+			内建函数 <literal>string</literal> </link>,比如
+            <literal>user?string[0]</literal>。不必担心你不理解这是什么意思,
+			内建函数将会在后续章节中讨论。)</para>
+
+            <para>示例(假设 user 是 <quote>Big Joe</quote>):</para>
+
+            <programlisting role="template">${user[0]}
+${user[4]}</programlisting>
+
+            <para>将会输出(请注意第一个字符的索引是0):</para>
+
+            <programlisting role="output">B
+J</programlisting>
+          </section>
+
+          <section xml:id="dgui_template_exp_stringop_slice">
+            <title>字符串切分 (子串)</title>
+
+            <indexterm>
+              <primary>string slicing</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>substring</primary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>slice</secondary>
+            </indexterm>
+
+            <indexterm>
+              <primary>string</primary>
+
+              <secondary>substring</secondary>
+            </indexterm>
+
+            <para>可以按照 <link 
+			linkend="dgui_template_exp_seqenceop_slice">切分序列</link> 
+			(请参看)的相同方式来切分字符串,这就是使用字符来代替序列。不同的是:</para>
+
+            <itemizedlist>
+              <listitem>
+                <pa

<TRUNCATED>

[04/32] incubator-freemarker git commit: Removed @Override-s that aren't valid for (some?) Java 5 compilers.

Posted by dd...@apache.org.
Removed @Override-s that aren't valid for (some?) Java 5 compilers.


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

Branch: refs/heads/2.3
Commit: 738b16ba6b82d940402d7e130a9d00d213dd6bf5
Parents: 99d939c
Author: ddekany <dd...@apache.org>
Authored: Sun Jan 24 22:56:24 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Jan 24 22:56:24 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/ext/servlet/FreemarkerServlet.java      | 3 ---
 .../java/freemarker/core/AppMetaTemplateDateFormatFactory.java   | 2 --
 .../java/freemarker/manual/UnitAwareTemplateNumberModel.java     | 1 -
 .../freemarker/test/CopyrightCommentRemoverTemplateLoader.java   | 4 ----
 4 files changed, 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/738b16ba/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java b/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
index 498466e..4bc7504 100644
--- a/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
+++ b/src/main/java/freemarker/ext/servlet/FreemarkerServlet.java
@@ -1635,7 +1635,6 @@ public class FreemarkerServlet extends HttpServlet {
             this.initParamValue = initParamValue;
         }
 
-        @Override
         public String getInitParamValue() {
             return initParamValue;
         }
@@ -1653,7 +1652,6 @@ public class FreemarkerServlet extends HttpServlet {
             this.initParamValue = initParamValue;
         }
 
-        @Override
         public String getInitParamValue() {
             return initParamValue;
         }
@@ -1669,7 +1667,6 @@ public class FreemarkerServlet extends HttpServlet {
             this.initParamValue = initParamValue;
         }
 
-        @Override
         public String getInitParamValue() {
             return initParamValue;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/738b16ba/src/test/java/freemarker/core/AppMetaTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/AppMetaTemplateDateFormatFactory.java b/src/test/java/freemarker/core/AppMetaTemplateDateFormatFactory.java
index cc518ee..c7e4f13 100644
--- a/src/test/java/freemarker/core/AppMetaTemplateDateFormatFactory.java
+++ b/src/test/java/freemarker/core/AppMetaTemplateDateFormatFactory.java
@@ -102,12 +102,10 @@ public class AppMetaTemplateDateFormatFactory extends TemplateDateFormatFactory
             this.appMeta = appMeta;
         }
 
-        @Override
         public Date getAsDate() throws TemplateModelException {
             return date;
         }
 
-        @Override
         public int getDateType() {
             return dateType;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/738b16ba/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java b/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
index 99a453d..74aacbd 100644
--- a/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
+++ b/src/test/java/freemarker/manual/UnitAwareTemplateNumberModel.java
@@ -31,7 +31,6 @@ public class UnitAwareTemplateNumberModel implements TemplateNumberModel {
         this.unit = unit;
     }
 
-    @Override
     public Number getAsNumber() throws TemplateModelException {
         return value;
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/738b16ba/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 8099e03..0b5ca05 100644
--- a/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
+++ b/src/test/java/freemarker/test/CopyrightCommentRemoverTemplateLoader.java
@@ -34,17 +34,14 @@ public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader {
         this.innerTemplateLoader = innerTemplateLoader;
     }
 
-    @Override
     public Object findTemplateSource(String name) throws IOException {
         return innerTemplateLoader.findTemplateSource(name);
     }
 
-    @Override
     public long getLastModified(Object templateSource) {
         return innerTemplateLoader.getLastModified(templateSource);
     }
 
-    @Override
     public Reader getReader(Object templateSource, String encoding) throws IOException {
         Reader reader = innerTemplateLoader.getReader(templateSource, encoding);
         try {
@@ -55,7 +52,6 @@ public class CopyrightCommentRemoverTemplateLoader implements TemplateLoader {
         }
     }
 
-    @Override
     public void closeTemplateSource(Object templateSource) throws IOException {
         innerTemplateLoader.closeTemplateSource(templateSource);
     }


[09/32] incubator-freemarker git commit: Removed all Eclipse files, instead, added an Eclipse setup guide to the README. It's written so that it useful for other IDE-s too.

Posted by dd...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/codestyle.xml
----------------------------------------------------------------------
diff --git a/codestyle.xml b/codestyle.xml
deleted file mode 100644
index 8fe15f0..0000000
--- a/codestyle.xml
+++ /dev/null
@@ -1,313 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
-  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.
--->
-<profiles version="12">
-<profile kind="CodeFormatterProfile" name="FreeMarker" version="12">
-<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
-<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="8"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
-<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
-<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
-<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
-<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
-<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
-<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
-<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="true"/>
-</profile>
-</profiles>

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/62158399/src/ide-settings/Eclipse-Mars/Formatter-profile-FreeMarker.xml
----------------------------------------------------------------------
diff --git a/src/ide-settings/Eclipse-Mars/Formatter-profile-FreeMarker.xml b/src/ide-settings/Eclipse-Mars/Formatter-profile-FreeMarker.xml
new file mode 100644
index 0000000..e881eaa
--- /dev/null
+++ b/src/ide-settings/Eclipse-Mars/Formatter-profile-FreeMarker.xml
@@ -0,0 +1,313 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+  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.
+-->
+<profiles version="12">
+<profile kind="CodeFormatterProfile" name="FreeMarker" version="12">
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
+<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
+<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+</profile>
+</profiles>


[29/32] incubator-freemarker git commit: README adjustments.

Posted by dd...@apache.org.
README adjustments.


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

Branch: refs/heads/2.3
Commit: af6f05ca307a9807af9ca30a8ee33c4da02842a1
Parents: aa00a77
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 22:29:30 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 22:29:30 2016 +0100

----------------------------------------------------------------------
 README | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/af6f05ca/README
----------------------------------------------------------------------
diff --git a/README b/README
index dde3126..57b8d81 100644
--- a/README
+++ b/README
@@ -117,9 +117,9 @@ You need JDK 8(!), Apache Ant and Ivy to be installed. (As of this writing
 it was tested with Ant 1.8.1 and Ivy 2.3.0.) Note that the ivy-<version>.jar
 should be copied to your Ant home directory "lib" subfolder.
 
-If you need to ensure compliance with certain J2SE versions, copy
-build.properties.sample into build.properties, and edit it
-accordingly.
+It's recommended to copy build.properties.sample into build.properties, and
+edit its content to fit your system. (Although basic jar building should
+succeeds without the build.properties file too.)
 
 To build freemarker.jar, just issue "ant" in the project root
 directory, and it should download all dependencies automatically and
@@ -133,7 +133,7 @@ You have to issue "ant update-deps" for that.
 Eclipse and other IDE setup
 ---------------------------
 
-Below you find the setp-by-step setup for Eclipse Mars.1. If you are using a
+Below you find the step-by-step setup for Eclipse Mars.1. If you are using a
 different version or an entierly different IDE, still read this, and try to
 apply it to your development environment:
 


[23/32] incubator-freemarker git commit: Further Manual (and some JavaDoc) improvements, mostly related to template loading/caching and template error handling. These are mostly wording improvements, but some outdated parts were updated too.

Posted by dd...@apache.org.
Further Manual (and some JavaDoc) improvements, mostly related to template loading/caching and template error handling. These are mostly wording improvements, but some outdated parts were updated too.


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

Branch: refs/heads/2.3
Commit: 9c68f4935f9ea013bb8f357d29ae391ed1db24f8
Parents: 12c64de
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 18:23:03 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 18:23:03 2016 +0100

----------------------------------------------------------------------
 .../template/TemplateExceptionHandler.java      |   9 +-
 src/manual/en_US/book.xml                       | 245 ++++++++++---------
 2 files changed, 132 insertions(+), 122 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/9c68f493/src/main/java/freemarker/template/TemplateExceptionHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/TemplateExceptionHandler.java b/src/main/java/freemarker/template/TemplateExceptionHandler.java
index fdd80ac..6fb113e 100644
--- a/src/main/java/freemarker/template/TemplateExceptionHandler.java
+++ b/src/main/java/freemarker/template/TemplateExceptionHandler.java
@@ -35,15 +35,18 @@ import freemarker.template.utility.StringUtil;
 public interface TemplateExceptionHandler {
     
     /** 
-     * Method called after a {@link TemplateException} was raised inside a template. The error is logged before this is
-     * called, so there's no need to log it here. The exception should be re-thrown unless you want to
-     * suppress the exception.
+     * Method called after a {@link TemplateException} was raised inside a template. The exception should be re-thrown
+     * unless you want to suppress the exception.
      * 
      * <p>Note that you can check with {@link Environment#isInAttemptBlock()} if you are inside a {@code #attempt}
      * block, which then will handle handle this exception and roll back the output generated inside it.
      * 
      * <p>Note that {@link StopException}-s (raised by {@code #stop}) won't be captured.
      * 
+     * <p>Note that you shouldn't log the exception in this method unless you suppress it. If there's a concern that the
+     * exception might won't be logged after it bubbles up from {@link Template#process(Object, Writer)}, simply
+     * ensure that {@link Configuration#getLogTemplateExceptions()} is {@code true}. 
+     * 
      * @param te The exception that occurred; don't forget to re-throw it unless you want to suppress it
      * @param env The runtime environment of the template
      * @param out This is where the output of the template is written

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/9c68f493/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 0df042a..35399f2 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -8487,16 +8487,16 @@ cfg.setTemplateLoader(mtl);</programlisting>
 
           <para>If you change the template file, then FreeMarker will re-load
           and re-parse the template automatically when you get the template
-          next time. However, since checking if the file has been changed can
-          be time consuming, there is a <literal>Configuration</literal> level
-          setting called ``update delay''. This is the time that must elapse
-          since the last checking for a newer version of a certain template
-          before FreeMarker will check that again. This is set to 5 seconds by
-          default. If you want to see the changes of templates immediately,
-          set it to 0. Note that some template loaders may have problems with
-          template updating. For example, class-loader based template loaders
-          typically do not notice that you have changed the template
-          file.</para>
+          next time. However, since always checking for changes can be burden
+          for a system that processes lot of templates, there is a
+          <literal>Configuration</literal> level setting called <quote>update
+          delay</quote> (defaults is 5 seconds). Until this much time has
+          elapsed since the last checking for a newer version, FreeMarker will
+          not check again if the template was changed. If you want to see the
+          changes without delay, set this setting to 0. Note that some
+          template loaders won't see that a template was changed because of
+          the underlying storage mechanism doesn't support that; for example,
+          class-loader based template loaders may have this problem.</para>
 
           <para>A template will be removed from the cache if you call
           <literal>getTemplate</literal> and FreeMarker realizes that the
@@ -8504,7 +8504,11 @@ cfg.setTemplateLoader(mtl);</programlisting>
           that it begins to run out of memory, by default it can arbitrarily
           drop templates from the cache. Furthermore, you can empty the cache
           manually with the <literal>clearTemplateCache</literal> method of
-          <literal>Configuration</literal>.</para>
+          <literal>Configuration</literal>. You can also drop selected
+          template from the cache with
+          <literal>removeTemplateFromCache</literal>; this can be also
+          utilized to force re-loading a template regardless of the
+          <quote>update delay</quote> setting.</para>
 
           <para>The actual strategy of when a cached template should be thrown
           away is pluggable with the <literal>cache_storage</literal> setting,
@@ -8533,12 +8537,12 @@ cfg.setTemplateLoader(mtl);</programlisting>
           <literal>strongSizeLimit</literal> is 0, and
           <literal>softSizeLimit</literal> is
           <literal>Integer.MAX_VALUE</literal> (that is, in practice,
-          infinite). But using non-0 <literal>strongSizeLimit</literal> is
-          maybe a better strategy for high load servers, since it seems that,
-          with only softly referenced items, JVM tends to cause just higher
-          resource consumption if the resource consumption was already high,
-          because it constantly throws frequently used templates from the
-          cache, which then have to be re-loaded and re-parsed.</para>
+          infinite). Depending on how smart the JVM is, using non-0
+          <literal>strongSizeLimit</literal> is maybe a safer option, as with
+          only softly referenced items the JVM could even throw the most
+          frequently used templates when there's a resource shortage, which
+          then have to be re-loaded and re-parsed, burdening the system even
+          more.</para>
         </section>
       </section>
 
@@ -8564,47 +8568,47 @@ cfg.setTemplateLoader(mtl);</programlisting>
               <para>Exceptions occurring when you configure FreeMarker:
               Typically you configure FreeMarker only once in your
               application, when your application initializes itself. Of
-              course, during this, exceptions can occur, as it is obvious from
-              the FreeMarker API...</para>
+              course, during this, exceptions can occur.</para>
             </listitem>
 
             <listitem>
               <para>Exceptions occurring when loading and parsing templates:
               When you call
               <literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>,
-              FreeMarker has to load the template file into the memory and
-              parse it (unless the template is already <link
+              FreeMarker has to load the template into the memory and parse it
+              (unless the template is already <link
               linkend="pgui_config_templateloading_caching">cached</link> in
-              that <literal>Configuration</literal> object). During this, two
-              kind of exceptions can occur:</para>
+              that <literal>Configuration</literal> object). During this,
+              these kind of exceptions can occur:</para>
 
               <itemizedlist>
                 <listitem>
-                  <para><literal>IOException</literal> because the template
-                  file was not found, or other I/O problem occurred while
-                  trying to read it, for example you have no right to read the
-                  file, or there are disk errors. The emitter of these errors
-                  is the <link
-                  linkend="pgui_config_templateloading"><literal>TemplateLoader</literal>
-                  object</link>, which is plugged into the
-                  <literal>Configuration</literal> object. (For the sake of
-                  correctness: When I say ``file'' here, that's a
-                  simplification. For example, templates can be stored in a
-                  table of a relational database as well. This is the business
-                  of the <literal>TemplateLoader</literal>.)</para>
+                  <para><literal>TemplateNotFoundException</literal> because
+                  the requested template doesn't exist. Note this extends
+                  <literal>IOException</literal>.</para>
                 </listitem>
 
                 <listitem>
                   <para><literal>freemarker.core.ParseException</literal>
-                  because the template file is syntactically incorrect
-                  according the rules of the FTL language. The point is that
-                  this error occurs when you obtain the
-                  <literal>Template</literal> object
+                  because the template is syntactically incorrect according
+                  the rules of the FTL language. Note that this error occurs
+                  when you obtain the <literal>Template</literal> object
                   (<literal>Configuration.getTemplate(<replaceable>...</replaceable>)</literal>),
-                  and not when you execute
+                  not later when you execute
                   (<literal>Template.process(<replaceable>...</replaceable>)</literal>)
-                  the template. This exception is an
-                  <literal>IOException</literal> subclass.</para>
+                  the template. . Note this extends
+                  <literal>IOException</literal> (legacy).</para>
+                </listitem>
+
+                <listitem>
+                  <para>Any other kind of <literal>IOException</literal>
+                  because an error has occurred while reading an existing
+                  template. For example you have no right to read the file, or
+                  the connection through which you read the template is
+                  broken. The emitter of these is the <link
+                  linkend="pgui_config_templateloading"><literal>TemplateLoader</literal>
+                  object</link>, which is plugged into the
+                  <literal>Configuration</literal> object.</para>
                 </listitem>
               </itemizedlist>
             </listitem>
@@ -8624,8 +8628,8 @@ cfg.setTemplateLoader(mtl);</programlisting>
                 <listitem>
                   <para><literal>freemarker.template.TemplatException</literal>
                   because other problem occurred while executing the template.
-                  For example, a frequent error is when a template refers to a
-                  variable which is not existing. Be default, when a
+                  For example, a frequent error is referring to a variable
+                  that doesn't exist in the data-model. By default, when a
                   <literal>TemplatException</literal> occurs, FreeMarker
                   prints the FTL error message and the stack trace to the
                   output writer with plain text format, and then aborts the
@@ -8633,8 +8637,11 @@ cfg.setTemplateLoader(mtl);</programlisting>
                   <literal>TemplatException</literal>, which then you can
                   catch as
                   <literal>Template.process(<replaceable>...</replaceable>)</literal>
-                  throws it. But this behavior can be customized. FreeMarker
-                  always <link linkend="pgui_misc_logging">logs</link>
+                  throws it. This behavior can be customized, and in fact, it
+                  should be; see the recommended configuration <link
+                  linkend="pgui_quickstart_createconfiguration">here</link>.
+                  By default FreeMarker also <link
+                  linkend="pgui_misc_logging">logs</link>
                   <literal>TemplatException</literal>-s.</para>
                 </listitem>
               </itemizedlist>
@@ -8651,20 +8658,66 @@ cfg.setTemplateLoader(mtl);</programlisting>
           object, which is plugged into the <literal>Configuration</literal>
           object with its
           <literal>setTemplateExceptionHandler(<replaceable>...</replaceable>)</literal>
-          mehod. The <literal>TemplateExceptionHandler</literal> contains 1
-          method:</para>
+          method. These are the <literal>TemplateExceptionHandler</literal>
+          implementations with FreeMarker comes with:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>TemplateExceptionHandler.DEBUG_HANDLER</literal>:
+              Prints stack trace (includes FTL error message and FTL stack
+              trace) and re-throws the exception. This is the default handler,
+              however, you should be careful not using it in production
+              environment, as it shows technical information about your
+              system.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>TemplateExceptionHandler.HTML_DEBUG_HANDLER</literal>:
+              Same as <literal>DEBUG_HANDLER</literal>, but it formats the
+              stack trace so that it will be readable with Web browsers.
+              Recommended over <literal>DEBUG_HANDLER</literal> when you
+              generate HTML pages, but it should only be used for development
+              as it shows technical information about your system.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>TemplateExceptionHandler.IGNORE_HANDLER</literal>:
+              Simply suppresses all exceptions (though FreeMarker will still
+              log them if
+              <literal>Configuration.getLogTemplateExceptions</literal> is
+              <literal>true</literal>). It does nothing to handle the event.
+              It does not re-throw the exception.</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>TemplateExceptionHandler.RETHROW_HANDLER</literal>:
+              Simply re-throws all exceptions; it doesn't do anything else.
+              This should be used in most applications today. It doesn't print
+              anything to the output about the error, which makes it safe, and
+              the developers can still get the error details from the logs.
+              It's not as convenient during template development as
+              <literal>HTML_DEBUG_HANDLER</literal> or
+              <literal>DEBUG_HANDLER</literal> though. For more information
+              about handling errors in Web applications <link
+              linkend="misc.faq.niceErrorPage">see the FAQ</link>.</para>
+            </listitem>
+          </itemizedlist>
+
+          <para>You can also write a custom
+          <literal>TemplateExceptionHandler</literal> by implementing that
+          interface, which contains this method:</para>
 
           <programlisting role="unspecified">void handleTemplateException(TemplateException te, Environment env, Writer out) 
         throws TemplateException;</programlisting>
 
           <para>Whenever a <literal>TemplateException</literal> occurs, this
-          method will be called. The exception to handle is passed with the
+          method will be called. The exception to handle is in the
           <literal>te</literal> argument, the runtime environment of the
-          template processing is accessible with the <literal>env</literal>
-          argument, and the handler can print to the output using the
-          <literal>out</literal> argument. If the method throws exception
-          (usually it re-throws <literal>te</literal>), then the template
-          processing will be aborted, and
+          template processing is in the <literal>env</literal> argument, and
+          the handler can print to the output using the <literal>out</literal>
+          argument. If this method throws exception (usually it re-throws
+          <literal>te</literal>), then the template processing will be
+          aborted, and
           <literal>Template.process(<replaceable>...</replaceable>)</literal>
           will throw the same exception. If
           <literal>handleTemplateException</literal> doesn't throw exception,
@@ -8673,12 +8726,7 @@ cfg.setTemplateLoader(mtl);</programlisting>
           later). Of course, the handler can still print an error indicator to
           the output.</para>
 
-          <para>In any case, before the
-          <literal>TemplateExceptionHandler</literal> is invoked, FreeMarker
-          will <link linkend="pgui_misc_logging">log</link> the
-          exception.</para>
-
-          <para>Let's see how FreeMarker skips ``statements'' when the error
+          <para>Let's see how FreeMarker skips statements when the error
           handler doesn't throw exception, through examples. Assume we are
           using this template exception handler:</para>
 
@@ -8717,8 +8765,8 @@ cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());</programlisti
 
           <programlisting role="template">a${"moo" + badVar}b</programlisting>
 
-          <para>since, as it was written, the whole interpolation is skipped
-          if any error occurs inside it.</para>
+          <para>because the whole interpolation is skipped if any error occurs
+          inside it.</para>
 
           <para>If an error occurs when evaluating the value of a parameter
           for a directive call, or if there are other problems with the
@@ -8748,8 +8796,8 @@ cfg.setTemplateExceptionHandler(new MyTemplateExceptionHandler());</programlisti
 
           <programlisting role="template">a&lt;#if "foo${badVar}" == "foobar"&gt;Foo&lt;/#if&gt;b</programlisting>
 
-          <para>since, as it was written, the whole directive calling will be
-          skipped if any error occurs during the parameter evaluation.</para>
+          <para>because whole directive calling will be skipped if any error
+          occurs during the parameter evaluation.</para>
 
           <para>The directive call will not be skipped if the error occurs
           after the execution of the directive was already started. That is,
@@ -8781,45 +8829,6 @@ b
   [ERROR: Expression badVar is undefined on line 4, column 5 in test.ftlh.]
   Bar
 c</programlisting>
-
-          <para>FreeMarker comes with these prewritten error handlers:</para>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>TemplateExceptionHandler.DEBUG_HANDLER</literal>:
-              Prints stack trace (includes FTL error message and FTL stack
-              trace) and re-throws the exception. This is the default handler
-              (that is, it is initially prugged into all new
-              <literal>Configuration</literal> objects).</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>TemplateExceptionHandler.HTML_DEBUG_HANDLER</literal>:
-              Same as <literal>DEBUG_HANDLER</literal>, but it formats the
-              stack trace so that it will be readable with Web browsers.
-              Recommended over <literal>DEBUG_HANDLER</literal> when you
-              generate HTML pages.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>TemplateExceptionHandler.IGNORE_HANDLER</literal>:
-              Simply suppresses all exceptions (but remember, FreeMarker will
-              still log them). It does nothing to handle the event. It does
-              not re-throw the exception.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>TemplateExceptionHandler.RETHROW_HANDLER</literal>:
-              Simply re-throws all exceptions, it doesn't do anything else.
-              This handler can be good for Web applications (assuming you
-              don't want to continue template processing after exception),
-              because it gives the most control to the Web application over
-              page generation on error conditions (since FreeMarker doesn't
-              print anything to the output about the error). For more
-              information about handling errors in Web applications <link
-              linkend="misc.faq.niceErrorPage">see the FAQ</link>.</para>
-            </listitem>
-          </itemizedlist>
         </section>
 
         <section>
@@ -8843,10 +8852,8 @@ c</programlisting>
 
           <para>Although it has nothing to do with the FreeMarker
           configuration (the topic of this chapter), for the sake of
-          completeness it is mentioned here that you can handle errors
-          directly in templates as well. This is usually a bad practice (try
-          keep templates simple and non-technical), but nonetheless necessary
-          sometimes:</para>
+          completeness it's mentioned here that you can handle errors directly
+          inside the templates as well:</para>
 
           <itemizedlist>
             <listitem>
@@ -8855,8 +8862,8 @@ c</programlisting>
             </listitem>
 
             <listitem>
-              <para>Surviving malfunctioning ``portlets'' and such expendable
-              page sections: <xref linkend="ref_directive_attempt"/></para>
+              <para>Substituting failing but expendable page sections: <xref
+              linkend="ref_directive_attempt"/></para>
             </listitem>
           </itemizedlist>
         </section>
@@ -8887,10 +8894,10 @@ c</programlisting>
         <itemizedlist>
           <listitem>
             <para><literal>TemplateConfiguration</literal>-s: These store the
-            actual setting assignments that you want to do. For example, this
-            <literal>TemplateConfiguration</literal> will set the encoding and
-            the output format of the matched template (and leave all other
-            settings of it alone):</para>
+            actual setting assignments that you want to apply. For example,
+            this <literal>TemplateConfiguration</literal> will set the
+            encoding and the output format of the matched template (and leave
+            all other settings of it alone):</para>
 
             <programlisting role="unspecified">TemplateConfiguration tcUTF8XML = new TemplateConfiguration();
 tc.setEncoding("utf-8");
@@ -8910,8 +8917,8 @@ tc.setOutputFormat(XMLOutputFormat.INSTANCE);</programlisting>
 
           <listitem>
             <para><literal>TemplateConfigurationFactory</literal>-es: This is
-            what connects <literal>TemplateConfiguration</literal> and
-            <literal>TemplateSourceMatcher</literal> together. This is the
+            what connects <literal>TemplateConfiguration</literal>-s and
+            <literal>TemplateSourceMatcher</literal>-s together. This is the
             Java type of the <literal>template_configurations</literal>
             setting. See the examples below for more.</para>
           </listitem>
@@ -8920,7 +8927,7 @@ tc.setOutputFormat(XMLOutputFormat.INSTANCE);</programlisting>
         <simplesect>
           <title>Example 1</title>
 
-          <para>This setup combines our earlier two example object with a
+          <para>This setup combines our earlier two example objects with a
           <literal>ConditionalTemplateConfigurationFactory</literal>, causing
           all templates with <literal>xml</literal> extension to get UTF-8
           encoding and XML output format:</para>
@@ -8934,7 +8941,7 @@ tc.setOutputFormat(XMLOutputFormat.INSTANCE);</programlisting>
           to the configuring Java code, but only to a Java
           <literal>*.properties</literal> file or other kind of string-string
           key value pairs (the <literal>\</literal>-s are prescribed by the
-          Java Properties file format):</para>
+          Java Properties file format for multi-line values):</para>
 
           <programlisting role="unspecified">templateConfigurations = \
     ConditionalTemplateConfigurationFactory( \
@@ -26412,8 +26419,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <listitem>
                 <para>Call <literal>httpResp.isCommitted()</literal>, and if
                 that returns <literal>false</literal>, then you call
-                <literal>httpResp.reset()</literal> and print a ``nice error
-                page'' for the visitor. If the return value was
+                <literal>httpResp.reset()</literal> and print a <quote>nice
+                error page</quote> for the visitor. If the return value was
                 <literal>true</literal>, then try to finish the page be
                 printing something that makes clear for the visitor that the
                 page generation was abruptly interrupted because of an error


[22/32] incubator-freemarker git commit: Manual grammatical/wording improvements, and some minor clarifications.

Posted by dd...@apache.org.
Manual grammatical/wording improvements, and some minor clarifications.


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

Branch: refs/heads/2.3
Commit: 12c64ded99861bbd67b5026e577c6622fcc629f6
Parents: ac7a07e
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 12:12:54 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 12:12:54 2016 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 367 ++++++++++++++++++++++-------------------
 1 file changed, 197 insertions(+), 170 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/12c64ded/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index a037f65..0df042a 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -5790,7 +5790,9 @@ ${"&lt;h1&gt;"?no_esc + "Foo &amp; bar" + "&lt;/h1&gt;"?no_esc}</programlisting>
             just a shorthand of using the <literal>+</literal> operator
             (<literal>&lt;#assign s = "Hello" + name + "!"&gt;</literal>).
             Thus, <literal>${<replaceable>...</replaceable>}</literal>-s
-            inside string expressions aren't auto-escaped.</para>
+            inside string expressions aren't auto-escaped, but of course when
+            the resulting concatenated string is printed later, it will be
+            possibly auto-escaped.</para>
 
             <programlisting role="template">&lt;#-- We assume that we have "HTML" output format by default. --&gt;
 &lt;#assign name = "Foo &amp; Bar"&gt;
@@ -6224,11 +6226,11 @@ That's all.</programlisting>
 
         <para>First you have to create a
         <literal>freemarker.template.Configuration</literal> instance and
-        adjust its settings. A <literal>Configuration</literal> instance is a
-        central place to store the application level settings of FreeMarker.
-        Also, it deals with the creation and <emphasis>caching</emphasis> of
-        pre-parsed templates (i.e., <literal>Template</literal>
-        objects).</para>
+        adjust its settings. A <literal>Configuration</literal> instance is
+        the central place to store the application level settings of
+        FreeMarker. Also, it deals with the creation and
+        <emphasis>caching</emphasis> of pre-parsed templates (i.e.,
+        <literal>Template</literal> objects).</para>
 
         <para>Normally you will <emphasis>do this only once</emphasis> at the
         beginning of the application (possibly servlet) life-cycle:</para>
@@ -6261,21 +6263,21 @@ cfg.setLogTemplateExceptions(false);</programlisting>
 
         <warning>
           <para>Do not needlessly re-create <literal>Configuration</literal>
-          instances; it's expensive, among others because you lose the caches.
-          <literal>Configuration</literal> instances meant to
-          application-level singletons.</para>
+          instances; it's expensive, among others because you lose the
+          template cache. <literal>Configuration</literal> instances meant to
+          be application-level singletons.</para>
         </warning>
 
-        <para>When using in multi-threaded applications (like for Web sites),
-        the settings in the <literal>Configuration</literal> instance must not
-        be modified anymore after this point. Then it can be treated as
-        <quote>effectively immutable</quote> object, so you can continue with
-        <emphasis>safe publishing</emphasis> techniques (see JSR 133 and
-        related literature) to make the instance available for the other
-        threads. Like, publish the instance through a final or volatile filed,
-        or through a thread-safe IoC container, but not through a plain field.
-        (<literal>Configuration</literal> methods that don't deal with
-        modifying settings are thread-safe.)</para>
+        <para>In multi-threaded applications (like Web sites) the settings in
+        the <literal>Configuration</literal> instance must not be modified
+        anymore after this point. Thus it can be treated as <quote>effectively
+        immutable</quote> object, so you can continue with <emphasis>safe
+        publishing</emphasis> techniques (see JSR 133 and related literature)
+        to make the instance available for other threads. Like, publish the
+        instance through a final or volatile filed, or through a thread-safe
+        IoC container (like the one provided by Spring).
+        <literal>Configuration</literal> methods that don't deal with
+        modifying settings are thread-safe.</para>
       </section>
 
       <section xml:id="pgui_quickstart_createdatamodel">
@@ -6297,7 +6299,7 @@ cfg.setLogTemplateExceptions(false);</programlisting>
           </listitem>
 
           <listitem>
-            <para>Use <literal>java.lang.Number</literal> descents for
+            <para>Use <literal>java.lang.Number</literal> subclasses for
             numbers.</para>
           </listitem>
 
@@ -6307,12 +6309,18 @@ cfg.setLogTemplateExceptions(false);</programlisting>
           </listitem>
 
           <listitem>
+            <para>Use <literal>java.util.Date</literal> and its subclasses for
+            date/time values</para>
+          </listitem>
+
+          <listitem>
             <para>Use <literal>java.util.List</literal> or Java arrays for
             sequences.</para>
           </listitem>
 
           <listitem>
-            <para>Use <literal>java.util.Map</literal> for hashes.</para>
+            <para>Use <literal>java.util.Map</literal> with
+            <literal>String</literal> keys for hashes.</para>
           </listitem>
 
           <listitem>
@@ -6426,9 +6434,8 @@ public class Product {
         <para>Templates are represented by
         <literal>freemarker.template.Template</literal> instances. Typically
         you obtain a <literal>Template</literal> instance from the
-        <literal>Configuration</literal> instance. Whenever you need a
-        template instance you can get it with its
-        <literal>getTemplate</literal> method. Store <link
+        <literal>Configuration</literal> instance, using its.
+        <literal>getTemplate</literal> method. If you store <link
         linkend="example.first">the example template</link> in the
         <literal>test.ftlh</literal> file of the <link
         linkend="pgui_quickstart_createconfiguration">earlier</link> set
@@ -6436,16 +6443,18 @@ public class Product {
 
         <programlisting role="unspecified">Template temp = cfg.getTemplate("test.ftlh");</programlisting>
 
-        <para>When you call this, it will create a <literal>Template</literal>
-        instance corresponds to <literal>test.ftlh</literal>, by reading
+        <para>This gives you a <literal>Template</literal> instance that was
+        created by reading
         <literal><replaceable>/where/you/store/templates/</replaceable>test.ftlh</literal>
-        and parsing (compile) it. The <literal>Template</literal> instance
-        stores the template in the parsed form, and not as text.</para>
+        and parsing it. The <literal>Template</literal> instance stores the
+        template in parsed form, and not as text. If the template is missing
+        or syntactically incorrect, <literal>getTemplate</literal> will throw
+        exception instead.</para>
 
         <para><literal>Configuration</literal> caches
-        <literal>Template</literal> instances, so when you get
-        <literal>test.ftlh</literal> again, it probably won't read and parse
-        the template file again, just returns the same
+        <literal>Template</literal> instances, so when you call
+        <literal>cfg.getTemplate("test.ftlh")</literal> next time, it probably
+        won't read and parse the template file again, just returns the same
         <literal>Template</literal> instance as for the first time.</para>
       </section>
 
@@ -6462,8 +6471,8 @@ public class Product {
           <primary>merging</primary>
         </indexterm>
 
-        <para>As we know, data-model + template = output, and we have a
-        data-model (<literal>root</literal>) and a template
+        <para>As you might already know, data-model + template = output. We
+        already have a data-model (<literal>root</literal>) and a template
         (<literal>temp</literal>), so to get the output we have to merge them.
         This is done by the <literal>process</literal> method of the template.
         It takes the data-model root and a <literal>Writer</literal> as
@@ -6474,9 +6483,9 @@ public class Product {
         <programlisting role="unspecified">Writer out = new OutputStreamWriter(System.out);
 temp.process(root, out);</programlisting>
 
-        <para>This will print to your terminal the output what you have seen
-        in the <link linkend="example.first">first example</link> of the
-        Template Author's Guide.</para>
+        <para>This will print to your terminal the output you have seen in the
+        <link linkend="example.first">first example</link> of the Template
+        Author's Guide.</para>
 
         <para>Java I/O related notes: Depending on what <literal>out</literal>
         is, you may need to ensure that <literal>out.close()</literal> is
@@ -6485,8 +6494,9 @@ temp.process(root, out);</programlisting>
         other times, like in typical Web applications, you must
         <emphasis>not</emphasis> close <literal>out</literal>. FreeMarker
         calls <literal>out.flush()</literal> after a successful template
-        execution (can be disabled in <literal>Configuration</literal>), so
-        you don't need to worry about that.</para>
+        execution (but tis can be disabled in
+        <literal>Configuration</literal>), so you don't need to worry about
+        that.</para>
 
         <para>Note that once you have obtained a <literal>Template</literal>
         instance, you can merge it with different data-models for unlimited
@@ -7850,22 +7860,26 @@ cfg.setObjectWrapper(new MyAppObjectWrapper(cfg.getIncompatibleImprovements()));
         shared variables). Also, it deals with the creation and caching of
         <literal>Template</literal> instances.</para>
 
-        <para>An application typically should use only a single shared
+        <para>An application typically uses only a single shared
         <literal>Configuration</literal> instance. More precisely, typically
-        you should have one <literal>Configuration</literal> instance per
-        independently developed components (like projects, modules, etc.) that
-        internally use FreeMarker, as each should create its own
-        instance.</para>
-
-        <para>As running templates are influenced by the configuration
-        settings, each <literal>Template</literal> instance has a
-        <literal>Configuration</literal> instance associated with it, via the
-        corresponding <literal>Template</literal> constructor parameter.
-        Usually you obtain <literal>Template</literal> instances with
-        <literal>Configuration.getTemplate</literal> (not by directly calling
-        the <literal>Template</literal> constructor), in which case the
-        associated <literal>Configuration</literal> instance will be the one
-        whose <literal>getTemplate</literal> method has been called.</para>
+        you have one <literal>Configuration</literal> instance per
+        independently developed component that internally uses FreeMarker, so
+        they can be configured independently of each other. For example, your
+        e-mail sender component and your report generator component (service)
+        probably want to use their own <literal>Configuration</literal>-s, as
+        their needs differ.</para>
+
+        <para>As the behavior of templates depends on the configuration
+        settings, each <literal>Template</literal> instance has an associated
+        <literal>Configuration</literal> instance. If you obtain the
+        <literal>Template</literal> instances with
+        <literal>Configuration.getTemplate</literal>, the associated
+        <literal>Configuration</literal> instance will be the one whose
+        <literal>getTemplate</literal> method was called. If you create the
+        <literal>Template</literal> instances directly with the
+        <literal>Template</literal> constructor, the
+        <literal>Configuration</literal> should be specified as constructor
+        parameter.</para>
       </section>
 
       <section xml:id="pgui_config_sharedvariables">
@@ -7967,17 +7981,17 @@ cfg.setSharedVariable("company", "Foo Inc.");</programlisting>
         API documentation of
         <literal>Configuration.setSetting(...)</literal></link>.</para>
 
-        <para>Settings stored in <literal>Configuration</literal> instance can
-        be overridden in a <literal>Template</literal> instance. For example
-        you set <literal>"en_US"</literal> for the <literal>locale</literal>
-        setting in the configuration, then the <literal>locale</literal> in
-        all templates that use this configuration will be
-        <literal>"en_US"</literal>, except in templates where the locale was
-        explicitly specified differently (see <link
-        linkend="ref_directive_include_localized">localization</link>). Thus,
-        values in a <literal>Configuration</literal> serve as defaults that
-        can be overridden in a per template manner. The value comes from
-        <literal>Configuration</literal> instance or
+        <para>The settings coming from the <literal>Configuration</literal>
+        can be overridden in a <literal>Template</literal> instance. For
+        example, if you set the <literal>locale</literal> setting to
+        <literal>"en_US"</literal> in the configuration, then the
+        <literal>locale</literal> in all templates that use this configuration
+        will be <literal>"en_US"</literal>, except in templates where the
+        <literal>locale</literal> was explicitly specified differently (see
+        <link linkend="ref_directive_include_localized">localization</link>).
+        Thus, the setting values in the <literal>Configuration</literal> serve
+        as defaults that can be overridden in a per template manner. The value
+        coming from the <literal>Configuration</literal> instance or
         <literal>Template</literal> instance can be further overridden for a
         single <literal>Template.process</literal> call. For each such call a
         <literal>freemarker.core.Environment</literal> object is created
@@ -7985,7 +7999,8 @@ cfg.setSharedVariable("company", "Foo Inc.");</programlisting>
         processing, including the setting values that were overridden on that
         level. The values stored there can even be changed during the template
         processing, so a template can set settings itself, like switching
-        <literal>locale</literal> at the middle of the output.</para>
+        <literal>locale</literal> at the middle of the ongoing
+        processing.</para>
 
         <para>This can be imagined as 3 layers
         (<literal>Configuration</literal>, <literal>Template</literal>,
@@ -8084,22 +8099,22 @@ cfg.setSharedVariable("company", "Foo Inc.");</programlisting>
 myCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
 myCfg.setDefaultEncoding("UTF-8");</programlisting>
 
-            <para>You do it before you start to actually use the
+            <para>You do this before you start to actually use the
             <literal>Configuration</literal> object (typically, when you
             initialize the application); you should treat the object as
             read-only after that.</para>
 
-            <para>In practice, in most Web application frameworks you have to
-            specify the settings in a framework-specific configuration file
-            that require specifying setting as <literal>String</literal>
+            <para>In practice, in most frameworks you have to specify the
+            settings in some kind of framework-specific configuration file
+            that require specifying settings as <literal>String</literal>
             name-value pairs (like in a <literal>.properties</literal> file).
             In that case the authors of the frameworks most probably use the
-            <literal>setSetting(String name, String value)</literal> method of
-            <literal>Configuration</literal>; see available setting names and
-            the format of the values in the <link
+            <literal>Confguration.setSetting(String name, String
+            value)</literal> method; see available setting names and the
+            format of the values in the <link
             xlink:href="http://freemarker.org/docs/api/freemarker/template/Configuration.html#setSetting-java.lang.String-java.lang.String-">API
-            doc of <literal>setSetting</literal></link>. Example for Spring
-            Framework:</para>
+            documentation of <literal>setSetting</literal></link>. Example for
+            Spring Framework:</para>
 
             <programlisting role="unspecified">&lt;bean id="freemarkerConfig"
     class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"&gt;
@@ -8113,9 +8128,9 @@ myCfg.setDefaultEncoding("UTF-8");</programlisting>
 &lt;/bean&gt;</programlisting>
 
             <para>Note that this kind of configuring
-            (<literal>String</literal> key-value pairs) is unfortunately
-            limited compared to directly using the API of
-            <literal>Configuration</literal>.</para>
+            (<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>
           </listitem>
 
           <listitem>
@@ -8145,14 +8160,14 @@ myCfg.setDefaultEncoding("UTF-8");</programlisting>
             <literal>tag_syntax</literal>,
             <literal>whitespace_stripping</literal>, etc.), as these are not
             inherited from the top-level template, instead each template
-            always uses its own, no mater how it was invoked.</para>
+            always uses its own values, no mater how it was invoked.</para>
 
             <note>
               <para>If you are going to use template layer settings, you
               should set <link
               linkend="pgui_config_incompatible_improvements">the
               <literal>incompatible_improvements</literal> setting</link> to
-              2.3.22 or higher, to avoid confusing legacy bugs.</para>
+              2.3.22 or higher, to avoid soe confusing legacy bugs.</para>
             </note>
           </listitem>
 
@@ -8163,14 +8178,13 @@ myCfg.setDefaultEncoding("UTF-8");</programlisting>
             <itemizedlist>
               <listitem>
                 <para>With Java API: Use the setter methods of the
-                <literal>Environment</literal> object. Certainly you want to
-                do that just before the processing of the template is started,
-                and then you run into the problem that when you call
-                <literal>myTemplate.process(...)</literal> it creates the
-                <literal>Environment</literal> object internally and the
-                immediately processes the template, so you had no chance. The
-                solution is that this two steps can be separated like
-                this:</para>
+                <literal>Environment</literal> object. You may run into the
+                API problem that <literal>myTemplate.process(...)</literal>
+                both creates the <literal>Environment</literal> object
+                internally and processes the template, so you have no
+                opportunity to adjust the <literal>Environment</literal> in
+                between. The solution is that those two steps can be separated
+                like this:</para>
 
                 <programlisting role="unspecified">Environment env = myTemplate.createProcessingEnvironment(root, out);
 env.setLocale(java.util.Locale.ITALY);
@@ -8252,80 +8266,93 @@ env.process();  // process the template</programlisting>
 
           <para>Template loaders are objects that load raw textual data based
           on abstract template paths like <literal>"index.ftl"</literal> or
-          <literal>"products/catalog.ftl"</literal>. It is up to the concrete
-          template loader object what source does it use to fetch the
-          requested data (files in a directory, data base, etc.). When you
-          call <literal>cfg.getTemplate</literal> (where
-          <literal>cfg</literal> is a <literal>Configuration</literal>
-          instance), FreeMarker ask the template loader you have set up for
-          the <literal>cfg</literal> to return the text for the given template
-          path, and then FreeMarker parses that text as template.</para>
+          <literal>"products/catalog.ftl"</literal>. It's up to the concrete
+          template loader if from where and how the template
+          <quote>files</quote> are loaded. They could be real files inside a
+          specified directory, or values in a data base table, or
+          <literal>String</literal>-s in a Java Map, etc. When you call
+          <literal>cfg.getTemplate</literal> (where <literal>cfg</literal> is
+          a <literal>Configuration</literal> instance), FreeMarker asks the
+          template loader (<literal>cfg.getTemplateLoader</literal>) to return
+          the text for the given template path, and then FreeMarker parses
+          that text as template. It doesn't care or even know if the template
+          is a real file or not, and where it is physically; those details are
+          only known by the template loader.</para>
 
           <section>
             <title>Built-in template loaders</title>
 
-            <para>You can set up three template loading methods in the
-            <literal>Configuration</literal> using the following convenience
-            methods. (Each method will create a template loader object
-            internally and set up the <literal>Configuration</literal>
-            instance to use that.)</para>
-
-            <programlisting role="unspecified">void setDirectoryForTemplateLoading(File dir);</programlisting>
-
-            <para>or</para>
-
-            <programlisting role="unspecified">void setClassForTemplateLoading(Class cl, String prefix);</programlisting>
-
-            <para>or</para>
-
-            <programlisting role="unspecified">void setServletContextForTemplateLoading(Object servletContext, String path);</programlisting>
-
-            <para>The first method above sets an explicit directory on the
-            file system from which to load templates. Needless to say perhaps,
-            the <literal>File</literal> parameter must be an existing
-            directory. Otherwise, an exception will be thrown.</para>
-
-            <para>The second call takes a <literal>Class</literal> as a
-            parameter and a prefix. This is for when you want to load
-            templates via the same mechanism that a java
-            <literal>ClassLoader</literal> uses to load classes. This means
-            that the class you pass in will be used to call
-            <literal>Class.getResource()</literal> to find the templates. The
-            <literal>prefix</literal> parameter is prepended to the name of
-            the template. The classloading mechanism will very likely be the
-            preferred means of loading templates for production code, since
-            loading from the classpath mechanism is usually more foolproof
-            than specifying an explicit directory location on the file system.
-            It is also nicer in a final application to keep everything in a
-            <literal>.jar</literal> file that the user can simply execute
-            directly and have all the icons and text and everything else
-            inside the <literal>.jar</literal> file.</para>
-
-            <para>The third call takes the context of your web application,
-            and a base path, which is interpreted relative to the web
-            application root directory (that's the parent of the
-            <literal>WEB-INF</literal> directory). This loader will load the
-            templates from the web application directory. Note that we refer
-            to "directory" here although this loading method works even for
-            unpacked <literal>.war</literal> files since it uses
-            <literal>ServletContext.getResource()</literal> to access the
-            templates. If you omit the second parameter (or use
-            <literal>""</literal>), you can simply store the static files
-            (<literal>.html</literal>, <literal>.jpg</literal>, etc.) mixed
-            with the <literal>.ftl</literal> files, just
-            <literal>.ftl</literal> files will be sent to the client
-            processed. Of course, you must set up a Servlet for the
-            <literal>*.ftl</literal> uri-pattern in
-            <literal>WEB-INF/web.xml</literal> for this, otherwise the client
-            will get the templates as is, and thus may see confidential
-            content! You should not use empty path if this is a problem for
-            your site, rather you should store the templates somewhere inside
-            the <literal>WEB-INF</literal> directory, so the raw templates are
-            never served accidentally. This mechanism will very likely be the
-            preferred means of loading templates for servlet applications,
-            since the templates can be updated without restarting the web
-            application, while this often doesn't work with the class-loader
-            mechanism.</para>
+            <para>You can set up the three most common template loading
+            mechanism in the <literal>Configuration</literal> using the
+            following <emphasis>convenience</emphasis> methods:</para>
+
+            <itemizedlist>
+              <listitem>
+                <para><literal>void setDirectoryForTemplateLoading(File
+                dir)</literal>: Sets a directory on the file system from which
+                to load templates. Template names (template paths) will be
+                interpreted relatively to this physical directory. It won't
+                let you load files outside this directory.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>void setClassForTemplateLoading(Class cl,
+                String basePackagePath)</literal> and <literal>void
+                setClassLoaderForTemplateLoading(ClassLoader classLoader,
+                String basePackagePath)</literal>: These are for when you want
+                to load templates via the same mechanism with which Java loads
+                classes (from the class-path, as they used to say vaguely).
+                This is very likely be the preferred means of loading
+                templates for production code, as it allows you to keep
+                everything inside the deployment <literal>jar</literal> files.
+                The first parameter decides which Java
+                <literal>ClassLoader</literal> will be used. The second
+                parameter specifies the package that contains the templates,
+                in <literal>/</literal>-separated format. Note that if you
+                don't start it with <literal>/</literal>, it will be
+                interpreted relatively to the package of the
+                <literal>Class</literal> parameter.</para>
+              </listitem>
+
+              <listitem>
+                <para><literal>void setServletContextForTemplateLoading(Object
+                servletContext, String path)</literal>: Takes the context of
+                your Servlet-based web application, and a base path, which is
+                interpreted relative to the web application root directory
+                (that's the parent of the <literal>WEB-INF</literal>
+                directory). Note that we refer to "directory" here although
+                this loading method works even for unpacked
+                <literal>.war</literal> files, since it uses
+                <literal>ServletContext.getResource()</literal> to access the
+                templates. If you omit the second parameter (or use
+                <literal>""</literal>), you can simply store the static files
+                (<literal>.html</literal>, <literal>.jpg</literal>, etc.)
+                mixed with the <literal>.ftl</literal> files. Of course, you
+                must set up a Servlet for the <literal>*.ftl</literal>,
+                <literal>*.ftlh</literal>, <literal>*.ftlx</literal>
+                uri-patterns in <literal>WEB-INF/web.xml</literal> for this,
+                otherwise the client will get the raw templates as is! To
+                avoid a such accident, many prefers storing the templates
+                somewhere inside the <literal>WEB-INF</literal> directory,
+                which is never visitable directly. This mechanism will very
+                likely be the preferred means of loading templates for servlet
+                applications, since the templates can be updated without
+                restarting the web application, while this often doesn't work
+                with the class-loader mechanism.</para>
+              </listitem>
+            </itemizedlist>
+
+            <para>If you want to use a custom
+            <literal>TemplateLoader</literal> implementation, or need to set
+            up some extra settings of a built-in template loader, you need to
+            instantiate the <literal>TemplateLoader</literal> object yourself,
+            and then call
+            <literal>Configuration.setTemplateLoader(TemplateLoader)</literal>:</para>
+
+            <programlisting role="unspecified">WebappTemplateLoader templateLoader = new WebappTemplateLoader(servletContext, "WEB-INF/templates");
+templateLoader.setURLConnectionUsesCaches(false);
+templateLoader.setAttemptFileAccess(false);
+cfg.setTemplateLoader(templateLoader);</programlisting>
           </section>
 
           <section>
@@ -8333,12 +8360,12 @@ env.process();  // process the template</programlisting>
 
             <para>If you need to load templates from multiple locations, you
             have to instantiate the template loader objects for every
-            location, wrap them into a special template loader named
-            <literal>MultiTemplateLoader</literal> and finally pass that
-            loader to the <literal>setTemplateLoader(TemplateLoader
-            loader)</literal> method of <literal>Configuration</literal>.
-            Here's an example for loading templates from two distinct
-            directories and with the class-loader:</para>
+            location, wrap them into a <literal>MultiTemplateLoader</literal>,
+            and finally pass that loader to the
+            <literal>setTemplateLoader(TemplateLoader loader)</literal> method
+            of <literal>Configuration</literal>. Here's an example for loading
+            templates from two distinct directories and with the
+            class-loader:</para>
 
             <programlisting role="unspecified">import freemarker.cache.*; // template loaders live in this package
 
@@ -8346,9 +8373,9 @@ env.process();  // process the template</programlisting>
 
 FileTemplateLoader ftl1 = new FileTemplateLoader(new File("/tmp/templates"));
 FileTemplateLoader ftl2 = new FileTemplateLoader(new File("/usr/data/templates"));
-ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "");
-TemplateLoader[] loaders = new TemplateLoader[] { ftl1, ftl2, ctl };
-MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
+ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "/com/example/templates");
+
+MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { ftl1, ftl2, ctl });
 
 cfg.setTemplateLoader(mtl);</programlisting>
 
@@ -8356,15 +8383,15 @@ cfg.setTemplateLoader(mtl);</programlisting>
             <literal>/tmp/templates</literal> directory, and if it does not
             find the requested template there, it will try to load that from
             <literal>/usr/data/templates</literal>, and if it still does not
-            find the requested template, then it tries to load that with the
-            class-loader.</para>
+            find the requested template, then it tries to load it from the
+            <literal>com.example.templates</literal> Java package.</para>
           </section>
 
           <section>
             <title>Loading templates from other sources</title>
 
-            <para>If none of the built-in class loaders are good for you, you
-            will have to write your own class that implements the
+            <para>If none of the built-in class loaders fit your needs, you
+            can write your own class that implements the
             <literal>freemarker.cache.TemplateLoader</literal> interface and
             pass it to the <literal>setTemplateLoader(TemplateLoader
             loader)</literal> method of <literal>Configuration</literal>.


[15/32] incubator-freemarker git commit: Version history adjusted for 2.3.24 final.

Posted by dd...@apache.org.
Version history adjusted for 2.3.24 final.


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

Branch: refs/heads/2.3
Commit: b8e1d5e3f4bd6d50cdf4a6346777b2499a08c347
Parents: 8ee5bc4
Author: ddekany <dd...@apache.org>
Authored: Thu Feb 4 00:05:22 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Thu Feb 4 00:05:22 2016 +0100

----------------------------------------------------------------------
 src/manual/en_US/book.xml | 454 ++++++-----------------------------------
 1 file changed, 66 insertions(+), 388 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/b8e1d5e3/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index e4fb10e..2e6fa99 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.24 Preview 1</productname>
+    <productname>Freemarker 2.3.24</productname>
   </info>
 
   <preface role="index.html" xml:id="preface">
@@ -26410,14 +26410,9 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
       <title>Version history</title>
 
       <section xml:id="versions_2_3_24">
-        <title>2.3.24 Release Candidate 1</title>
+        <title>2.3.24</title>
 
-        <para>Date of release for Release Candidate 1: 2015-01-12</para>
-
-        <para>Planned final release date: around 2016-02-20</para>
-
-        <para>Please test for backward compatibility, and help polishing the
-        new features!</para>
+        <para>Planned final release date: around 2016-03-01</para>
 
         <section>
           <title>Legal changes</title>
@@ -26434,8 +26429,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
           making process have stabilized in a manner consistent with other
           successful ASF projects. While incubation status is not necessarily
           a reflection of the completeness or stability of the code, it does
-          indicate that the project has yet to be fully endorsed by the ASF.
-          </para>
+          indicate that the project has yet to be fully endorsed by the
+          ASF.</para>
         </section>
 
         <section>
@@ -26627,8 +26622,8 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <literal>[<replaceable>index</replaceable>]</literal> operator,
               but not <literal>?size</literal>, which causes
               <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
-              to fail among others. (They shouldn't implement either, but this
-              is historical heritage.)</para>
+              to fail, among others. (They shouldn't implement either, but
+              this is historical heritage.)</para>
             </listitem>
           </itemizedlist>
         </section>
@@ -26748,13 +26743,10 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   TemplateNumberFormatFactory&gt;)</literal> and
                   <literal>Configurable.setCustomDateFormats(Map&lt;String,
                   TemplateDateFormatFactory&gt;)</literal>) with which you can
-                  register your own formats. <emphasis>If you <link
-                  linkend="pgui_config_incompatible_improvements_how_to_set">set
-                  <literal>incompatible_improvements</literal></link> to
-                  2.3.24, and only then</emphasis>, these formats can be
-                  referred from everywhere where you can use a string to
-                  define a format (often as a pattern), with a format string
-                  like <literal>"@foo"</literal> or <literal>"@foo
+                  register your own formats. These formats can be referred
+                  from everywhere where you can use a string to define a
+                  format (often as a pattern), with a format string like
+                  <literal>"@foo"</literal> or <literal>"@foo
                   params"</literal>, where <literal>"foo"</literal> is the key
                   in the <literal>Map&lt;String, ...&gt;</literal> parameter
                   of the earlier shown methods, and the parameters (if any)
@@ -26859,7 +26851,7 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
 
                 <listitem>
                   <para><literal>OverrideResponseLocale</literal>: Specifies
-                  if should we override the <literal>contentType</literal>
+                  if we should override the <literal>contentType</literal>
                   that's already set (i.e., non-<literal>null</literal>) in
                   the <literal>HttpServletResponse</literal>. Earlier, we have
                   always set it, but now this behavior can be changed so that
@@ -26869,11 +26861,11 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 <listitem>
                   <para><literal>ResponseCharacterEncoding</literal>:
                   Deprecates the old (and quirky) logic of specifying the
-                  output charset, which was putting it into the
+                  output charset, which is putting it into the
                   <literal>ContentType</literal> init-param after the MIME
-                  type, otherwise falling back to using the template file
-                  charset. The possible values are <literal>legacy</literal>
-                  (the default for backward compatibility),
+                  type, otherwise falling back to the template file charset.
+                  The possible values are <literal>legacy</literal> (the
+                  default for backward compatibility),
                   <literal>fromTemplate</literal> (which is
                   <literal>legacy</literal> without quirks, and is aware of
                   the <literal>outputEncoding</literal> setting),
@@ -26955,17 +26947,18 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                 </listitem>
 
                 <listitem>
-                  <para>Number without decimal point will now be parsed to
+                  <para>A number without decimal point will now be parsed to
                   <literal>Integer</literal>, <literal>Long</literal>, or
-                  <literal>BigInteger</literal>, depending in the size of the
-                  number. Earlier all number were
+                  <literal>BigInteger</literal>, depending on the size of the
+                  number. Earlier all numbers were parsed to
                   <literal>BigDecimal</literal>-s, but it had little
-                  importance as number types are converted to the constructor
-                  parameter type anyway.</para>
+                  importance before lists and maps were added, as the number
+                  was converted to the constructor or setter parameter type
+                  anyway.</para>
                 </listitem>
 
                 <listitem>
-                  <para>Number literals can have Java type specified postfixes
+                  <para>Number literals can have Java type suffixes
                   (<literal>f</literal>, <literal>d</literal>,
                   <literal>l</literal>), plus <literal>bd</literal> for
                   <literal>BigDecimal</literal> and <literal>bi</literal> for
@@ -27045,11 +27038,11 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
                   <para><literal>DefaultObjectWrapper</literal> (fix is always
                   active): Operations on the <literal>Iterator</literal> that
                   only check if it's empty without reading an element from it,
-                  such as <literal>?has_content</literal>, won't cause the a
-                  later iteration (or further emptiness check) to fail
-                  anymore. Earlier, in certain situations, the second
-                  operation has failed saying that the iterator <quote>can be
-                  listed only once</quote>.</para>
+                  such as <literal>?has_content</literal>, won't cause a later
+                  iteration (or further emptiness check) to fail anymore.
+                  Earlier, in certain situations, the second operation has
+                  failed saying that the iterator <quote>can be listed only
+                  once</quote>.</para>
                 </listitem>
 
                 <listitem>
@@ -27139,11 +27132,6 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
-              <para>Internal code cleanup: Mostly for consistent source code
-              formatting, also many parser construction/setup cleanup</para>
-            </listitem>
-
-            <listitem>
               <para>JSP TLD loading now quotes the location of
               <literal>jar</literal>-s (and other <literal>zip</literal>-s)
               which can't be loaded due to zip format errors in the error
@@ -27195,381 +27183,71 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
               <literal>String</literal>-s and
               <literal>Interpolation</literal>-s.</para>
             </listitem>
-          </itemizedlist>
-        </section>
-
-        <section>
-          <title>Changes compared to 2.3.24 Preview 1</title>
-
-          <itemizedlist>
-            <listitem>
-              <para><literal>Environment</literal> now has public
-              <literal>TemplateDateFormat</literal> returning methods.</para>
-            </listitem>
-
-            <listitem>
-              <para>The various
-              <literal>Template<replaceable>Xxx</replaceable>Format</literal>
-              and
-              <literal>Template<replaceable>Xxx</replaceable>FormatFacotry</literal>
-              exceptions were united under a common abstract superclass,
-              <literal>TemplateValueFormatException</literal>, which is now
-              what the methods of said classes throw (mostly).</para>
-            </listitem>
-
-            <listitem>
-              <para>Added
-              <literal>freemarker.core.AliasTemplateNumberFormatFactory</literal>
-              and <literal>AliasTemplateDateFormatFactory</literal>, which can
-              be used to create custom formats that are aliases to other
-              formats. For example, instead of writing
-              <literal>${n?string["0.00"]}</literal> again and again, you can
-              define the custom format <literal>"price"</literal> as the alias
-              to the format string <literal>"0.00"</literal> in the
-              configuration, and then use
-              <literal>${n?string.@price}</literal>. Thus, you can control at
-              a central place how prices look. Furthermore, the alias can
-              chose a different target format string depending on the current
-              locale; this is especially useful for dates, where conventions
-              can significantly differ in different countries.</para>
-            </listitem>
-
-            <listitem>
-              <para>Everywhere where Java <literal>DecimalFormat</literal>
-              patterns are used (like in the <literal>number_format</literal>
-              configuration setting, or in
-              <literal>?string('0.##')</literal>), now it's possible to
-              specify options like rounding mode or the symbols used, with a
-              FreeMarker-specific <link
-              linkend="topic.extendedJavaDecimalFormat">extension to the
-              pattern syntax</link>.</para>
-            </listitem>
-
-            <listitem>
-              <para>In number/date/time/datetime format strings, initial
-              <literal>@</literal> can be used to refer to custom formats even
-              if <literal>incompatible_improvements</literal> is less than
-              2.3.24, as far as there's any custom format defined. As custom
-              formats is also a 2.3.24 feature, it's backward compatible this
-              way.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>@@</literal> can't be used to escape
-              <literal>@</literal> at the beginning of format strings anymore,
-              because it was confusing on Android, where
-              <literal>DecimalFormat</literal> supports patterns like
-              <literal>"@@@@@@"</literal>. If a pattern has to output a
-              literal <literal>@</literal> as the first character, you can
-              simply use quoting as defined by
-              <literal>DecimalFormat</literal> and
-              <literal>SimpleDateFormat</literal> (for example,
-              <literal>"'@'0.##"</literal>).</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>?date</literal>, <literal>?time</literal> and
-              <literal>?datetime</literal> now can be called as 0 argument
-              method, like <literal>?date()</literal>, etc., which returns the
-              exact object that <literal>TemplateDateFormat.parse</literal>
-              returns, instead of the tricky multi-type object that just using
-              <literal>?date</literal> returns. Because custom
-              <literal>TemplateDateFormat</literal> implementations may return
-              custom <literal>TemplateDateModel</literal> implementations,
-              keeping the exact class can be important in some
-              applications.</para>
-            </listitem>
-
-            <listitem>
-              <para>The <literal>TemplateDateFormat.parse</literal> has been
-              worked out (earlier it was a but different and was marked as
-              draft). <literal>TemplateNumberFormat</literal> has also have a
-              parse method now, though it's just a <literal>final</literal>
-              placeholder now.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>TemplateNumberFormat.format</literal>/<literal>TemplateDateFormat.format</literal>
-              overloads were changed to <literal>formatToPlainText</literal>
-              and <literal>format</literal>, the last returning either String
-              or a <literal>TemplateMarkupOutputModel</literal>. Also,
-              formatting to markup is now actually used by FreeMarker. Thus,
-              it's now possible to have HTML or other markup in number and
-              date/time/datetime formatting results, like
-              <literal>1.23*10&lt;sup&gt;6&lt;/sup&gt;</literal>, which won't
-              be accidentally auto-escaped, as FreeMarker knows that it's
-              already HTML. (See [TODO] as an example.) Note that no
-              out-of-the-box format formats to markup (at the moment), but you
-              could write such custom format.</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>${<replaceable>...</replaceable>}</literal>
-              inside string literals is equivalent to using the
-              <literal>+</literal> operator again. This rule was broken by
-              <literal>+</literal> supporting markup operands, while
-              <literal>${<replaceable>...</replaceable>}</literal> inside
-              string literals didn't. Now similarly as <literal>"foo " +
-              someMarkup</literal> works and gives a markup result,
-              <literal>"foo ${someMarkup}"</literal> does too.</para>
-            </listitem>
-
-            <listitem>
-              <para>The extended decimal format options don't use
-              abbreviations anymore. Like instead of
-              <literal>rnd=hu</literal>, now there's
-              <literal>roundingMode=halfUp</literal>.</para>
-            </listitem>
-
-            <listitem>
-              <para>Added <literal>XHTMLOutputFormat</literal> and
-              <literal>TemplateXHTMLOutputModel</literal>.</para>
-            </listitem>
 
             <listitem>
-              <para><literal>XMLOutputFormat</literal> now uses
-              application/xml MIME type instead of text/xml MIME type</para>
-            </listitem>
-
-            <listitem>
-              <para><literal>RTFOutputFormat</literal> now uses
-              application/rtf MIME type instead of text/rtf</para>
-            </listitem>
-
-            <listitem>
-              <para>Added non-escaping formats (just for the MIME type):
-              <literal>JavaScriptOutputFormat</literal>,
-              <literal>JSONOutputFormat</literal>,
-              <literal>CSSOutputFormat</literal>.</para>
-            </listitem>
-
-            <listitem>
-              <para>Added JavaScriptOutput</para>
-            </listitem>
-
-            <listitem>
-              <para>Added new built-in: <literal>is_markup_output</literal>,
-              returns <literal>true</literal> if the value is of type
-              <quote>markup output</quote>.</para>
+              <para>Internal code cleanup: Mostly for consistent source code
+              formatting, also many parser construction/setup cleanup</para>
             </listitem>
 
             <listitem>
-              <para>New <literal>FreemarkerServlet</literal> init-params (see
-              <link
-              xlink:href="http://freemarker.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">the
-              <literal>FreemarkerSerlvet</literal> API documentation</link>
-              for details):</para>
-
-              <itemizedlist>
-                <listitem>
-                  <para><literal>OverrideResponseContentType</literal>:
-                  Specifies when should we override the
-                  <literal>contentType</literal> that's already set (i.e.,
-                  non-<literal>null</literal>) in the
-                  <literal>HttpServletResponse</literal>. Earlier, we have
-                  always set it, and that's still the default behavior. But
-                  now that this init-param exists, you can change that
-                  behavior, so that the <literal>contentType</literal> you
-                  have specified before forwarding to
-                  <literal>FreemarkerServlet</literal> matters.</para>
-                </listitem>
-
-                <listitem>
-                  <para><literal>OverrideResponseLocale</literal>: Specifies
-                  if should we override the <literal>contentType</literal>
-                  that's already set (i.e., non-<literal>null</literal>) in
-                  the <literal>HttpServletResponse</literal>. Earlier, we have
-                  always set it, but now this behavior can be changed so that
-                  we only set it if it wasn't already set.</para>
-                </listitem>
-
-                <listitem>
-                  <para><literal>ResponseCharacterEncoding</literal>:
-                  Deprecates the old (and quirky) logic of specifying the
-                  output charset, which was putting it into the
-                  <literal>ContentType</literal> init-param after the MIME
-                  type, otherwise falling back to using the template file
-                  charset. The possible values are <literal>legacy</literal>
-                  (the default for backward compatibility),
-                  <literal>fromTemplate</literal> (which is
-                  <literal>legacy</literal> without quirks, and is aware of
-                  the <literal>outputEncoding</literal> setting),
-                  <literal>doNotSet</literal> (keeps what the caller has
-                  already set in the <literal>ServletRespone</literal>) and
-                  any valid charset name (forces a specific output
-                  charset).</para>
-                </listitem>
-              </itemizedlist>
+              <para>Source code changes to conform to Apache source release
+              policy, such as adding copyright headers and getting rid of test
+              <literal>jar</literal>-s committed into the source code. Eclipse
+              project files were also removed, instead the
+              <literal>README</literal> describes how to set up the
+              project.</para>
             </listitem>
 
             <listitem>
-              <para>The new <literal>TemplateConfigurer</literal> class was
-              renamed to <literal>TemplateConfiguration</literal>, and the
-              related configuration setting from
-              <literal>template_configurers</literal> to
-              <literal>template_configurations</literal>. Also, the
-              <literal>TemplateConfigurer.configure</literal> method was
-              renamed to
-              <literal>TemplateConfiguration.apply</literal>.</para>
+              <para>Build script and distribution artifact changes to conform
+              to Apache release policy, most notably separate source and
+              binary releases.</para>
             </listitem>
+          </itemizedlist>
+        </section>
 
-            <listitem>
-              <para>Bug fixed: It wasn't well defined when a Java
-              <literal>Iterator</literal> counts as empty. Depending on what
-              <literal>ObjectWrapper</literal> you are using, one of these
-              fixes apply:</para>
-
-              <itemizedlist>
-                <listitem>
-                  <para><literal>DefaultObjectWrapper</literal> (fix is always
-                  active): Operations on the <literal>Iterator</literal> that
-                  only check if it's empty without reading an element from it,
-                  such as <literal>?has_content</literal>, won't cause the a
-                  later iteration (or further emptiness check) to fail
-                  anymore. Earlier, in certain situations, the second
-                  operation has failed saying that the iterator <quote>can be
-                  listed only once</quote>.</para>
-                </listitem>
-
-                <listitem>
-                  <para><literal>BeansWrapper</literal> (when it's not
-                  extended by <literal>DefaultObjectWrapper</literal>), if
-                  it's <literal>incompatibleImprovements</literal> property is
-                  set to 2.3.24 (or higher): <literal>Iterator</literal>-s
-                  were always said to be non-empty when using
-                  <literal>?has_content</literal> and such (i.e., operators
-                  that check emptiness without reading any elements). Now an
-                  <literal>Iterator</literal> counts as empty exactly if it
-                  has no elements left. (Note that this bug has never affected
-                  basic functionality, like <literal>&lt;#list
-                  ...&gt;</literal>.)</para>
-                </listitem>
-              </itemizedlist>
-            </listitem>
-
-            <listitem>
-              <para>Fixes and improvements in the <quote>object
-              builder</quote> syntax used for configuring FreeMarker from
-              <literal>java.util.Properties</literal> (or other string-only
-              sources). This is not to be confused with the template language
-              syntax, which has nothing to do with the <quote>object
-              builder</quote> syntax we are writing about here. The
-              improvements are:</para>
-
-              <itemizedlist>
-                <listitem>
-                  <para>Number literals can have Java type specified postfixes
-                  (<literal>f</literal>, <literal>d</literal>,
-                  <literal>l</literal>), plus <literal>bd</literal> for
-                  <literal>BigDecimal</literal> and <literal>bi</literal> for
-                  <literal>BigInteger</literal>.</para>
-                </listitem>
-
-                <listitem>
-                  <para>Public static fields can be referred, like
-                  <literal>com.example.MyClass.MY_CONSTANT</literal> or
-                  <literal>Configuration.AUTO_DETECT_TAG_SYNTAX</literal>.</para>
-                </listitem>
-              </itemizedlist>
-            </listitem>
+        <section>
+          <title>Changes compared to 2.3.24 Release Candidate 1</title>
 
+          <itemizedlist>
             <listitem>
-              <para>The parser used by <literal>?interpet</literal> and
-              <literal>?eval</literal> inherits not only the
-              <literal>output_format</literal> of its surrounding lexical
-              context, but also the auto-escaping policy of it (basically, if
-              auto-escapig is on or off).</para>
+              <para>Added
+              <literal>MultiTemplateLoader.setSticky(boolean)</literal> and
+              <literal>MultiTemplateLoader.isSticky()</literal>, with which
+              you can disable the default behavior, where once a template was
+              found in a child <literal>TemplateLoader</literal>, it will be
+              searched there first next time (typically, when the template
+              update delay is expired). With the <literal>sticky</literal>
+              property set to <literal>false</literal>, the child
+              <literal>TemplateLoader</literal>-s will be always searched in
+              the order as they were added to the
+              <literal>MultiTemplateLoader</literal>.</para>
             </listitem>
 
             <listitem>
-              <para>Bug fixed, with
-              <literal>incompatible_improvements</literal> set to 2.3.24
-              (<link linkend="topic.defaultObjectWrapperIcI">see how
-              here...</link>): The <literal>#import</literal> directive meant
-              to copy the library variable into a global variable if it's
-              executed in the main namespace, but that haven't happened when
-              the imported template was already imported earlier in another
-              namespace.</para>
+              <para>Added
+              <literal>StringTemplateLoader.removeTemplate(String)</literal>
+              method.</para>
             </listitem>
 
             <listitem>
-              <para>Fixes in the XML processing feature
-              (<literal>freemarker.ext.dom</literal>):</para>
+              <para>Source code changes to conform to Apache release policy
+              and recommendations:</para>
 
               <itemizedlist>
                 <listitem>
-                  <para>Bug fixed: XPath queries that has only contained
-                  characters that are valid in XML element names and has also
-                  contained <literal>::</literal> (which is valid in names in
-                  namespace-unware documents), like
-                  <literal>e['following-sibling::foo']</literal>, were
-                  interpreted as literal element names (giving 0 hits) rather
-                  than as XPath expressions. Note that there were no such
-                  problem with <literal>e['following-sibling::*']</literal>
-                  for example, as it's not a valid XML element name according
-                  the XML specification. This fix can actually break
-                  applications that has processed namespace unaware XML that
-                  use <literal>::</literal> as part of element or attribute
-                  names, but such an application is highly unlikely, unlike
-                  running into the fixed problem. (Unfortunately, using
-                  <literal>incompatible_improvements</literal> wasn't
-                  technically possible here.)</para>
+                  <para>No more binary test <literal>jar</literal>-s committed
+                  into the source code (instead, they are generated
+                  on-the-fly)</para>
                 </listitem>
 
                 <listitem>
-                  <para>Bug fixed: The <literal>@@qname</literal> of elements
-                  that belong to the XML namespace declared as the default via
-                  <literal>&lt;#ftl ns_prefixes={'D':'...', ...
-                  }&gt;</literal> no longer starts with <literal>D:</literal>,
-                  instead they just start with no name space prefix.</para>
-                </listitem>
-
-                <listitem>
-                  <para>Bug fixed: In the markup returned by the
-                  <literal>@@markup</literal> key, when there were multiple
-                  namespaces for which there was no prefix associated with via
-                  <literal>&lt;#ftl
-                  ns_prefixes=<replaceable>...</replaceable>&gt;</literal>,
-                  all those namespaces were assigned to the same
-                  auto-generated <literal>xmlns</literal> prefix (usually
-                  <quote>a</quote>). Now they will get <quote>a</quote>,
-                  <quote>b</quote>, <quote>c</quote>, etc. prefixes.</para>
+                  <para>Eclipse project files were removed, instead, the
+                  <literal>README</literal> describes how to set up the
+                  project.</para>
                 </listitem>
               </itemizedlist>
             </listitem>
-
-            <listitem>
-              <para>Bug fixed: With
-              <literal>incompatible_improvements</literal> set to 2.3.24
-              (<link linkend="topic.defaultObjectWrapperIcI">see how
-              here...</link>),
-              <literal><replaceable>m</replaceable>?is_sequence</literal>
-              doesn't return <literal>true</literal> for Java methods wrapped
-              by <literal>BeansWrapper</literal> and its subclasses (most
-              notably <literal>DefaultObjectWrapper</literal>) anymore, as
-              they only implement the
-              <literal>[<replaceable>index</replaceable>]</literal> operator,
-              but not <literal>?size</literal>, which causes
-              <literal>&lt;#list <replaceable>...</replaceable>&gt;</literal>
-              to fail among others. (They shouldn't implement either, but this
-              is historical heritage.)</para>
-            </listitem>
-
-            <listitem>
-              <para>Added an overload to
-              <literal>Configuration.getSupportedBuiltInNames</literal> and
-              <literal>Configuration.getSupportedBuiltInDirectiveNames</literal>
-              that has a <literal>namingConvention</literal> parameter. This
-              is useful for tooling as since 2.3.23 we support both camel case
-              naming convention (like
-              <literal><replaceable>s</replaceable>?upperCase</literal>) and
-              the legacy one (like
-              <literal><replaceable>s</replaceable>?upper_case</literal>).
-              Furthermore the old 0 argument overload will now utilize
-              <literal>Configuration.getNamingConvention()</literal> to only
-              return the relevant names if it's not
-              <literal>AUTO_DETECT_NAMING_CONVENTION</literal>.</para>
-            </listitem>
           </itemizedlist>
         </section>
       </section>


[26/32] incubator-freemarker git commit: NOTICE content fix

Posted by dd...@apache.org.
NOTICE content 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/4bc1ce18
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/4bc1ce18
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/4bc1ce18

Branch: refs/heads/2.3
Commit: 4bc1ce1898c8fd0078e4d6179b0e7b729659f785
Parents: 677cdf9
Author: ddekany <dd...@apache.org>
Authored: Sun Mar 20 21:09:23 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Mar 20 21:09:23 2016 +0100

----------------------------------------------------------------------
 NOTICE | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/4bc1ce18/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
index 4c7b803..9015fd9 100644
--- a/NOTICE
+++ b/NOTICE
@@ -12,10 +12,10 @@ 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:
   
-    src/main/freemarker/ext/jsp/web-app_2_2.dtd
-    src/main/freemarker/ext/jsp/web-app_2_3.dtd
-    src/main/freemarker/ext/jsp/web-jsptaglibrary_1_1.dtd
-    src/main/freemarker/ext/jsp/web-jsptaglibrary_1_2.dtd
+    src/main/resources/freemarker/ext/jsp/web-app_2_2.dtd
+    src/main/resources/freemarker/ext/jsp/web-app_2_3.dtd
+    src/main/resources/freemarker/ext/jsp/web-jsptaglibrary_1_1.dtd
+    src/main/resources/freemarker/ext/jsp/web-jsptaglibrary_1_2.dtd
 
 =========================================================================
 


[14/32] incubator-freemarker git commit: 1. Added MultiTemplateLoader.setSticky(boolean) and MultiTemplateLoader.isSticky(), with which you can disable the default behavior, where once a template was found in a child TemplateLoader, it will be searched t

Posted by dd...@apache.org.
1. Added MultiTemplateLoader.setSticky(boolean) and MultiTemplateLoader.isSticky(), with which you can disable the default behavior, where once a template was found in a child TemplateLoader, it will be searched there first next time (typically, when the template update delay is expired). With the sticky property set to false, the child TemplateLoader-s will be always searched in the order as they were added to the MultiTemplateLoader.

2. Added StringTemplateLoader.removeTemplate(String) method.


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

Branch: refs/heads/2.3
Commit: 8ee5bc47eeb07594bb26e1dae31aa27a82c393e0
Parents: cbf9457
Author: ddekany <dd...@apache.org>
Authored: Wed Feb 3 22:48:27 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Wed Feb 3 22:48:27 2016 +0100

----------------------------------------------------------------------
 .../freemarker/cache/MultiTemplateLoader.java   | 61 ++++++++++++------
 .../cache/StatefulTemplateLoader.java           |  2 +-
 .../freemarker/cache/StringTemplateLoader.java  | 13 ++++
 src/manual/en_US/book.xml                       | 20 ++++++
 .../cache/MultiTemplateLoaderTest.java          | 67 ++++++++++++++++++++
 5 files changed, 143 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8ee5bc47/src/main/java/freemarker/cache/MultiTemplateLoader.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/MultiTemplateLoader.java b/src/main/java/freemarker/cache/MultiTemplateLoader.java
index 1500056..c86baa3 100644
--- a/src/main/java/freemarker/cache/MultiTemplateLoader.java
+++ b/src/main/java/freemarker/cache/MultiTemplateLoader.java
@@ -21,25 +21,24 @@ package freemarker.cache;
 
 import java.io.IOException;
 import java.io.Reader;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A {@link TemplateLoader} that uses a set of other loaders to load the templates. On every request, loaders are
- * queried in the order of their appearance in the array of loaders provided to the constructor. However, if a request
- * for some template name was already satisfied in the past by one of the loaders, that Loader is queried first (a soft
- * affinity).
+ * queried in the order of their appearance in the array of loaders provided to the constructor. However, by default, if
+ * a request for some template name was already satisfied in the past by one of the loaders, that loader is queried
+ * first (stickiness). This behavior can be disabled with {@link #setSticky(boolean)}, then the loaders are always
+ * queried in the order of their appearance in the array.
  * 
- * <p>
- * This class is <em>not</em> thread-safe. If it's accessed from multiple threads concurrently, proper synchronization
- * must be provided by the callers. Note that {@link TemplateCache}, the natural user of this class, provides the
- * necessary synchronizations when it uses this class, so then you don't have to worry this.
+ * <p>This class is thread-safe.
  */
 public class MultiTemplateLoader implements StatefulTemplateLoader {
 
     private final TemplateLoader[] loaders;
-    private final Map lastLoaderForName = Collections.synchronizedMap(new HashMap());
+    private final Map<String, TemplateLoader> lastLoaderForName = new ConcurrentHashMap<String, TemplateLoader>();
+    
+    private boolean sticky = true;
 
     /**
      * Creates a new multi template Loader that will use the specified loaders.
@@ -53,13 +52,15 @@ public class MultiTemplateLoader implements StatefulTemplateLoader {
 
     public Object findTemplateSource(String name)
             throws IOException {
-        // Use soft affinity - give the loader that last found this
-        // resource a chance to find it again first.
-        TemplateLoader lastLoader = (TemplateLoader) lastLoaderForName.get(name);
-        if (lastLoader != null) {
-            Object source = lastLoader.findTemplateSource(name);
-            if (source != null) {
-                return new MultiSource(source, lastLoader);
+        if (sticky) {
+            // Use soft affinity - give the loader that last found this
+            // resource a chance to find it again first.
+            TemplateLoader lastLoader = lastLoaderForName.get(name);
+            if (lastLoader != null) {
+                Object source = lastLoader.findTemplateSource(name);
+                if (source != null) {
+                    return new MultiSource(source, lastLoader);
+                }
             }
         }
 
@@ -71,12 +72,16 @@ public class MultiTemplateLoader implements StatefulTemplateLoader {
             TemplateLoader loader = loaders[i];
             Object source = loader.findTemplateSource(name);
             if (source != null) {
-                lastLoaderForName.put(name, loader);
+                if (sticky) {
+                    lastLoaderForName.put(name, loader);
+                }
                 return new MultiSource(source, loader);
             }
         }
 
-        lastLoaderForName.remove(name);
+        if (sticky) {
+            lastLoaderForName.remove(name);
+        }
         // Resource not found
         return null;
     }
@@ -100,6 +105,9 @@ public class MultiTemplateLoader implements StatefulTemplateLoader {
         ((MultiSource) templateSource).close();
     }
 
+    /**
+     * Clears the soft affinity memory, also resets all enclosed {@link StatefulTemplateLoader}-s.
+     */
     public void resetState() {
         lastLoaderForName.clear();
         for (int i = 0; i < loaders.length; i++) {
@@ -200,4 +208,19 @@ public class MultiTemplateLoader implements StatefulTemplateLoader {
         return loaders[index];
     }
 
+    /**
+     * @since 2.3.24
+     */
+    public boolean isSticky() {
+        return sticky;
+    }
+
+    /**
+     * @since 2.3.24
+     */
+    public void setSticky(boolean sticky) {
+        this.sticky = sticky;
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8ee5bc47/src/main/java/freemarker/cache/StatefulTemplateLoader.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/StatefulTemplateLoader.java b/src/main/java/freemarker/cache/StatefulTemplateLoader.java
index 0387793..0e0a21c 100644
--- a/src/main/java/freemarker/cache/StatefulTemplateLoader.java
+++ b/src/main/java/freemarker/cache/StatefulTemplateLoader.java
@@ -22,7 +22,7 @@ package freemarker.cache;
 import freemarker.template.Configuration;
 
 /**
- * Interface that can be implemented by template loaders that maintain some 
+ * Interface that can be implemented by {@link TemplateLoader}-s that maintain some 
  * sort of internal state (i.e. caches of earlier lookups for performance 
  * optimization purposes etc.) and support resetting of their state. 
  */

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8ee5bc47/src/main/java/freemarker/cache/StringTemplateLoader.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/StringTemplateLoader.java b/src/main/java/freemarker/cache/StringTemplateLoader.java
index e3ccf1a..8b8bd4a 100644
--- a/src/main/java/freemarker/cache/StringTemplateLoader.java
+++ b/src/main/java/freemarker/cache/StringTemplateLoader.java
@@ -94,6 +94,19 @@ public class StringTemplateLoader implements TemplateLoader {
         templates.put(name, new StringTemplateSource(name, templateSource, lastModified));
     }
     
+    /**
+     * Removes the template with the specified name if it was added earlier.
+     * 
+     * @param name Exactly the key with which the template was added.
+     * 
+     * @return Whether a template was found with the given key (and hence was removed now) 
+     * 
+     * @since 2.3.24
+     */
+    public boolean removeTemplate(String name) {
+        return templates.remove(name) != null;
+    }
+    
     public void closeTemplateSource(Object templateSource) {
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8ee5bc47/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 0ea368d..e4fb10e 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -26987,6 +26987,26 @@ TemplateModel x = env.getVariable("x");  // get variable x</programlisting>
             </listitem>
 
             <listitem>
+              <para>Added
+              <literal>MultiTemplateLoader.setSticky(boolean)</literal> and
+              <literal>MultiTemplateLoader.isSticky()</literal>, with which
+              you can disable the default behavior, where once a template was
+              found in a child <literal>TemplateLoader</literal>, it will be
+              searched there first next time (typically, when the template
+              update delay is expired). With the <literal>sticky</literal>
+              property set to <literal>false</literal>, the child
+              <literal>TemplateLoader</literal>-s will be always searched in
+              the order as they were added to the
+              <literal>MultiTemplateLoader</literal>.</para>
+            </listitem>
+
+            <listitem>
+              <para>Added
+              <literal>StringTemplateLoader.removeTemplate(String)</literal>
+              method.</para>
+            </listitem>
+
+            <listitem>
               <para>Bug fixed, only with
               <literal>incompatible_improvements</literal> set to 2.3.24
               (<link linkend="topic.defaultObjectWrapperIcI">see how

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8ee5bc47/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java b/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
new file mode 100644
index 0000000..c67ca76
--- /dev/null
+++ b/src/test/java/freemarker/cache/MultiTemplateLoaderTest.java
@@ -0,0 +1,67 @@
+package freemarker.cache;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+
+public class MultiTemplateLoaderTest {
+
+    @Test
+    public void testBasics() throws IOException {
+        StringTemplateLoader stl1 = new StringTemplateLoader();
+        stl1.putTemplate("1.ftl", "1");
+        stl1.putTemplate("both.ftl", "both 1");
+
+        StringTemplateLoader stl2 = new StringTemplateLoader();
+        stl2.putTemplate("2.ftl", "2");
+        stl2.putTemplate("both.ftl", "both 2");
+        
+        MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { stl1, stl2 });
+        assertEquals("1", getTemplate(mtl, "1.ftl"));
+        assertEquals("2", getTemplate(mtl, "2.ftl"));
+        assertEquals("both 1", getTemplate(mtl, "both.ftl"));
+        assertNull(getTemplate(mtl, "neither.ftl"));
+    }
+
+    @Test
+    public void testSticky() throws IOException {
+        testStickiness(true);
+    }
+
+    @Test
+    public void testNonSticky() throws IOException {
+        testStickiness(false);
+    }
+    
+    private void testStickiness(boolean sticky) throws IOException {
+        StringTemplateLoader stl1 = new StringTemplateLoader();
+        stl1.putTemplate("both.ftl", "both 1");
+        
+        StringTemplateLoader stl2 = new StringTemplateLoader();
+        stl2.putTemplate("both.ftl", "both 2");
+
+        MultiTemplateLoader mtl = new MultiTemplateLoader(new TemplateLoader[] { stl1, stl2 });
+        mtl.setSticky(sticky);
+        
+        assertEquals("both 1", getTemplate(mtl, "both.ftl"));
+        assertTrue(stl1.removeTemplate("both.ftl"));
+        assertEquals("both 2", getTemplate(mtl, "both.ftl"));
+        stl1.putTemplate("both.ftl", "both 1");
+        assertEquals(sticky ? "both 2" : "both 1", getTemplate(mtl, "both.ftl"));
+        assertTrue(stl2.removeTemplate("both.ftl"));
+        assertEquals("both 1", getTemplate(mtl, "both.ftl"));
+    }
+    
+    private String getTemplate(TemplateLoader tl, String name) throws IOException {
+        Object tSrc = tl.findTemplateSource(name);
+        if (tSrc == null) {
+            return null;
+        }
+        
+        return IOUtils.toString(tl.getReader(tSrc, "UTF-8"));
+    }
+    
+}