Repository: incubator-freemarker
Updated Branches:
  refs/heads/3 f48c81368 -> 0b02af638


Forward ported from 2.3-gae: Added ?absoulte_template_name. Necessary additions 
to the Environment and TemplateNameFormat.


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

Branch: refs/heads/3
Commit: 0b02af638982907ff8ca0fc3d0d77bd0c41c4535
Parents: f48c813
Author: ddekany <ddek...@apache.org>
Authored: Sat Mar 10 21:00:09 2018 +0100
Committer: ddekany <ddek...@apache.org>
Committed: Sat Mar 10 21:00:09 2018 +0100

----------------------------------------------------------------------
 .../core/AbsoluteTemplateNameBITest.java        | 62 ++++++++++++++++++++
 .../core/CustomTemplateResolverTest.java        |  5 ++
 .../TemplateNameFormatTest.java                 | 15 ++++-
 .../apache/freemarker/core/ASTExpBuiltIn.java   |  3 +-
 .../freemarker/core/BuiltInsForStringsMisc.java | 52 ++++++++++++++++
 .../org/apache/freemarker/core/Environment.java | 27 ++++++++-
 .../templateresolver/TemplateNameFormat.java    |  5 ++
 .../core/templateresolver/TemplateResolver.java | 12 +++-
 .../impl/DefaultTemplateNameFormat.java         | 15 ++++-
 .../impl/DefaultTemplateResolver.java           |  5 ++
 .../examples/AbsoluteTemplateNameBIExample.java | 42 +++++++++++++
 .../AbsoluteTemplateNameBIExample-foo.ftl       | 19 ++++++
 .../AbsoluteTemplateNameBIExample-lib.ftl       | 38 ++++++++++++
 .../dir/AbsoluteTemplateNameBIExample-foo.ftl   | 19 ++++++
 .../dir/AbsoluteTemplateNameBIExample-main.ftl  | 24 ++++++++
 .../AbsoluteTemplateNameBIExample-main.ftl.out  | 26 ++++++++
 .../apache/freemarker/test/TemplateTest.java    |  2 +-
 17 files changed, 362 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core-test/src/test/java/org/apache/freemarker/core/AbsoluteTemplateNameBITest.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/AbsoluteTemplateNameBITest.java
 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/AbsoluteTemplateNameBITest.java
new file mode 100644
index 0000000..f674047
--- /dev/null
+++ 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/AbsoluteTemplateNameBITest.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.apache.freemarker.core;
+
+import java.io.IOException;
+
+import org.apache.freemarker.test.TemplateTest;
+import org.junit.Test;
+
+public class AbsoluteTemplateNameBITest extends TemplateTest {
+
+    @Test
+    public void basicsTest() throws Exception {
+        assertOutput("${'a/b'?absoluteTemplateName}", "/a/b");
+        assertOutput("${'a/b/'?absoluteTemplateName}", "/a/b/");
+        assertOutput("${'foo://a/b'?absoluteTemplateName}", "foo://a/b");
+        assertOutput("${'/a/b'?absoluteTemplateName}", "/a/b");
+
+        assertOutputOfDirPerF("${'a/b'?absoluteTemplateName}", "/dir/a/b");
+        assertOutputOfDirPerF("${'a/b/'?absoluteTemplateName}", "/dir/a/b/");
+        assertOutputOfDirPerF("${'foo://a/b'?absoluteTemplateName}", 
"foo://a/b");
+        assertOutputOfDirPerF("${'/a/b'?absoluteTemplateName}", "/a/b");
+        
+        for (String baseName : new String[] { "dir/f", "/dir/f", "dir/", 
"/dir/" }) {
+            assertOutput("${'a/b'?absoluteTemplateName('" + baseName + "')}", 
"/dir/a/b");
+            assertOutput("${'a/b/'?absoluteTemplateName('" + baseName + "')}", 
"/dir/a/b/");
+            assertOutput("${'foo://a/b'?absoluteTemplateName('" + baseName + 
"')}", "foo://a/b");
+            assertOutput("${'/a/b'?absoluteTemplateName('" + baseName + "')}", 
"/a/b");
+        }
+
+        assertOutput("${'a/b'?absoluteTemplateName('schema://dir/f')}", 
"schema://dir/a/b");
+        assertOutput("${'a/b/'?absoluteTemplateName('schema://dir/f')}", 
"schema://dir/a/b/");
+        assertOutput("${'foo://a/b'?absoluteTemplateName('schema://dir/f')}", 
"foo://a/b");
+        assertOutput("${'/a/b'?absoluteTemplateName('schema://dir/f')}", 
"schema://a/b");
+    }
+    
+    private void assertOutputOfDirPerF(String ftl, String expectedOut)
+            throws IOException, TemplateException {
+        addTemplate("dir/f", ftl);
+        Configuration cfg = getConfiguration();
+        cfg.removeTemplateFromCache("dir/f", getConfiguration().getLocale(), 
null);
+        assertOutputForNamed("dir/f", expectedOut);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core-test/src/test/java/org/apache/freemarker/core/CustomTemplateResolverTest.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CustomTemplateResolverTest.java
 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CustomTemplateResolverTest.java
index 426a96b..d44e999 100644
--- 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/CustomTemplateResolverTest.java
+++ 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/CustomTemplateResolverTest.java
@@ -351,6 +351,11 @@ public class CustomTemplateResolverTest {
         }
 
         @Override
+        public String rootBasedNameToAbsoluteName(String name) throws 
MalformedTemplateNameException {
+            return name.startsWith(":") ? name : ":" + name;
+        }
+
+        @Override
         public boolean supportsTemplateLoaderSetting() {
             return TEMPLATE_LOADER_KEY.equals(supportedSetting);
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateNameFormatTest.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateNameFormatTest.java
 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateNameFormatTest.java
index 50a4120..edbe98d 100644
--- 
a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateNameFormatTest.java
+++ 
b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateNameFormatTest.java
@@ -198,9 +198,22 @@ public class TemplateNameFormatTest {
         assertNormRBNameThrowsColonException("a/b:c/d", tnf);
         assertNormRBNameThrowsColonException("a/b:/..", tnf);
     }
+
+    @Test
+    public void testRootBasedNameToAbsoluteName() throws 
MalformedTemplateNameException {
+        final TemplateNameFormat tnf = DefaultTemplateNameFormat.INSTANCE;
+        
+        assertEquals("/foo/bar", tnf.rootBasedNameToAbsoluteName("foo/bar"));
+        assertEquals("scheme://foo/bar", 
tnf.rootBasedNameToAbsoluteName("scheme://foo/bar"));
+        assertEquals("/foo/bar", tnf.rootBasedNameToAbsoluteName("/foo/bar"));
+        // Lenient handling of malformed rootBasedName:
+        assertEquals("/a/b://c/d", 
tnf.rootBasedNameToAbsoluteName("a/b://c/d"));
+        assertEquals("b:/c/d", tnf.rootBasedNameToAbsoluteName("b:/c/d"));
+        assertEquals("b:c/d", tnf.rootBasedNameToAbsoluteName("b:c/d"));
+    }    
     
     @Test
-    public void assertBackslashNotAllowed() throws IOException {
+    public void testBackslashNotAllowed() throws IOException {
         Configuration cfg = new TestConfigurationBuilder()
                 .templateLoader(new ByteArrayTemplateLoader())
                 .templateNameFormat(DefaultTemplateNameFormat.INSTANCE)

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java 
b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
index 8151568..37163da 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/ASTExpBuiltIn.java
@@ -75,13 +75,14 @@ abstract class ASTExpBuiltIn extends ASTExpression 
implements Cloneable {
     protected ASTExpression target;
     protected String key;
 
-    static final int NUMBER_OF_BIS = 262;
+    static final int NUMBER_OF_BIS = 263;
     static final HashMap<String, ASTExpBuiltIn> BUILT_INS_BY_NAME = new 
HashMap(NUMBER_OF_BIS * 3 / 2 + 1, 1f);
 
     static {
         // Note that you must update NUMBER_OF_BIS if you add new items here!
         
         putBI("abs", new absBI());
+        putBI("absoluteTemplateName", new 
BuiltInsForStringsMisc.absolute_template_nameBI());
         putBI("ancestors", new ancestorsBI());
         putBI("api", new BuiltInsForMultipleTypes.apiBI());
         putBI("boolean", new BuiltInsForStringsMisc.booleanBI());

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
index be95c94..9c401cd 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/BuiltInsForStringsMisc.java
@@ -34,6 +34,9 @@ import org.apache.freemarker.core.model.TemplateStringModel;
 import org.apache.freemarker.core.model.impl.BeanModel;
 import org.apache.freemarker.core.model.impl.DefaultObjectWrapper;
 import org.apache.freemarker.core.model.impl.SimpleNumber;
+import org.apache.freemarker.core.model.impl.SimpleString;
+import 
org.apache.freemarker.core.templateresolver.MalformedTemplateNameException;
+import org.apache.freemarker.core.util.CallableUtils;
 
 class BuiltInsForStringsMisc {
 
@@ -302,5 +305,54 @@ class BuiltInsForStringsMisc {
 
         }
     }
+
+    static class absolute_template_nameBI extends BuiltInForString {
+        @Override
+        TemplateModel calculateResult(String s, Environment env)  throws 
TemplateException {
+            return new AbsoluteTemplateNameResult(s, env);
+        }
+        
+        private class AbsoluteTemplateNameResult implements 
TemplateStringModel, TemplateFunctionModel {
+            private final String pathToResolve;
+            private final Environment env;
+
+            public AbsoluteTemplateNameResult(String pathToResolve, 
Environment env) {
+                this.pathToResolve = pathToResolve;
+                this.env = env;
+            }
+
+            @Override
+            public TemplateModel execute(TemplateModel[] args, CallPlace 
callPlace, Environment env)
+                    throws TemplateException {
+                return new 
SimpleString(resolvePath(CallableUtils.getStringArgument(args, 0, this)));
+            }
+
+            @Override
+            public ArgumentArrayLayout getFunctionArgumentArrayLayout() {
+                return ArgumentArrayLayout.SINGLE_POSITIONAL_PARAMETER;
+            }
+
+            @Override
+            public String getAsString() throws TemplateException {
+                return resolvePath(getTemplate().getLookupName());
+            }
+
+            /**
+             * @param basePath Maybe {@code null}
+             */
+            private String resolvePath(String basePath) throws 
TemplateException {
+                try {
+                    return 
env.rootBasedToAbsoluteTemplateName(env.toFullTemplateName(basePath, 
pathToResolve));
+                } catch (MalformedTemplateNameException e) {
+                    throw new TemplateException(e,
+                            "Can't resolve ", new 
_DelayedJQuote(pathToResolve),
+                            "to absolute template name using base ", new 
_DelayedJQuote(basePath),
+                            "; see cause exception");
+                }
+            }
+            
+        }
+        
+    }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java 
b/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
index 9434990..4800a5b 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Environment.java
@@ -2629,9 +2629,13 @@ public final class Environment extends 
MutableProcessingConfiguration<Environmen
 
     /**
      * 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.
-     *
+     * name. This gives a root based, even if non-normalized and possibly 
non-absolute (but then relative to the root)
+     * template name, that could be used for {@link 
Configuration#getTemplate(String)}. This is mostly used when a
+     * template refers to another template.
+     * <p>
+     * If you need to guarantee that the result is also an absolute path, then 
apply
+     * {@link #rootBasedToAbsoluteTemplateName(String)} on it.
+     * 
      * @param baseName
      *            The name to which relative {@code targetName}-s are relative 
to. Maybe {@code null} (happens when
      *            resolving names in nameless templates), which means that the 
base is the root "directory", and so
@@ -2659,6 +2663,23 @@ public final class Environment extends 
MutableProcessingConfiguration<Environmen
         return configuration.getTemplateResolver().toRootBasedName(baseName, 
targetName);
     }
 
+    /**
+     * Converts a root based name (a name that's either relative to the root, 
or is absolute), which are typically used
+     * by the API (such as for {@link Configuration#getTemplate(String)}), to 
an absolute name, which can be safely
+     * passed to {@code <#include path>} and such, as it won't be 
misinterpreted to be relative to the directory of the
+     * template. For example, {@code "foo/bar.ftl"} is converted to {@code 
"/foo/bar.ftl"}, while {@code "/foo/bar"} or
+     * {@code "foo://bar/baz"} remains as is, as they are already absolute 
names (see {@link DefaultTemplateNameFormat}
+     * for more about the format of names).
+     * 
+     * <p>
+     * You only need this if the template name will be passed to {@code 
<#include name>}, {@code <#import name>},
+     * {@code .getOptionalTemplate(name)} or a similar construct in a 
template, otherwise using non-absolute root
+     * based names is fine.
+     */
+    public String rootBasedToAbsoluteTemplateName(String rootBasedName) throws 
MalformedTemplateNameException {
+        return 
configuration.getTemplateResolver().rootBasedNameToAbsoluteName(rootBasedName);
+    }
+    
     void importMacros(Template template) {
         for (Object macro : template.getMacros().values()) {
             visitMacroOrFunctionDefinition((ASTDirMacroOrFunction) macro);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateNameFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateNameFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateNameFormat.java
index 57773f4..22b5c5e 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateNameFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateNameFormat.java
@@ -39,6 +39,11 @@ public abstract class TemplateNameFormat {
      */
     public abstract String normalizeRootBasedName(String name) throws 
MalformedTemplateNameException;
 
+    /**
+     * Implements {@link 
TemplateResolver#rootBasedNameToAbsoluteName(String)}; see more there.
+     */
+    public abstract String rootBasedNameToAbsoluteName(String name) throws 
MalformedTemplateNameException;
+    
     protected void checkNameHasNoNullCharacter(final String name) throws 
MalformedTemplateNameException {
         if (name.indexOf(0) != -1) {
             throw new MalformedTemplateNameException(name,

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
index debc42d..8a86b20 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/TemplateResolver.java
@@ -199,13 +199,23 @@ public abstract class TemplateResolver {
      * returned), for example, "/foo.ftl" becomes to "foo.ftl".
      * 
      * @param name
-     *            The root based name. Not {@code null}.
+     *            The root based name (a name that's either absolute or 
relative to the root). Not {@code null}.
      * 
      * @return The normalized root based name. Not {@code null}.
      */
     public abstract String normalizeRootBasedName(String name) throws 
MalformedTemplateNameException;
 
     /**
+     * Converts a root based name to an absolute name, which is useful if you 
need to pass a name to something that
+     * doesn't necessary resolve relative paths relative to the root (like the 
{@code #include} directive).
+     * 
+     * @param name
+     *            The root based name (a name that's either absolute or 
relative to the root). Not {@code null}.
+     */
+    // TODO [FM3] This is the kind of complication why normalized template 
names should just be absolute paths. 
+    public abstract String rootBasedNameToAbsoluteName(String name) throws 
MalformedTemplateNameException;
+    
+    /**
      * Tells whether the {@link TemplateResolver} implementation depends on the
      * {@link Configuration#getTemplateLoader() templateLoader} {@link 
Configuration}. If it returns {@code false}
      * then this {@link TemplateResolver} must not call {@link 
TemplateResolverDependencies#getTemplateLoader()}, or

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
index ff2049d..5d07159 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateNameFormat.java
@@ -39,8 +39,8 @@ import org.apache.freemarker.core.util._StringUtils;
  * "example.com/foo.ftl"). The scheme name before the {@code ":"} (colon) 
can't contain {@code "/"}, and {@code ":"}
  * can only be used for denoting the scheme, or else {@link 
MalformedTemplateNameException} is thrown.
  * The scheme part can be separated either with {@code "://"} or just with 
{@code ":"} from the path, hence, {@code
- * myschme:/x} is normalized to {@code myschme:x}, while {@code myschme:///x} 
is normalized to {@code myschme://x},
- * but {@code myschme://x} or {@code myschme:/x} aren't changed by 
normalization. It's up the {@link TemplateLoader}
+ * myscheme:/x} is normalized to {@code myscheme:x}, while {@code 
myscheme:///x} is normalized to {@code myscheme://x},
+ * but {@code myscheme://x} or {@code myscheme:/x} aren't changed by 
normalization. It's up the {@link TemplateLoader}
  * (to which the normalized names are passed) to decide which of these scheme 
separation conventions are accepted.
  * <p>
  * Template names might end with {@code /}, like {@code "foo/"}, and the 
presence or lack of the terminating {@code
@@ -131,6 +131,17 @@ public final class DefaultTemplateNameFormat extends 
TemplateNameFormat {
         
         return scheme == null ? path : scheme + path;
     }
+    
+    @Override
+    public String rootBasedNameToAbsoluteName(String name) throws 
MalformedTemplateNameException {
+        if (findSchemeSectionEnd(name) != 0) {
+            return name;
+        }
+        if (!name.startsWith("/")) {
+            return "/" + name;
+        }
+        return name;
+    }
 
     private int findSchemeSectionEnd(String name) {
         int schemeColonIdx = name.indexOf(":");

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
----------------------------------------------------------------------
diff --git 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
index aaf09bc..5f277d3 100644
--- 
a/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
+++ 
b/freemarker-core/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
@@ -189,6 +189,11 @@ public class DefaultTemplateResolver extends 
TemplateResolver {
     }
 
     @Override
+    public String rootBasedNameToAbsoluteName(String name) throws 
MalformedTemplateNameException {
+        return templateNameFormat.rootBasedNameToAbsoluteName(name);
+    }
+
+    @Override
     public boolean supportsTemplateLoaderSetting() {
         return true;
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
----------------------------------------------------------------------
diff --git 
a/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
 
b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
new file mode 100644
index 0000000..2a1dcc3
--- /dev/null
+++ 
b/freemarker-manual/src/test/java/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.apache.freemarker.manual.examples;
+
+import org.apache.freemarker.core.Configuration;
+import org.apache.freemarker.core.templateresolver.impl.ClassTemplateLoader;
+import org.apache.freemarker.test.TemplateTest;
+import org.apache.freemarker.test.TestConfigurationBuilder;
+import org.junit.Test;
+
+public class AbsoluteTemplateNameBIExample extends TemplateTest {
+
+    @Override
+    protected Configuration createDefaultConfiguration() throws Exception {
+        return new TestConfigurationBuilder()
+                .templateLoader(new 
ClassTemplateLoader(AbsoluteTemplateNameBIExample.class, ""))
+                .build();
+    }
+
+    @Test
+    public void test() throws Exception {
+        assertOutputForNamed("dir/AbsoluteTemplateNameBIExample-main.ftl");
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-foo.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-foo.ftl
 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-foo.ftl
new file mode 100644
index 0000000..b588cb3
--- /dev/null
+++ 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-foo.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.
+-->
+/foo

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-lib.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-lib.ftl
 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-lib.ftl
new file mode 100644
index 0000000..13d724b
--- /dev/null
+++ 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/AbsoluteTemplateNameBIExample-lib.ftl
@@ -0,0 +1,38 @@
+<#--
+  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.
+-->
+<#--
+  <@smileyInclude name /> behaves like <#include name>, but prints a "(:" 
before the
+  template, or prints "):" instead if the template is missing.
+
+  Note that just like with #include, if name is relative, it's resolved based 
on the
+  directory of the caller template, not of the template that defines this 
macro. As
+  .get_optional_template resolves relative names based on the current 
template, we
+  had to convert the name to an absolute name based on the caller template 
before
+  passing it to it.
+-->
+<#macro smileyInclude name{positional}>
+  <#local t = .getOptionalTemplate(
+      name?absoluteTemplateName(.callerTemplateName))>
+  <#if t.exists>
+    (:
+    <@t.include />
+  <#else>
+    ):
+  </#if>
+</#macro>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-foo.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-foo.ftl
 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-foo.ftl
new file mode 100644
index 0000000..e68993c
--- /dev/null
+++ 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-foo.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.
+-->
+/dir/foo

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl
----------------------------------------------------------------------
diff --git 
a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl
 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl
new file mode 100644
index 0000000..311bb9a
--- /dev/null
+++ 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl
@@ -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.
+-->
+<#import '/AbsoluteTemplateNameBIExample-lib.ftl' as lib>
+
+<@lib.smileyInclude 'AbsoluteTemplateNameBIExample-foo.ftl' />
+<@lib.smileyInclude '../AbsoluteTemplateNameBIExample-foo.ftl' />
+<@lib.smileyInclude '/AbsoluteTemplateNameBIExample-foo.ftl' />
+<@lib.smileyInclude 'AbsoluteTemplateNameBIExample-missing.ftl' />
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl.out
----------------------------------------------------------------------
diff --git 
a/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl.out
 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl.out
new file mode 100644
index 0000000..9e9f175
--- /dev/null
+++ 
b/freemarker-manual/src/test/resources/org/apache/freemarker/manual/examples/dir/AbsoluteTemplateNameBIExample-main.ftl.out
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+    (:
+/dir/foo
+    (:
+/foo
+    (:
+/foo
+    ):

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/0b02af63/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
----------------------------------------------------------------------
diff --git 
a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
 
b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
index 00d9306..a7d31f4 100644
--- 
a/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
+++ 
b/freemarker-test-utils/src/main/java/org/apache/freemarker/test/TemplateTest.java
@@ -242,7 +242,7 @@ public abstract class TemplateTest {
             throw new IllegalStateException("The templateLoader was null in 
the configuration");
         } else {
             throw new IllegalStateException(
-                    "The template loader was already set to a 
non-ByteArrayTemplateLoader non-MultiTemplateLoader: "
+                    "The template loader was set to a 
non-ByteArrayTemplateLoader non-MultiTemplateLoader: "
                             + tl);
         }
     }

Reply via email to