You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2017/06/10 17:59:26 UTC
incubator-freemarker git commit: Added protected
getImpliedRegisteredCustomOutputFormats() as well,
and some cleanup around the customOutputFormats setting.
Repository: incubator-freemarker
Updated Branches:
refs/heads/3 164f292ef -> bd1c4c40d
Added protected getImpliedRegisteredCustomOutputFormats() as well, and some cleanup around the customOutputFormats setting.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/bd1c4c40
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/bd1c4c40
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/bd1c4c40
Branch: refs/heads/3
Commit: bd1c4c40d828a87cd23733e948ec2edcb96b0444
Parents: 164f292
Author: ddekany <dd...@apache.org>
Authored: Sat Jun 10 19:58:49 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Sat Jun 10 19:58:49 2017 +0200
----------------------------------------------------------------------
.../freemarker/core/ConfigurationTest.java | 33 ++++++-
.../userpkg/NameClashingDummyOutputFormat.java | 65 +++++++++++++
.../apache/freemarker/core/Configuration.java | 97 +++++++++++++-------
.../freemarker/core/TopLevelConfiguration.java | 33 +++++++
4 files changed, 191 insertions(+), 37 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bd1c4c40/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
index 7cf205f..ae9bd74 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java
@@ -76,6 +76,8 @@ import org.apache.freemarker.core.userpkg.DummyOutputFormat;
import org.apache.freemarker.core.userpkg.EpochMillisDivTemplateDateFormatFactory;
import org.apache.freemarker.core.userpkg.EpochMillisTemplateDateFormatFactory;
import org.apache.freemarker.core.userpkg.HexTemplateNumberFormatFactory;
+import org.apache.freemarker.core.userpkg.NameClashingDummyOutputFormat;
+import org.apache.freemarker.core.userpkg.SeldomEscapedOutputFormat;
import org.apache.freemarker.core.util._CollectionUtil;
import org.apache.freemarker.core.util._DateUtil;
import org.apache.freemarker.core.util._NullArgumentException;
@@ -1457,7 +1459,8 @@ public class ConfigurationTest extends TestCase {
}
@Test
- public void testImpliedSettingValues() throws IOException, TemplateConfigurationFactoryException {
+ public void testImpliedSettingValues()
+ throws IOException, TemplateConfigurationFactoryException, UnregisteredOutputFormatException {
Configuration cfg = new ImpliedSettingValuesTestBuilder().build();
assertEquals("Y,N", cfg.getTemplateConfigurations().get("t.yn", null).getBooleanFormat());
@@ -1466,10 +1469,16 @@ public class ConfigurationTest extends TestCase {
assertEquals(ImmutableMap.of("lib", "lib.ftl"), cfg.getAutoImports());
assertEquals(ImmutableList.of("inc.ftl"), cfg.getAutoIncludes());
assertEquals(ImmutableMap.of("v", 1), cfg.getSharedVariables());
+ assertEquals(ImmutableList.of(CustomHTMLOutputFormat.INSTANCE, DummyOutputFormat.INSTANCE),
+ cfg.getRegisteredCustomOutputFormats());
+ assertSame(CustomHTMLOutputFormat.INSTANCE, cfg.getOutputFormat("HTML"));
+ assertSame(DummyOutputFormat.INSTANCE, cfg.getOutputFormat("dummy"));
+ assertSame(XMLOutputFormat.INSTANCE, cfg.getOutputFormat("XML"));
}
@Test
- public void testImpliedSettingValues2() throws IOException, TemplateConfigurationFactoryException {
+ public void testImpliedSettingValues2()
+ throws IOException, TemplateConfigurationFactoryException, UnregisteredOutputFormatException {
Configuration cfg = new ImpliedSettingValuesTestBuilder()
.templateConfigurations(
new ConditionalTemplateConfigurationFactory(
@@ -1482,6 +1491,8 @@ public class ConfigurationTest extends TestCase {
.autoImports(ImmutableMap.of("lib2", "lib2.ftl"))
.autoIncludes(ImmutableList.of("inc2.ftl"))
.sharedVariables(ImmutableMap.of("v2", 2))
+ .registeredCustomOutputFormats(
+ SeldomEscapedOutputFormat.INSTANCE, NameClashingDummyOutputFormat.INSTANCE)
.build();
TemplateConfigurationFactory tcf = cfg.getTemplateConfigurations();
@@ -1499,6 +1510,17 @@ public class ConfigurationTest extends TestCase {
assertEquals(ImmutableList.of("inc.ftl", "inc2.ftl"), cfg.getAutoIncludes());
assertEquals(ImmutableMap.of("v", 1, "v2", 2), cfg.getSharedVariables());
+
+ assertEquals(
+ ImmutableList.of(
+ CustomHTMLOutputFormat.INSTANCE,
+ SeldomEscapedOutputFormat.INSTANCE,
+ NameClashingDummyOutputFormat.INSTANCE),
+ cfg.getRegisteredCustomOutputFormats());
+ assertSame(CustomHTMLOutputFormat.INSTANCE, cfg.getOutputFormat("HTML"));
+ assertSame(NameClashingDummyOutputFormat.INSTANCE, cfg.getOutputFormat("dummy"));
+ assertSame(SeldomEscapedOutputFormat.INSTANCE, cfg.getOutputFormat("seldomEscaped"));
+ assertSame(XMLOutputFormat.INSTANCE, cfg.getOutputFormat("XML"));
}
@SuppressWarnings("boxing")
@@ -1568,9 +1590,14 @@ public class ConfigurationTest extends TestCase {
}
@Override
- protected Map<String, Object> getImplicitSharedVariables() {
+ protected Map<String, Object> getImpliedSharedVariables() {
return ImmutableMap.<String, Object>of("v", 1);
}
+
+ @Override
+ protected Collection<OutputFormat> getImpliedRegisteredCustomOutputFormats() {
+ return ImmutableList.<OutputFormat>of(CustomHTMLOutputFormat.INSTANCE, DummyOutputFormat.INSTANCE);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bd1c4c40/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NameClashingDummyOutputFormat.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NameClashingDummyOutputFormat.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NameClashingDummyOutputFormat.java
new file mode 100644
index 0000000..dd26156
--- /dev/null
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/userpkg/NameClashingDummyOutputFormat.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 NameClashingDummyOutputFormat extends CommonMarkupOutputFormat<TemplateDummyOutputModel> {
+
+ public static final NameClashingDummyOutputFormat INSTANCE = new NameClashingDummyOutputFormat();
+
+ private NameClashingDummyOutputFormat() {
+ // 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/bd1c4c40/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
index 93bd1ff..3b96857 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/Configuration.java
@@ -26,9 +26,11 @@ import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
@@ -302,12 +304,36 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
incompatibleImprovements = builder.getIncompatibleImprovements();
{
- Collection<OutputFormat> registeredCustomOutputFormats = builder.getRegisteredCustomOutputFormats();
+ final Collection<OutputFormat> regCustOutputFormats;
+ {
+ Collection<OutputFormat> directRegCustOutputFormats = builder.getRegisteredCustomOutputFormats();
+ Collection<OutputFormat> impliedRegCustOutputFormats =
+ builder.getImpliedRegisteredCustomOutputFormats();
+ if (impliedRegCustOutputFormats.isEmpty()) {
+ regCustOutputFormats = directRegCustOutputFormats;
+ } else if (directRegCustOutputFormats.isEmpty()) {
+ regCustOutputFormats = impliedRegCustOutputFormats;
+ } else {
+ List<OutputFormat> mergedOutputFormats = new ArrayList<>(
+ impliedRegCustOutputFormats.size() + directRegCustOutputFormats.size());
+ HashSet<String> directNames = new HashSet<>(directRegCustOutputFormats.size() * 4 / 3 + 1, .75f);
+ for (OutputFormat directRegCustOutputFormat : directRegCustOutputFormats) {
+ directNames.add(directRegCustOutputFormat.getName());
+ }
+ for (OutputFormat impliedRegCustOutputFormat : impliedRegCustOutputFormats) {
+ if (!directNames.contains(impliedRegCustOutputFormat.getName())) {
+ mergedOutputFormats.add(impliedRegCustOutputFormat);
+ }
+ }
+ mergedOutputFormats.addAll(directRegCustOutputFormats);
+ regCustOutputFormats = Collections.unmodifiableList(mergedOutputFormats);
+ }
+ }
- _NullArgumentException.check(registeredCustomOutputFormats);
+ _NullArgumentException.check(regCustOutputFormats);
Map<String, OutputFormat> registeredCustomOutputFormatsByName = new LinkedHashMap<>(
- registeredCustomOutputFormats.size() * 4 / 3, 1f);
- for (OutputFormat outputFormat : registeredCustomOutputFormats) {
+ regCustOutputFormats.size() * 4 / 3, 1f);
+ for (OutputFormat outputFormat : regCustOutputFormats) {
String name = outputFormat.getName();
if (name.equals(UndefinedOutputFormat.INSTANCE.getName())) {
throw new InvalidSettingValueException(
@@ -367,14 +393,14 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
this.registeredCustomOutputFormatsByName = registeredCustomOutputFormatsByName;
this.registeredCustomOutputFormats = Collections.unmodifiableList(
- new ArrayList<> (registeredCustomOutputFormats));
+ new ArrayList<> (regCustOutputFormats));
}
ObjectWrapper objectWrapper = builder.getObjectWrapper();
{
Map<String, Object> sharedVariables = _CollectionUtil.mergeImmutableMaps(builder
- .getImplicitSharedVariables(), builder.getSharedVariables(), false);
+ .getImpliedSharedVariables(), builder.getSharedVariables(), false);
HashMap<String, TemplateModel> wrappedSharedVariables = new HashMap<>(
sharedVariables.size() * 4 / 3 + 1, 0.75f);
@@ -803,32 +829,19 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
return (MarkupOutputFormat) of;
}
- /**
- * The custom output formats that can be referred by their unique name ({@link OutputFormat#getName()}) from
- * templates. Names are also used to look up the {@link OutputFormat} for standard file extensions; see them at
- * {@link #getRecognizeStandardFileExtensions()}. Each must be different and has a unique name
- * ({@link OutputFormat#getName()}) within this collection.
- *
- * <p>
- * When there's a clash between a custom output format name and a standard output format name, the custom format
- * will win, thus you can override the meaning of standard output format names. Except, it's not allowed to override
- * {@link UndefinedOutputFormat} and {@link PlainTextOutputFormat}.
- *
- * <p>
- * The default value is an empty collection.
- *
- * @throws IllegalArgumentException
- * When multiple different {@link OutputFormat}-s have the same name in the parameter collection. When
- * the same {@link OutputFormat} object occurs for multiple times in the collection. If an
- * {@link OutputFormat} name is 0 long. If an {@link OutputFormat} name doesn't start with letter or
- * digit. If an {@link OutputFormat} name contains {@code '+'} or <code>'{'</code> or <code>'}'</code>.
- * If an {@link OutputFormat} name equals to {@link UndefinedOutputFormat#getName()} or
- * {@link PlainTextOutputFormat#getName()}.
- */
public Collection<OutputFormat> getRegisteredCustomOutputFormats() {
return registeredCustomOutputFormats;
}
+ /**
+ * Always {@code true} in {@link Configuration}-s; even if this setting wasn't set in the builder, it gets a default
+ * value in the {@link Configuration}.
+ */
+ @Override
+ public boolean isRegisteredCustomOutputFormatsSet() {
+ return true;
+ }
+
@Override
public boolean getRecognizeStandardFileExtensions() {
return recognizeStandardFileExtensions == null
@@ -2477,9 +2490,6 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
: getDefaultRegisteredCustomOutputFormats();
}
- /**
- * Tells if this setting was explicitly set (if not, the default value of the setting will be used).
- */
public boolean isRegisteredCustomOutputFormatsSet() {
return registeredCustomOutputFormats != null;
}
@@ -2489,11 +2499,23 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
}
/**
+ * The imports that will be added to the built {@link Configuration} before the ones coming from
+ * {@link #getRegisteredCustomOutputFormats()}. When overriding this method, always consider adding to the
+ * return value of the super method, rather than replacing it.
+ *
+ * @return Immutable {@link Collection}; not {@code null}
+ */
+ protected Collection<OutputFormat> getImpliedRegisteredCustomOutputFormats() {
+ return Collections.emptyList();
+ }
+
+ /**
* Setter pair of {@link Configuration#getRegisteredCustomOutputFormats()}.
*/
public void setRegisteredCustomOutputFormats(Collection<OutputFormat> registeredCustomOutputFormats) {
_NullArgumentException.check("registeredCustomOutputFormats", registeredCustomOutputFormats);
- this.registeredCustomOutputFormats = registeredCustomOutputFormats;
+ this.registeredCustomOutputFormats = Collections.unmodifiableCollection(
+ new ArrayList<>(registeredCustomOutputFormats));
}
/**
@@ -2505,6 +2527,13 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
}
/**
+ * Varargs overload if {@link #registeredCustomOutputFormats(Collection)}.
+ */
+ public SelfT registeredCustomOutputFormats(OutputFormat... registeredCustomOutputFormats) {
+ return registeredCustomOutputFormats(Arrays.asList(registeredCustomOutputFormats));
+ }
+
+ /**
* Resets this setting to its initial state, as if it was never set.
*/
public void unsetRegisteredCustomOutputFormats() {
@@ -2534,7 +2563,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
/**
* The {@link Map} to use as shared variables if {@link #isSharedVariablesSet()} is {@code false}.
*
- * @see #getImplicitSharedVariables()
+ * @see #getImpliedSharedVariables()
*/
protected Map<String, Object> getDefaultSharedVariables() {
return Collections.emptyMap();
@@ -2559,7 +2588,7 @@ public final class Configuration implements TopLevelConfiguration, CustomStateSc
*
* @return Immutable {@link Map}; not {@code null}
*/
- protected Map<String, Object> getImplicitSharedVariables() {
+ protected Map<String, Object> getImpliedSharedVariables() {
return DEFAULT_SHARED_VARIABLES;
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/bd1c4c40/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java b/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
index fed778e..66d3495 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/TopLevelConfiguration.java
@@ -19,9 +19,13 @@
package org.apache.freemarker.core;
+import java.util.Collection;
import java.util.Map;
import org.apache.freemarker.core.model.TemplateModel;
+import org.apache.freemarker.core.outputformat.OutputFormat;
+import org.apache.freemarker.core.outputformat.impl.PlainTextOutputFormat;
+import org.apache.freemarker.core.outputformat.impl.UndefinedOutputFormat;
import org.apache.freemarker.core.templateresolver.CacheStorage;
import org.apache.freemarker.core.templateresolver.TemplateConfigurationFactory;
import org.apache.freemarker.core.templateresolver.TemplateLoader;
@@ -237,4 +241,33 @@ public interface TopLevelConfiguration extends ParsingAndProcessingConfiguration
*/
boolean isSharedVariablesSet();
+ /**
+ * The custom output formats that can be referred by their unique name ({@link OutputFormat#getName()}) from
+ * templates. Names are also used to look up the {@link OutputFormat} for standard file extensions; see them at
+ * {@link #getRecognizeStandardFileExtensions()}. Each must be different and has a unique name
+ * ({@link OutputFormat#getName()}) within this collection.
+ *
+ * <p>
+ * When there's a clash between a custom output format name and a standard output format name, the custom format
+ * will win, thus you can override the meaning of standard output format names. Except, it's not allowed to override
+ * {@link UndefinedOutputFormat} and {@link PlainTextOutputFormat}.
+ *
+ * <p>
+ * The default value is an empty collection.
+ *
+ * @throws IllegalArgumentException
+ * When multiple different {@link OutputFormat}-s have the same name in the parameter collection. When
+ * the same {@link OutputFormat} object occurs for multiple times in the collection. If an
+ * {@link OutputFormat} name is 0 long. If an {@link OutputFormat} name doesn't start with letter or
+ * digit. If an {@link OutputFormat} name contains {@code '+'} or <code>'{'</code> or <code>'}'</code>.
+ * If an {@link OutputFormat} name equals to {@link UndefinedOutputFormat#getName()} or
+ * {@link PlainTextOutputFormat#getName()}.
+ */
+ Collection<OutputFormat> getRegisteredCustomOutputFormats();
+
+ /**
+ * Tells if this setting was explicitly set (if not, the default value of the setting will be used).
+ */
+ boolean isRegisteredCustomOutputFormatsSet();
+
}