http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateConfigurationFactoryTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateConfigurationFactoryTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateConfigurationFactoryTest.java new file mode 100644 index 0000000..a7259d8 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateConfigurationFactoryTest.java @@ -0,0 +1,203 @@ +/* + * 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.templateresolver; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.freemarker.core.TemplateConfiguration; +import org.junit.Test; + +public class TemplateConfigurationFactoryTest { + + @Test + public void testCondition1() throws IOException, TemplateConfigurationFactoryException { + TemplateConfiguration tc = newTemplateConfiguration(1); + + TemplateConfigurationFactory tcf = new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.ftlx"), tc); + + assertNotApplicable(tcf, "x.ftl"); + assertApplicable(tcf, "x.ftlx", tc); + } + + @Test + public void testCondition2() throws IOException, TemplateConfigurationFactoryException { + TemplateConfiguration tc = newTemplateConfiguration(1); + + TemplateConfigurationFactory tcf = new ConditionalTemplateConfigurationFactory( + new FileNameGlobMatcher("*.ftlx"), + new ConditionalTemplateConfigurationFactory( + new FileNameGlobMatcher("x.*"), tc)); + + assertNotApplicable(tcf, "x.ftl"); + assertNotApplicable(tcf, "y.ftlx"); + assertApplicable(tcf, "x.ftlx", tc); + } + + @Test + public void testMerging() throws IOException, TemplateConfigurationFactoryException { + TemplateConfiguration tc1 = newTemplateConfiguration(1); + TemplateConfiguration tc2 = newTemplateConfiguration(2); + TemplateConfiguration tc3 = newTemplateConfiguration(3); + + TemplateConfigurationFactory tcf = new MergingTemplateConfigurationFactory( + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.ftlx"), tc1), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*a*.*"), tc2), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*b*.*"), tc3)); + + assertNotApplicable(tcf, "x.ftl"); + assertApplicable(tcf, "x.ftlx", tc1); + assertApplicable(tcf, "a.ftl", tc2); + assertApplicable(tcf, "b.ftl", tc3); + assertApplicable(tcf, "a.ftlx", tc1, tc2); + assertApplicable(tcf, "b.ftlx", tc1, tc3); + assertApplicable(tcf, "ab.ftl", tc2, tc3); + assertApplicable(tcf, "ab.ftlx", tc1, tc2, tc3); + + assertNotApplicable(new MergingTemplateConfigurationFactory(), "x.ftl"); + } + + @Test + public void testFirstMatch() throws IOException, TemplateConfigurationFactoryException { + TemplateConfiguration tc1 = newTemplateConfiguration(1); + TemplateConfiguration tc2 = newTemplateConfiguration(2); + TemplateConfiguration tc3 = newTemplateConfiguration(3); + + FirstMatchTemplateConfigurationFactory tcf = new FirstMatchTemplateConfigurationFactory( + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.ftlx"), tc1), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*a*.*"), tc2), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*b*.*"), tc3)); + + try { + assertNotApplicable(tcf, "x.ftl"); + } catch (TemplateConfigurationFactoryException e) { + assertThat(e.getMessage(), containsString("x.ftl")); + } + tcf.setNoMatchErrorDetails("Test details"); + try { + assertNotApplicable(tcf, "x.ftl"); + } catch (TemplateConfigurationFactoryException e) { + assertThat(e.getMessage(), containsString("Test details")); + } + + tcf.setAllowNoMatch(true); + + assertNotApplicable(tcf, "x.ftl"); + assertApplicable(tcf, "x.ftlx", tc1); + assertApplicable(tcf, "a.ftl", tc2); + assertApplicable(tcf, "b.ftl", tc3); + assertApplicable(tcf, "a.ftlx", tc1); + assertApplicable(tcf, "b.ftlx", tc1); + assertApplicable(tcf, "ab.ftl", tc2); + assertApplicable(tcf, "ab.ftlx", tc1); + + assertNotApplicable(new FirstMatchTemplateConfigurationFactory().allowNoMatch(true), "x.ftl"); + } + + @Test + public void testComplex() throws IOException, TemplateConfigurationFactoryException { + TemplateConfiguration tcA = newTemplateConfiguration(1); + TemplateConfiguration tcBSpec = newTemplateConfiguration(2); + TemplateConfiguration tcBCommon = newTemplateConfiguration(3); + TemplateConfiguration tcHH = newTemplateConfiguration(4); + TemplateConfiguration tcHtml = newTemplateConfiguration(5); + TemplateConfiguration tcXml = newTemplateConfiguration(6); + TemplateConfiguration tcNWS = newTemplateConfiguration(7); + + TemplateConfigurationFactory tcf = new MergingTemplateConfigurationFactory( + new FirstMatchTemplateConfigurationFactory( + new ConditionalTemplateConfigurationFactory(new PathGlobMatcher("a/**"), tcA), + new ConditionalTemplateConfigurationFactory(new PathGlobMatcher("b/**"), + new MergingTemplateConfigurationFactory( + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*"), tcBCommon), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.s.*"), tcBSpec)))) + .allowNoMatch(true), + new FirstMatchTemplateConfigurationFactory( + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.hh"), tcHH), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.*h"), tcHtml), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.*x"), tcXml)) + .allowNoMatch(true), + new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.nws.*"), tcNWS)); + + assertNotApplicable(tcf, "x.ftl"); + assertApplicable(tcf, "b/x.ftl", tcBCommon); + assertApplicable(tcf, "b/x.s.ftl", tcBCommon, tcBSpec); + assertApplicable(tcf, "b/x.s.ftlh", tcBCommon, tcBSpec, tcHtml); + assertApplicable(tcf, "b/x.s.nws.ftlx", tcBCommon, tcBSpec, tcXml, tcNWS); + assertApplicable(tcf, "a/x.s.nws.ftlx", tcA, tcXml, tcNWS); + assertApplicable(tcf, "a.hh", tcHH); + assertApplicable(tcf, "a.nws.hh", tcHH, tcNWS); + } + + @SuppressWarnings("boxing") + private TemplateConfiguration newTemplateConfiguration(int id) { + TemplateConfiguration.Builder tcb = new TemplateConfiguration.Builder(); + tcb.setCustomAttribute("id", id); + tcb.setCustomAttribute("contains" + id, true); + return tcb.build(); + } + + private void assertNotApplicable(TemplateConfigurationFactory tcf, String sourceName) + throws IOException, TemplateConfigurationFactoryException { + assertNull(tcf.get(sourceName, DummyTemplateLoadingSource.INSTANCE)); + } + + private void assertApplicable(TemplateConfigurationFactory tcf, String sourceName, TemplateConfiguration... expectedTCs) + throws IOException, TemplateConfigurationFactoryException { + TemplateConfiguration mergedTC = tcf.get(sourceName, DummyTemplateLoadingSource.INSTANCE); + List<Object> mergedTCAttNames = new ArrayList<>(mergedTC.getCustomAttributes().keySet()); + + for (TemplateConfiguration expectedTC : expectedTCs) { + Integer tcId = (Integer) expectedTC.getCustomAttribute("id"); + if (tcId == null) { + fail("TemplateConfiguration-s must be created with newTemplateConfiguration(id) in this test"); + } + if (!mergedTCAttNames.contains("contains" + tcId)) { + fail("TemplateConfiguration with ID " + tcId + " is missing from the asserted value"); + } + } + + for (Object attKey: mergedTCAttNames) { + if (!containsCustomAttr(attKey, expectedTCs)) { + fail("The asserted TemplateConfiguration contains an unexpected custom attribute: " + attKey); + } + } + + assertEquals(expectedTCs[expectedTCs.length - 1].getCustomAttribute("id"), mergedTC.getCustomAttribute("id")); + } + + private boolean containsCustomAttr(Object attKey, TemplateConfiguration... expectedTCs) { + for (TemplateConfiguration expectedTC : expectedTCs) { + if (expectedTC.getCustomAttribute(attKey) != null) { + return true; + } + } + return false; + } + + @SuppressWarnings("serial") + private static class DummyTemplateLoadingSource implements TemplateLoadingSource { + private static DummyTemplateLoadingSource INSTANCE = new DummyTemplateLoadingSource(); + } + +}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/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 new file mode 100644 index 0000000..3a24bfc --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateNameFormatTest.java @@ -0,0 +1,330 @@ +/* + * 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.templateresolver; + +import static org.apache.freemarker.test.hamcerst.Matchers.*; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.Locale; + +import org.apache.freemarker.core.Configuration; +import org.apache.freemarker.core.Template; +import org.apache.freemarker.core.TemplateNotFoundException; +import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader; +import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormat; +import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormatFM2; +import org.apache.freemarker.test.MonitoredTemplateLoader; +import org.apache.freemarker.test.TestConfigurationBuilder; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + + +public class TemplateNameFormatTest { + + @Test + public void testToRootBasedName() throws MalformedTemplateNameException { + // Path that are treated the same both in 2.3 and 2.4 format: + for (TemplateNameFormat tnf : new TemplateNameFormat[] { + DefaultTemplateNameFormatFM2.INSTANCE, DefaultTemplateNameFormat.INSTANCE }) { + // Relative paths: + // - No scheme: + assertEquals("a/b", tnf.toRootBasedName("a/", "b")); + assertEquals("/a/b", tnf.toRootBasedName("/a/", "b")); + assertEquals("a/b", tnf.toRootBasedName("a/f", "b")); + assertEquals("/a/b", tnf.toRootBasedName("/a/f", "b")); + // - Scheme: + assertEquals("s://a/b", tnf.toRootBasedName("s://a/", "b")); + assertEquals("s:///a/b", tnf.toRootBasedName("s:///a/", "b")); + assertEquals("s://a/b", tnf.toRootBasedName("s://a/f", "b")); + assertEquals("s:///a/b", tnf.toRootBasedName("s:///a/f", "b")); + assertEquals("s://b", tnf.toRootBasedName("s://f", "b")); + assertEquals("s:///b", tnf.toRootBasedName("s:///f", "b")); + + // Absolute paths: + // - No scheme: + assertEquals("b", tnf.toRootBasedName("a/", "/b")); + assertEquals("b", tnf.toRootBasedName("/a/", "/b")); + assertEquals("b", tnf.toRootBasedName("a/s:/f/", "/b")); + // - Scheme: + assertEquals("s://b", tnf.toRootBasedName("s://x/", "/b")); + assertEquals("s://b", tnf.toRootBasedName("s:///x/", "/b")); + + // Schemed absolute paths: + assertEquals("s://b", tnf.toRootBasedName("a/", "s://b")); + assertEquals("s://b", tnf.toRootBasedName("i://a/", "s://b")); + } + + // Scheme names in 2.4 format only: + { + final TemplateNameFormat tnf = DefaultTemplateNameFormat.INSTANCE; + assertEquals("s:b", tnf.toRootBasedName("s:f", "b")); + assertEquals("s:/b", tnf.toRootBasedName("s:/f", "b")); + assertEquals("s:b", tnf.toRootBasedName("s:f", "/b")); + assertEquals("s:b", tnf.toRootBasedName("s:/f", "/b")); + assertEquals("s:f/b", tnf.toRootBasedName("s:f/", "b")); + assertEquals("s:/f/b", tnf.toRootBasedName("s:/f/", "b")); + assertEquals("s:b", tnf.toRootBasedName("s:f/", "/b")); + assertEquals("s:b", tnf.toRootBasedName("s:/f/", "/b")); + assertEquals("s:b", tnf.toRootBasedName("s:/f/", "/b")); + assertEquals("b", tnf.toRootBasedName("a/s://f/", "/b")); + } + + // Scheme names in 2.3 format only: + { + final TemplateNameFormat tnf = DefaultTemplateNameFormatFM2.INSTANCE; + assertEquals("a/s://b", tnf.toRootBasedName("a/s://f/", "/b")); + } + } + + @Test + public void testNormalizeRootBasedName() throws MalformedTemplateNameException { + // Normalizations that are the same in legacy and modern format: + for (TemplateNameFormat tnf : new TemplateNameFormat[] { + DefaultTemplateNameFormatFM2.INSTANCE, DefaultTemplateNameFormat.INSTANCE }) { + assertEquals("", tnf.normalizeRootBasedName("")); + for (String lead : new String[] { "", "/" }) { + assertEquals("foo", tnf.normalizeRootBasedName(lead + "foo")); + assertEquals("foo", tnf.normalizeRootBasedName(lead + "./foo")); + assertEquals("foo", tnf.normalizeRootBasedName(lead + "./././foo")); + assertEquals("foo", tnf.normalizeRootBasedName(lead + "bar/../foo")); + assertEquals("a/b/", tnf.normalizeRootBasedName("a/b/")); + assertEquals("a/", tnf.normalizeRootBasedName("a/b/../")); + assertEquals("a/c../..d/e*/*f", tnf.normalizeRootBasedName("a/c../..d/e*/*f")); + assertEquals("", tnf.normalizeRootBasedName("")); + assertEquals("foo/bar/*", tnf.normalizeRootBasedName("foo/bar/*")); + assertEquals("schema://", tnf.normalizeRootBasedName("schema://")); + + assertThrowsWithBackingOutException(lead + "bar/../../x/foo", tnf); + assertThrowsWithBackingOutException(lead + "../x", tnf); + assertThrowsWithBackingOutException(lead + "../../../x", tnf); + assertThrowsWithBackingOutException(lead + "../../../x", tnf); + assertThrowsWithBackingOutException("x://../../../foo", tnf); + + { + final String name = lead + "foo\u0000"; + try { + tnf.normalizeRootBasedName(name); + fail(); + } catch (MalformedTemplateNameException e) { + assertEquals(name, e.getTemplateName()); + + assertThat(e.getMalformednessDescription(), containsStringIgnoringCase("null character")); + } + } + } + } + + // ".." and "." + assertEqualsOn23AndOn24("bar/foo", "foo", "bar/./../foo"); + + // Even number of leading ".."-s bug: + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("foo", "../../foo"); + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("foo", "../../../../foo"); + + // ".." and "*" + assertEqualsOn23AndOn24("a/b/foo", "a/*/foo", "a/b/*/../foo"); + // + assertEqualsOn23AndOn24("a/foo", "foo", "a/b/*/../../foo"); + // + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("foo", "a/b/*/../../../foo"); + // + assertEqualsOn23AndOn24("a/b/*/foo", "a/*/foo", "a/b/*/*/../foo"); + // + assertEqualsOn23AndOn24("a/b/*/c/foo", "a/b/*/foo", "a/b/*/c/*/../foo"); + // + assertEqualsOn23AndOn24("a/b/*/c/foo", "a/b/*/foo", "a/b/*/c/d/*/../../foo"); + // + assertEqualsOn23AndOn24("a/*//b/*/c/foo", "a/*/b/*/foo", "a/*//b/*/c/d/*/../../foo"); + // + assertEqualsOn23AndOn24("*", "", "a/../*"); + // + assertEqualsOn23AndOn24("*/", "", "a/../*/"); + + // ".." and "scheme" + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("x:/foo", "x://../foo"); + // + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("foo", "x://../../foo"); + // + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("x:../foo", "x:../foo"); + // + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("foo", "x:../../foo"); + + // Tricky cases with terminating "/": + assertEqualsOn23AndOn24("/", "", "/"); + // Terminating "/.." (produces terminating "/"): + assertEqualsOn23AndOn24("foo/bar/..", "foo/", "foo/bar/.."); + // Terminating "/." (produces terminating "/"): + assertEqualsOn23AndOn24("foo/bar/.", "foo/bar/", "foo/bar/."); + + // Lonely "." + assertEqualsOn23AndOn24(".", "", "."); + // Lonely ".." + assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24("..", ".."); + // Lonely "*" + + // Eliminating redundant "//": + assertEqualsOn23AndOn24("foo//bar", "foo/bar", "foo//bar"); + // + assertEqualsOn23AndOn24("///foo//bar///baaz////wombat", "foo/bar/baaz/wombat", "////foo//bar///baaz////wombat"); + // + assertEqualsOn23AndOn24("scheme://foo", "scheme://foo", "scheme://foo"); + // + assertEqualsOn23AndOn24("scheme://foo//x/y", "scheme://foo/x/y", "scheme://foo//x/y"); + // + assertEqualsOn23AndOn24("scheme:///foo", "scheme://foo", "scheme:///foo"); + // + assertEqualsOn23AndOn24("scheme:////foo", "scheme://foo", "scheme:////foo"); + + // Eliminating redundant "*"-s: + assertEqualsOn23AndOn24("a/*/*/b", "a/*/b", "a/*/*/b"); + // + assertEqualsOn23AndOn24("a/*/*/*/b", "a/*/b", "a/*/*/*/b"); + // + assertEqualsOn23AndOn24("*/*/b", "b", "*/*/b"); + // + assertEqualsOn23AndOn24("*/*/b", "b", "/*/*/b"); + // + assertEqualsOn23AndOn24("b/*/*", "b/*", "b/*/*"); + // + assertEqualsOn23AndOn24("b/*/*/*", "b/*", "b/*/*/*"); + // + assertEqualsOn23AndOn24("*/a/*/b/*/*/c", "a/*/b/*/c", "*/a/*/b/*/*/c"); + + // New kind of scheme handling: + + assertEquals("s:a/b", DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName("s:a/b")); + assertEquals("s:a/b", DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName("s:/a/b")); + assertEquals("s://a/b", DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName("s://a/b")); + assertEquals("s://a/b", DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName("s:///a/b")); + assertEquals("s://a/b", DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName("s:////a/b")); + + // Illegal use a of ":": + assertNormRBNameThrowsColonExceptionOn24("a/b:c/d"); + assertNormRBNameThrowsColonExceptionOn24("a/b:/.."); + } + + @Test + public void assertBackslashNotSpecialWith23() throws IOException { + MonitoredTemplateLoader tl = new MonitoredTemplateLoader(); + tl.putTextTemplate("foo\\bar.ftl", ""); + + Configuration cfg = new TestConfigurationBuilder().templateLoader(tl).build(); + + { + final String name = "foo\\bar.ftl"; + + Template t = cfg.getTemplate(name, Locale.US); + assertEquals(name, t.getLookupName()); + assertEquals(name, t.getSourceName()); + assertEquals( + ImmutableList.of( + "foo\\bar_en_US.ftl", + "foo\\bar_en.ftl", + name), + tl.getLoadNames()); + tl.clearEvents(); + } + + try { + cfg.getTemplate("foo\\missing.ftl", Locale.US); + fail(); + } catch (TemplateNotFoundException e) { + assertEquals("foo\\missing.ftl", e.getTemplateName()); + assertEquals( + ImmutableList.of( + "foo\\missing_en_US.ftl", + "foo\\missing_en.ftl", + "foo\\missing.ftl"), + tl.getLoadNames()); + tl.clearEvents(); + cfg.clearTemplateCache(); + } + + { + final String name = "foo/bar\\..\\bar.ftl"; + try { + cfg.getTemplate(name, Locale.US); + fail(); + } catch (TemplateNotFoundException e) { + assertEquals(name, e.getTemplateName()); + } + } + + } + + @Test + public void assertBackslashNotAllowed() throws IOException { + Configuration cfg = new TestConfigurationBuilder() + .templateLoader(new ByteArrayTemplateLoader()) + .templateNameFormat(DefaultTemplateNameFormat.INSTANCE) + .build(); + try { + cfg.getTemplate("././foo\\bar.ftl", Locale.US); + fail(); + } catch (MalformedTemplateNameException e) { + assertThat(e.getMessage(), containsStringIgnoringCase("backslash")); + } + + } + + private void assertEqualsOn23AndOn24(String expected23, String expected24, String name) + throws MalformedTemplateNameException { + assertEquals(expected23, DefaultTemplateNameFormatFM2.INSTANCE.normalizeRootBasedName(name)); + assertEquals(expected24, DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName(name)); + } + + private void assertNormRBNameEqualsOn23ButThrowsBackOutExcOn24(final String expected23, final String name) + throws MalformedTemplateNameException { + assertEquals(expected23, DefaultTemplateNameFormatFM2.INSTANCE.normalizeRootBasedName(name)); + assertThrowsWithBackingOutException(name, DefaultTemplateNameFormat.INSTANCE); + } + + private void assertThrowsWithBackingOutException(final String name, final TemplateNameFormat tnf) { + try { + tnf.normalizeRootBasedName(name); + fail(); + } catch (MalformedTemplateNameException e) { + assertEquals(name, e.getTemplateName()); + assertBackingOutFromRootException(e); + } + } + + private void assertNormRBNameThrowsColonExceptionOn24(final String name) throws MalformedTemplateNameException { + try { + DefaultTemplateNameFormat.INSTANCE.normalizeRootBasedName(name); + fail(); + } catch (MalformedTemplateNameException e) { + assertEquals(name, e.getTemplateName()); + assertColonException(e); + } + } + + private void assertBackingOutFromRootException(MalformedTemplateNameException e) { + assertThat(e.getMessage(), containsStringIgnoringCase("backing out")); + } + + private void assertColonException(MalformedTemplateNameException e) { + assertThat(e.getMessage(), containsString("':'")); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateSourceMatcherTest.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateSourceMatcherTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateSourceMatcherTest.java new file mode 100644 index 0000000..51273c0 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/templateresolver/TemplateSourceMatcherTest.java @@ -0,0 +1,188 @@ +/* + * 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.templateresolver; + +import static org.junit.Assert.*; + +import java.io.IOException; + +import org.junit.Test; + +public class TemplateSourceMatcherTest { + + @Test + public void testPathGlobMatcher() throws IOException { + PathGlobMatcher m = new PathGlobMatcher("**/a/?.ftl"); + assertTrue(m.matches("a/b.ftl", "dummy")); + assertTrue(m.matches("x/a/c.ftl", "dummy")); + assertFalse(m.matches("a/b.Ftl", "dummy")); + assertFalse(m.matches("b.ftl", "dummy")); + assertFalse(m.matches("a/bc.ftl", "dummy")); + + m = new PathGlobMatcher("**/a/?.ftl").caseInsensitive(true); + assertTrue(m.matches("A/B.FTL", "dummy")); + m.setCaseInsensitive(false); + assertFalse(m.matches("A/B.FTL", "dummy")); + + try { + new PathGlobMatcher("/b.ftl"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void testFileNameGlobMatcher() throws IOException { + FileNameGlobMatcher m = new FileNameGlobMatcher("a*.ftl"); + assertTrue(m.matches("ab.ftl", "dummy")); + assertTrue(m.matches("dir/ab.ftl", "dummy")); + assertTrue(m.matches("/dir/dir/ab.ftl", "dummy")); + assertFalse(m.matches("Ab.ftl", "dummy")); + assertFalse(m.matches("bb.ftl", "dummy")); + assertFalse(m.matches("ab.ftl/x", "dummy")); + + m = new FileNameGlobMatcher("a*.ftl").caseInsensitive(true); + assertTrue(m.matches("AB.FTL", "dummy")); + m.setCaseInsensitive(false); + assertFalse(m.matches("AB.FTL", "dummy")); + + m = new FileNameGlobMatcher("\u00E1*.ftl").caseInsensitive(true); + assertTrue(m.matches("\u00C1b.ftl", "dummy")); + + try { + new FileNameGlobMatcher("dir/a*.ftl"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void testFileExtensionMatcher() throws IOException { + FileExtensionMatcher m = new FileExtensionMatcher("ftlx"); + assertTrue(m.matches("a.ftlx", "dummy")); + assertTrue(m.matches(".ftlx", "dummy")); + assertTrue(m.matches("b/a.b.ftlx", "dummy")); + assertTrue(m.matches("b/a.ftlx", "dummy")); + assertTrue(m.matches("c.b/a.ftlx", "dummy")); + assertFalse(m.matches("a.ftl", "dummy")); + assertFalse(m.matches("ftlx", "dummy")); + assertFalse(m.matches("b.ftlx/a.ftl", "dummy")); + + assertTrue(m.isCaseInsensitive()); + assertTrue(m.matches("a.fTlX", "dummy")); + m.setCaseInsensitive(false); + assertFalse(m.matches("a.fTlX", "dummy")); + assertTrue(m.matches("A.ftlx", "dummy")); + + m = new FileExtensionMatcher(""); + assertTrue(m.matches("a.", "dummy")); + assertTrue(m.matches(".", "dummy")); + assertFalse(m.matches("a", "dummy")); + assertFalse(m.matches("", "dummy")); + assertFalse(m.matches("a.x", "dummy")); + + m = new FileExtensionMatcher("html.t"); + assertTrue(m.matches("a.html.t", "dummy")); + assertFalse(m.matches("a.xhtml.t", "dummy")); + assertFalse(m.matches("a.html", "dummy")); + assertFalse(m.matches("a.t", "dummy")); + + try { + new FileExtensionMatcher("*.ftlx"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + try { + new FileExtensionMatcher("ftl?"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + try { + new FileExtensionMatcher(".ftlx"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + try { + new FileExtensionMatcher("dir/a.ftl"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void testPathRegexMatcher() throws IOException { + PathRegexMatcher m = new PathRegexMatcher("a/[a-z]+\\.ftl"); + assertTrue(m.matches("a/b.ftl", "dummy")); + assertTrue(m.matches("a/abc.ftl", "dummy")); + assertFalse(m.matches("b.ftl", "dummy")); + assertFalse(m.matches("b/b.ftl", "dummy")); + + try { + new PathRegexMatcher("/b.ftl"); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void testAndMatcher() throws IOException { + AndMatcher m = new AndMatcher(new PathGlobMatcher("a*.*"), new PathGlobMatcher("*.t")); + assertTrue(m.matches("ab.t", "dummy")); + assertFalse(m.matches("bc.t", "dummy")); + assertFalse(m.matches("ab.ftl", "dummy")); + + try { + new AndMatcher(); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void testOrMatcher() throws IOException { + OrMatcher m = new OrMatcher(new PathGlobMatcher("a*.*"), new PathGlobMatcher("*.t")); + assertTrue(m.matches("ab.t", "dummy")); + assertTrue(m.matches("bc.t", "dummy")); + assertTrue(m.matches("ab.ftl", "dummy")); + assertFalse(m.matches("bc.ftl", "dummy")); + + try { + new OrMatcher(); + fail(); + } catch (IllegalArgumentException e) { + // Expected + } + } + + @Test + public void testNotMatcher() throws IOException { + NotMatcher m = new NotMatcher(new PathGlobMatcher("a*.*")); + assertFalse(m.matches("ab.t", "dummy")); + assertTrue(m.matches("bc.t", "dummy")); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AppMetaTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AppMetaTemplateDateFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AppMetaTemplateDateFormatFactory.java new file mode 100644 index 0000000..1d69dd8 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/AppMetaTemplateDateFormatFactory.java @@ -0,0 +1,129 @@ +/* + * 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.userpkg; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.UnformattableValueException; +import org.apache.freemarker.core.valueformat.UnknownDateTypeFormattingUnsupportedException; +import org.apache.freemarker.core.valueformat.UnparsableValueException; + +public class AppMetaTemplateDateFormatFactory extends TemplateDateFormatFactory { + + public static final AppMetaTemplateDateFormatFactory INSTANCE = new AppMetaTemplateDateFormatFactory(); + + private AppMetaTemplateDateFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, + Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { + TemplateFormatUtil.checkHasNoParameters(params); + return AppMetaTemplateDateFormat.INSTANCE; + } + + private static class AppMetaTemplateDateFormat extends TemplateDateFormat { + + private static final AppMetaTemplateDateFormat INSTANCE = new AppMetaTemplateDateFormat(); + + private AppMetaTemplateDateFormat() { } + + @Override + public String formatToPlainText(TemplateDateModel dateModel) + throws UnformattableValueException, TemplateModelException { + String result = String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime()); + if (dateModel instanceof AppMetaTemplateDateModel) { + result += "/" + ((AppMetaTemplateDateModel) dateModel).getAppMeta(); + } + return result; + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + public boolean isTimeZoneBound() { + return false; + } + + @Override + public Object parse(String s, int dateType) throws UnparsableValueException { + int slashIdx = s.indexOf('/'); + try { + if (slashIdx != -1) { + return new AppMetaTemplateDateModel( + new Date(Long.parseLong(s.substring(0, slashIdx))), + dateType, + s.substring(slashIdx +1)); + } else { + return new Date(Long.parseLong(s)); + } + } catch (NumberFormatException e) { + throw new UnparsableValueException("Malformed long"); + } + } + + @Override + public String getDescription() { + return "millis since the epoch"; + } + + } + + public static class AppMetaTemplateDateModel implements TemplateDateModel { + + private final Date date; + private final int dateType; + private final String appMeta; + + public AppMetaTemplateDateModel(Date date, int dateType, String appMeta) { + this.date = date; + this.dateType = dateType; + this.appMeta = appMeta; + } + + @Override + public Date getAsDate() throws TemplateModelException { + return date; + } + + @Override + public int getDateType() { + return dateType; + } + + public String getAppMeta() { + return appMeta; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/BaseNTemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/BaseNTemplateNumberFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/BaseNTemplateNumberFormatFactory.java new file mode 100644 index 0000000..e5def77 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/BaseNTemplateNumberFormatFactory.java @@ -0,0 +1,128 @@ +/* + * 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.userpkg; + +import java.util.Locale; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.util._NumberUtil; +import org.apache.freemarker.core.util._StringUtil; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.TemplateNumberFormat; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateValueFormatException; +import org.apache.freemarker.core.valueformat.UnformattableValueException; + +/** + * Shows a number in base N number system. Can only format numbers that fit into an {@code int}, + * however, optionally you can specify a fallback format. This format has one required parameter, + * the numerical system base. That can be optionally followed by "|" and a fallback format. + */ +public class BaseNTemplateNumberFormatFactory extends TemplateNumberFormatFactory { + + public static final BaseNTemplateNumberFormatFactory INSTANCE + = new BaseNTemplateNumberFormatFactory(); + + private BaseNTemplateNumberFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateNumberFormat get(String params, Locale locale, Environment env) + throws InvalidFormatParametersException { + TemplateNumberFormat fallbackFormat; + { + int barIdx = params.indexOf('|'); + if (barIdx != -1) { + String fallbackFormatStr = params.substring(barIdx + 1); + params = params.substring(0, barIdx); + try { + fallbackFormat = env.getTemplateNumberFormat(fallbackFormatStr, locale); + } catch (TemplateValueFormatException e) { + throw new InvalidFormatParametersException( + "Couldn't get the fallback number format (specified after the \"|\"), " + + _StringUtil.jQuote(fallbackFormatStr) + ". Reason: " + e.getMessage(), + e); + } + } else { + fallbackFormat = null; + } + } + + int base; + try { + base = Integer.parseInt(params); + } catch (NumberFormatException e) { + if (params.length() == 0) { + throw new InvalidFormatParametersException( + "A format parameter is required to specify the numerical system base."); + } + throw new InvalidFormatParametersException( + "The format paramter must be an integer, but was (shown quoted): " + + _StringUtil.jQuote(params)); + } + if (base < 2) { + throw new InvalidFormatParametersException("A base must be at least 2."); + } + return new BaseNTemplateNumberFormat(base, fallbackFormat); + } + + private static class BaseNTemplateNumberFormat extends TemplateNumberFormat { + + private final int base; + private final TemplateNumberFormat fallbackFormat; + + private BaseNTemplateNumberFormat(int base, TemplateNumberFormat fallbackFormat) { + this.base = base; + this.fallbackFormat = fallbackFormat; + } + + @Override + public String formatToPlainText(TemplateNumberModel numberModel) + throws TemplateModelException, TemplateValueFormatException { + Number n = TemplateFormatUtil.getNonNullNumber(numberModel); + try { + return Integer.toString(_NumberUtil.toIntExact(n), base); + } catch (ArithmeticException e) { + if (fallbackFormat == null) { + throw new UnformattableValueException( + n + " doesn't fit into an int, and there was no fallback format " + + "specified."); + } else { + return fallbackFormat.formatToPlainText(numberModel); + } + } + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + public String getDescription() { + return "base " + base; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomHTMLOutputFormat.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomHTMLOutputFormat.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomHTMLOutputFormat.java new file mode 100644 index 0000000..f570a66 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomHTMLOutputFormat.java @@ -0,0 +1,72 @@ +/* + * 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.userpkg; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat; +import org.apache.freemarker.core.util._StringUtil; + +/** + * Represents the HTML output format. + * + * @since 2.3.24 + */ +public final class CustomHTMLOutputFormat extends CommonMarkupOutputFormat<CustomTemplateHTMLModel> { + + public static final CustomHTMLOutputFormat INSTANCE = new CustomHTMLOutputFormat(); + + private CustomHTMLOutputFormat() { + // Only to decrease visibility + } + + @Override + public String getName() { + return "HTML"; + } + + @Override + public String getMimeType() { + return "text/html"; + } + + @Override + public void output(String textToEsc, Writer out) throws IOException, TemplateModelException { + // This is lazy - don't do it in reality. + out.write(escapePlainText(textToEsc)); + } + + @Override + public String escapePlainText(String plainTextContent) { + return _StringUtil.XHTMLEnc(plainTextContent.replace('x', 'X')); + } + + @Override + public boolean isLegacyBuiltInBypassed(String builtInName) { + return builtInName.equals("html") || builtInName.equals("xml") || builtInName.equals("xhtml"); + } + + @Override + protected CustomTemplateHTMLModel newTemplateMarkupOutputModel(String plainTextContent, String markupContent) { + return new CustomTemplateHTMLModel(plainTextContent, markupContent); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomTemplateHTMLModel.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomTemplateHTMLModel.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomTemplateHTMLModel.java new file mode 100644 index 0000000..4cc67be --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/CustomTemplateHTMLModel.java @@ -0,0 +1,34 @@ +/* + * 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.userpkg; + +import org.apache.freemarker.core.outputformat.CommonTemplateMarkupOutputModel; + +public final class CustomTemplateHTMLModel extends CommonTemplateMarkupOutputModel<CustomTemplateHTMLModel> { + + CustomTemplateHTMLModel(String plainTextContent, String markupContent) { + super(plainTextContent, markupContent); + } + + @Override + public CustomHTMLOutputFormat getOutputFormat() { + return CustomHTMLOutputFormat.INSTANCE; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/DummyOutputFormat.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/DummyOutputFormat.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/DummyOutputFormat.java new file mode 100644 index 0000000..f368969 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/DummyOutputFormat.java @@ -0,0 +1,65 @@ +/* + * 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.userpkg; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat.CommonMarkupOutputFormat; + +public class DummyOutputFormat extends CommonMarkupOutputFormat<TemplateDummyOutputModel> { + + public static final DummyOutputFormat INSTANCE = new DummyOutputFormat(); + + private DummyOutputFormat() { + // hide + } + + @Override + public String getName() { + return "dummy"; + } + + @Override + public String getMimeType() { + return "text/dummy"; + } + + @Override + public void output(String textToEsc, Writer out) throws IOException, TemplateModelException { + out.write(escapePlainText(textToEsc)); + } + + @Override + public String escapePlainText(String plainTextContent) { + return plainTextContent.replaceAll("(\\.|\\\\)", "\\\\$1"); + } + + @Override + public boolean isLegacyBuiltInBypassed(String builtInName) { + return false; + } + + @Override + protected TemplateDummyOutputModel newTemplateMarkupOutputModel(String plainTextContent, String markupContent) { + return new TemplateDummyOutputModel(plainTextContent, markupContent); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisDivTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisDivTemplateDateFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisDivTemplateDateFormatFactory.java new file mode 100644 index 0000000..8799eef --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisDivTemplateDateFormatFactory.java @@ -0,0 +1,102 @@ +/* + * 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.userpkg; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.util._StringUtil; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.UnformattableValueException; +import org.apache.freemarker.core.valueformat.UnknownDateTypeFormattingUnsupportedException; +import org.apache.freemarker.core.valueformat.UnparsableValueException; + +public class EpochMillisDivTemplateDateFormatFactory extends TemplateDateFormatFactory { + + public static final EpochMillisDivTemplateDateFormatFactory INSTANCE = new EpochMillisDivTemplateDateFormatFactory(); + + private EpochMillisDivTemplateDateFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, + Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { + int divisor; + try { + divisor = Integer.parseInt(params); + } catch (NumberFormatException e) { + if (params.length() == 0) { + throw new InvalidFormatParametersException( + "A format parameter is required, which specifies the divisor."); + } + throw new InvalidFormatParametersException( + "The format paramter must be an integer, but was (shown quoted): " + _StringUtil.jQuote(params)); + } + return new EpochMillisDivTemplateDateFormat(divisor); + } + + private static class EpochMillisDivTemplateDateFormat extends TemplateDateFormat { + + private final int divisor; + + private EpochMillisDivTemplateDateFormat(int divisor) { + this.divisor = divisor; + } + + @Override + public String formatToPlainText(TemplateDateModel dateModel) + throws UnformattableValueException, TemplateModelException { + return String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime() / divisor); + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + public boolean isTimeZoneBound() { + return false; + } + + @Override + public Date parse(String s, int dateType) throws UnparsableValueException { + try { + return new Date(Long.parseLong(s)); + } catch (NumberFormatException e) { + throw new UnparsableValueException("Malformed long"); + } + } + + @Override + public String getDescription() { + return "millis since the epoch"; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisTemplateDateFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisTemplateDateFormatFactory.java new file mode 100644 index 0000000..9f27095 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/EpochMillisTemplateDateFormatFactory.java @@ -0,0 +1,92 @@ +/* + * 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.userpkg; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.UnformattableValueException; +import org.apache.freemarker.core.valueformat.UnparsableValueException; + +public class EpochMillisTemplateDateFormatFactory extends TemplateDateFormatFactory { + + public static final EpochMillisTemplateDateFormatFactory INSTANCE + = new EpochMillisTemplateDateFormatFactory(); + + private EpochMillisTemplateDateFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateDateFormat get(String params, int dateType, + Locale locale, TimeZone timeZone, boolean zonelessInput, + Environment env) + throws InvalidFormatParametersException { + TemplateFormatUtil.checkHasNoParameters(params); + return EpochMillisTemplateDateFormat.INSTANCE; + } + + private static class EpochMillisTemplateDateFormat extends TemplateDateFormat { + + private static final EpochMillisTemplateDateFormat INSTANCE + = new EpochMillisTemplateDateFormat(); + + private EpochMillisTemplateDateFormat() { } + + @Override + public String formatToPlainText(TemplateDateModel dateModel) + throws UnformattableValueException, TemplateModelException { + return String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime()); + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + public boolean isTimeZoneBound() { + return false; + } + + @Override + public Date parse(String s, int dateType) throws UnparsableValueException { + try { + return new Date(Long.parseLong(s)); + } catch (NumberFormatException e) { + throw new UnparsableValueException("Malformed long"); + } + } + + @Override + public String getDescription() { + return "millis since the epoch"; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java new file mode 100644 index 0000000..357034c --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HTMLISOTemplateDateFormatFactory.java @@ -0,0 +1,114 @@ +/* + * 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.userpkg; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat; +import org.apache.freemarker.core.util._DateUtil; +import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter; +import org.apache.freemarker.core.util._DateUtil.DateParseException; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.TemplateValueFormatException; +import org.apache.freemarker.core.valueformat.UnformattableValueException; +import org.apache.freemarker.core.valueformat.UnknownDateTypeFormattingUnsupportedException; +import org.apache.freemarker.core.valueformat.UnparsableValueException; + +public class HTMLISOTemplateDateFormatFactory extends TemplateDateFormatFactory { + + public static final HTMLISOTemplateDateFormatFactory INSTANCE = new HTMLISOTemplateDateFormatFactory(); + + private HTMLISOTemplateDateFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, + Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { + TemplateFormatUtil.checkHasNoParameters(params); + return HTMLISOTemplateDateFormat.INSTANCE; + } + + private static class HTMLISOTemplateDateFormat extends TemplateDateFormat { + + private static final HTMLISOTemplateDateFormat INSTANCE = new HTMLISOTemplateDateFormat(); + + private _DateUtil.TrivialDateToISO8601CalendarFactory calendarFactory; + + private CalendarFieldsToDateConverter calToDateConverter; + + private HTMLISOTemplateDateFormat() { } + + @Override + public String formatToPlainText(TemplateDateModel dateModel) + throws UnformattableValueException, TemplateModelException { + if (calendarFactory == null) { + calendarFactory = new _DateUtil.TrivialDateToISO8601CalendarFactory(); + } + return _DateUtil.dateToISO8601String( + TemplateFormatUtil.getNonNullDate(dateModel), + true, true, true, _DateUtil.ACCURACY_SECONDS, _DateUtil.UTC, + calendarFactory); + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + public boolean isTimeZoneBound() { + return false; + } + + @Override + public Date parse(String s, int dateType) throws UnparsableValueException { + try { + if (calToDateConverter == null) { + calToDateConverter = new _DateUtil.TrivialCalendarFieldsToDateConverter(); + } + return _DateUtil.parseISO8601DateTime(s, _DateUtil.UTC, calToDateConverter); + } catch (DateParseException e) { + throw new UnparsableValueException("Malformed ISO date-time", e); + } + } + + @Override + public Object format(TemplateDateModel dateModel) throws TemplateValueFormatException, TemplateModelException { + return HTMLOutputFormat.INSTANCE.fromMarkup( + formatToPlainText(dateModel).replace("T", "<span class='T'>T</span>")); + } + + @Override + public String getDescription() { + return "ISO UTC HTML"; + } + + } + +} + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java new file mode 100644 index 0000000..6d72c20 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/HexTemplateNumberFormatFactory.java @@ -0,0 +1,77 @@ +/* + * 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.userpkg; + +import java.util.Locale; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.util._NumberUtil; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.TemplateNumberFormat; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; +import org.apache.freemarker.core.valueformat.UnformattableValueException; + +public class HexTemplateNumberFormatFactory extends TemplateNumberFormatFactory { + + public static final HexTemplateNumberFormatFactory INSTANCE = new HexTemplateNumberFormatFactory(); + + private HexTemplateNumberFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateNumberFormat get(String params, Locale locale, Environment env) + throws InvalidFormatParametersException { + TemplateFormatUtil.checkHasNoParameters(params); + return HexTemplateNumberFormat.INSTANCE; + } + + private static class HexTemplateNumberFormat extends TemplateNumberFormat { + + private static final HexTemplateNumberFormat INSTANCE = new HexTemplateNumberFormat(); + + private HexTemplateNumberFormat() { } + + @Override + public String formatToPlainText(TemplateNumberModel numberModel) + throws UnformattableValueException, TemplateModelException { + Number n = TemplateFormatUtil.getNonNullNumber(numberModel); + try { + return Integer.toHexString(_NumberUtil.toIntExact(n)); + } catch (ArithmeticException e) { + throw new UnformattableValueException(n + " doesn't fit into an int"); + } + } + + @Override + public boolean isLocaleBound() { + return false; + } + + @Override + public String getDescription() { + return "hexadecimal int"; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java new file mode 100644 index 0000000..42b0401 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocAndTZSensitiveTemplateDateFormatFactory.java @@ -0,0 +1,97 @@ +/* + * 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.userpkg; + +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateDateModel; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateDateFormat; +import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.UnformattableValueException; +import org.apache.freemarker.core.valueformat.UnknownDateTypeFormattingUnsupportedException; +import org.apache.freemarker.core.valueformat.UnparsableValueException; + +public class LocAndTZSensitiveTemplateDateFormatFactory extends TemplateDateFormatFactory { + + public static final LocAndTZSensitiveTemplateDateFormatFactory INSTANCE = new LocAndTZSensitiveTemplateDateFormatFactory(); + + private LocAndTZSensitiveTemplateDateFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateDateFormat get(String params, int dateType, Locale locale, TimeZone timeZone, boolean zonelessInput, + Environment env) throws UnknownDateTypeFormattingUnsupportedException, InvalidFormatParametersException { + TemplateFormatUtil.checkHasNoParameters(params); + return new LocAndTZSensitiveTemplateDateFormat(locale, timeZone); + } + + private static class LocAndTZSensitiveTemplateDateFormat extends TemplateDateFormat { + + private final Locale locale; + private final TimeZone timeZone; + + public LocAndTZSensitiveTemplateDateFormat(Locale locale, TimeZone timeZone) { + this.locale = locale; + this.timeZone = timeZone; + } + + @Override + public String formatToPlainText(TemplateDateModel dateModel) + throws UnformattableValueException, TemplateModelException { + return String.valueOf(TemplateFormatUtil.getNonNullDate(dateModel).getTime() + "@" + locale + ":" + timeZone.getID()); + } + + @Override + public boolean isLocaleBound() { + return true; + } + + @Override + public boolean isTimeZoneBound() { + return true; + } + + @Override + public Date parse(String s, int dateType) throws UnparsableValueException { + try { + int atIdx = s.indexOf("@"); + if (atIdx == -1) { + throw new UnparsableValueException("Missing @"); + } + return new Date(Long.parseLong(s.substring(0, atIdx))); + } catch (NumberFormatException e) { + throw new UnparsableValueException("Malformed long"); + } + } + + @Override + public String getDescription() { + return "millis since the epoch"; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java new file mode 100644 index 0000000..dc3dae0 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/LocaleSensitiveTemplateNumberFormatFactory.java @@ -0,0 +1,78 @@ +/* + * 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.userpkg; + +import java.util.Locale; + +import org.apache.freemarker.core.Environment; +import org.apache.freemarker.core.model.TemplateModelException; +import org.apache.freemarker.core.model.TemplateNumberModel; +import org.apache.freemarker.core.valueformat.InvalidFormatParametersException; +import org.apache.freemarker.core.valueformat.TemplateFormatUtil; +import org.apache.freemarker.core.valueformat.TemplateNumberFormat; +import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; +import org.apache.freemarker.core.valueformat.UnformattableValueException; + +public class LocaleSensitiveTemplateNumberFormatFactory extends TemplateNumberFormatFactory { + + public static final LocaleSensitiveTemplateNumberFormatFactory INSTANCE = new LocaleSensitiveTemplateNumberFormatFactory(); + + private LocaleSensitiveTemplateNumberFormatFactory() { + // Defined to decrease visibility + } + + @Override + public TemplateNumberFormat get(String params, Locale locale, Environment env) + throws InvalidFormatParametersException { + TemplateFormatUtil.checkHasNoParameters(params); + return new LocaleSensitiveTemplateNumberFormat(locale); + } + + private static class LocaleSensitiveTemplateNumberFormat extends TemplateNumberFormat { + + private final Locale locale; + + private LocaleSensitiveTemplateNumberFormat(Locale locale) { + this.locale = locale; + } + + @Override + public String formatToPlainText(TemplateNumberModel numberModel) + throws UnformattableValueException, TemplateModelException { + Number n = numberModel.getAsNumber(); + try { + return n + "_" + locale; + } catch (ArithmeticException e) { + throw new UnformattableValueException(n + " doesn't fit into an int"); + } + } + + @Override + public boolean isLocaleBound() { + return true; + } + + @Override + public String getDescription() { + return "test locale sensitive"; + } + + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java new file mode 100644 index 0000000..f3ebc72 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAll.java @@ -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. + */ + +package org.apache.freemarker.core.userpkg; + +class PackageVisibleAll { + + PackageVisibleAll() {} + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java new file mode 100644 index 0000000..53a89d4 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilder.java @@ -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. + */ + +package org.apache.freemarker.core.userpkg; + +class PackageVisibleAllWithBuilder { + + PackageVisibleAllWithBuilder() {} + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java new file mode 100644 index 0000000..510ecc2 --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleAllWithBuilderBuilder.java @@ -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. + */ + +package org.apache.freemarker.core.userpkg; + +public class PackageVisibleAllWithBuilderBuilder { + + public PackageVisibleAllWithBuilder build() { + return new PackageVisibleAllWithBuilder(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/28a276c8/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java ---------------------------------------------------------------------- diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java new file mode 100644 index 0000000..836e80d --- /dev/null +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/PackageVisibleWithPublicConstructor.java @@ -0,0 +1,27 @@ +/* + * 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.userpkg; + +class PackageVisibleWithPublicConstructor { + + public PackageVisibleWithPublicConstructor() { + } + +}
