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/03/27 11:48:51 UTC
[2/6] incubator-freemarker git commit: Various refactorings of
Configurable and its subclasses. This is part of the preparation for making
such classes immutable, and offer builders to create them.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
index d79b545..7b4b887 100644
--- a/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/ParserConfiguration.java
@@ -18,14 +18,18 @@
*/
package org.apache.freemarker.core;
+import java.io.Writer;
+
import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
import org.apache.freemarker.core.outputformat.OutputFormat;
/**
* <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is implemented by
- * classes that hold settings that affect parsing. New parser settings can be added in new FreeMarker versions, which
- * will break your implementation.
- *
+ * classes that hold settings that affect template parsing (as opposed to {@linkplain Template#process(Object, Writer)
+ * template processing}). New parser settings can be added in new FreeMarker versions, which will break your
+ * implementation.
+ *
+ * @see ProcessingConfiguration
* @since 2.3.24
*/
public interface ParserConfiguration {
@@ -38,40 +42,89 @@ public interface ParserConfiguration {
int getTagSyntax();
/**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isTagSyntaxSet();
+
+ /**
* See {@link Configuration#getNamingConvention()}.
*/
int getNamingConvention();
/**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isNamingConventionSet();
+
+ /**
* See {@link Configuration#getWhitespaceStripping()}.
*/
boolean getWhitespaceStripping();
/**
- * Overlaps with {@link Configurable#getArithmeticEngine()}; the parser needs this for creating numerical literals.
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isWhitespaceStrippingSet();
+
+ /**
+ * Overlaps with {@link MutableProcessingConfiguration#getArithmeticEngine()}; the parser needs this for creating numerical literals.
*/
ArithmeticEngine getArithmeticEngine();
-
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isArithmeticEngineSet();
+
/**
* See {@link Configuration#getAutoEscapingPolicy()}.
*/
int getAutoEscapingPolicy();
-
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isAutoEscapingPolicySet();
+
/**
* See {@link Configuration#getOutputEncoding()}.
*/
OutputFormat getOutputFormat();
-
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isOutputFormatSet();
+
/**
* See {@link Configuration#getRecognizeStandardFileExtensions()}.
*/
boolean getRecognizeStandardFileExtensions();
-
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isRecognizeStandardFileExtensionsSet();
+
/**
* See {@link Configuration#getIncompatibleImprovements()}.
*/
Version getIncompatibleImprovements();
-
+
/**
* See {@link Configuration#getTabSize()}.
*
@@ -79,4 +132,18 @@ public interface ParserConfiguration {
*/
int getTabSize();
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isTabSizeSet();
+
+ /**
+ * Gets the default encoding for converting bytes to characters when
+ * reading template files in a locale for which no explicit encoding
+ * was specified. Defaults to the default system encoding.
+ */
+ String getEncoding();
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
new file mode 100644
index 0000000..16cbdd5
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/ProcessingConfiguration.java
@@ -0,0 +1,335 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import java.io.Writer;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.apache.freemarker.core.arithmetic.ArithmeticEngine;
+import org.apache.freemarker.core.model.ObjectWrapper;
+import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
+import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
+
+/**
+ * <b>Don't implement this interface yourself</b>; use the existing implementation(s). This interface is implemented by
+ * classes that hold settings that affect {@linkplain Template#process(Object, Writer) template processing} (as opposed
+ * to template parsing). New parser settings can be added in new FreeMarker versions, which will break your
+ * implementation.
+ *
+ * @see ParserConfiguration
+ */
+// TODO [FM3] JavaDoc
+public interface ProcessingConfiguration {
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setLocale(Locale)}.
+ */
+ Locale getLocale();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isLocaleSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setTimeZone(TimeZone)}.
+ */
+ TimeZone getTimeZone();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isTimeZoneSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setSQLDateAndTimeTimeZone(TimeZone)}.
+ *
+ * @return {@code null} if the value of {@link #getTimeZone()} should be used for formatting {@link java.sql.Date
+ * java.sql.Date} and {@link java.sql.Time java.sql.Time} values, otherwise the time zone that should be used to
+ * format the values of those two types.
+ */
+ TimeZone getSQLDateAndTimeTimeZone();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isSQLDateAndTimeTimeZoneSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setNumberFormat(String)}.
+ */
+ String getNumberFormat();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isNumberFormatSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setCustomNumberFormats(Map)}.
+ */
+ Map<String, ? extends TemplateNumberFormatFactory> getCustomNumberFormats();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isCustomNumberFormatsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setBooleanFormat(String)}.
+ */
+ String getBooleanFormat();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isBooleanFormatSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setTimeFormat(String)}.
+ */
+ String getTimeFormat();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isTimeFormatSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setDateFormat(String)}.
+ */
+ String getDateFormat();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isDateFormatSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setDateTimeFormat(String)}.
+ */
+ String getDateTimeFormat();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isDateTimeFormatSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setCustomDateFormats(Map)}.
+ */
+ Map<String, ? extends TemplateDateFormatFactory> getCustomDateFormats();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isCustomDateFormatsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setTemplateExceptionHandler(TemplateExceptionHandler)}.
+ */
+ TemplateExceptionHandler getTemplateExceptionHandler();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isTemplateExceptionHandlerSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setArithmeticEngine(ArithmeticEngine)}.
+ */
+ ArithmeticEngine getArithmeticEngine();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isArithmeticEngineSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setObjectWrapper(ObjectWrapper)}.
+ */
+ ObjectWrapper getObjectWrapper();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isObjectWrapperSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setOutputEncoding(String)}.
+ */
+ String getOutputEncoding();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isOutputEncodingSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setURLEscapingCharset(String)}.
+ */
+ String getURLEscapingCharset();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isURLEscapingCharsetSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setNewBuiltinClassResolver(TemplateClassResolver)}.
+ */
+ TemplateClassResolver getNewBuiltinClassResolver();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isNewBuiltinClassResolverSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setAutoFlush(boolean)}.
+ */
+ boolean getAutoFlush();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isAutoFlushSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setShowErrorTips(boolean)}.
+ */
+ boolean getShowErrorTips();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isShowErrorTipsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setLogTemplateExceptions(boolean)}.
+ */
+ boolean getLogTemplateExceptions();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isLogTemplateExceptionsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setLazyImports(boolean)}.
+ */
+ boolean getLazyImports();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isLazyImportsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setLazyAutoImports(Boolean)}.
+ */
+ Boolean getLazyAutoImports();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isLazyAutoImportsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setAutoImports(Map)}.
+ */
+ Map<String, String> getAutoImports();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isAutoImportsSet();
+
+ /**
+ * Getter pair of {@link MutableProcessingConfiguration#setAutoIncludes(List)}.
+ */
+ List<String> getAutoIncludes();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isAutoIncludesSet();
+
+ Map<Object, Object> getCustomAttributes();
+
+ /**
+ * Tells if this setting is set directly in this object. If not, then depending on the implementing class, reading
+ * the setting mights returns a default value, or returns the value of the setting from a parent object, or throws
+ * an {@link SettingValueNotSetException}.
+ */
+ boolean isCustomAttributesSet();
+
+ Object getCustomAttribute(Object name);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/SettingValueNotSetException.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/SettingValueNotSetException.java b/src/main/java/org/apache/freemarker/core/SettingValueNotSetException.java
new file mode 100644
index 0000000..6ff7bab
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/SettingValueNotSetException.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.freemarker.core;
+
+import org.apache.freemarker.core.util._StringUtil;
+
+public class SettingValueNotSetException extends IllegalStateException {
+
+ private final String settingName;
+
+ public SettingValueNotSetException(String settingName) {
+ super("Setting " + _StringUtil.jQuote(settingName)
+ + " is not set in this layer and has no default here either.");
+ this.settingName = settingName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/Template.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/Template.java b/src/main/java/org/apache/freemarker/core/Template.java
index e253197..77b5b2d 100644
--- a/src/main/java/org/apache/freemarker/core/Template.java
+++ b/src/main/java/org/apache/freemarker/core/Template.java
@@ -38,6 +38,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.freemarker.core.debug._DebuggerService;
import org.apache.freemarker.core.model.ObjectWrapper;
@@ -72,7 +73,7 @@ import org.apache.freemarker.core.util._NullArgumentException;
* shared {@link Configuration}, and you are using {@link Configuration#getTemplate(String)} (or its overloads), then
* use {@link Configuration#setTemplateConfigurations(org.apache.freemarker.core.templateresolver.TemplateConfigurationFactory)} to achieve that.
*/
-public class Template extends Configurable {
+public class Template extends MutableProcessingConfiguration<Template> implements CustomStateScope {
public static final String DEFAULT_NAMESPACE_PREFIX = "D";
public static final String NO_NS_PREFIX = "N";
@@ -95,6 +96,9 @@ public class Template extends Configurable {
private Map namespaceURIToPrefixLookup = new HashMap();
private Version templateLanguageVersion;
+ private final Object lock = new Object();
+ private final ConcurrentHashMap<CustomStateKey, Object> customStateMap = new ConcurrentHashMap<>(0);
+
/**
* A prime constructor to which all other constructors should
* delegate directly or indirectly.
@@ -206,7 +210,7 @@ public class Template extends Configurable {
* practically just overrides some of the parser settings, as the others are inherited from the
* {@link Configuration}. Note that if this is a {@link TemplateConfiguration}, you will also want to
* call {@link TemplateConfiguration#apply(Template)} on the resulting {@link Template} so that
- * {@link Configurable} settings will be set too, because this constructor only uses it as a
+ * {@link MutableProcessingConfiguration} settings will be set too, because this constructor only uses it as a
* {@link ParserConfiguration}.
* @param encoding
* Same as in {@link #Template(String, String, Reader, Configuration, String)}.
@@ -425,7 +429,7 @@ public class Template extends Configurable {
* @param dataModel the holder of the variables visible from all templates; see {@link #process(Object, Writer)} for
* more details.
* @param wrapper The {@link ObjectWrapper} to use to wrap objects into {@link TemplateModel}
- * instances. Normally you left it {@code null}, in which case {@link Configurable#getObjectWrapper()} will be
+ * instances. Normally you left it {@code null}, in which case {@link MutableProcessingConfiguration#getObjectWrapper()} will be
* used.
* @param out The {@link Writer} where the output of the template will go; see {@link #process(Object, Writer)} for
* more details.
@@ -928,5 +932,25 @@ public class Template extends Configurable {
return prefix + ":" + localName;
}
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getCustomState(CustomStateKey<T> customStateKey) {
+ T customState = (T) customStateMap.get(customStateKey);
+ if (customState == null) {
+ synchronized (lock) {
+ customState = (T) customStateMap.get(customStateKey);
+ if (customState == null) {
+ customState = customStateKey.create();
+ if (customState == null) {
+ throw new IllegalStateException("CustomStateKey.create() must not return null (for key: "
+ + customStateKey + ")");
+ }
+ customStateMap.put(customStateKey, customState);
+ }
+ }
+ }
+ return customState;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/TemplateClassResolver.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateClassResolver.java b/src/main/java/org/apache/freemarker/core/TemplateClassResolver.java
index 0c5a9fc..c49e3fa 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateClassResolver.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateClassResolver.java
@@ -29,7 +29,7 @@ import org.apache.freemarker.core.util._ClassUtil;
* The implementation should be thread-safe, unless an
* instance is always only used in a single {@link Environment} object.
*
- * @see Configurable#setNewBuiltinClassResolver(TemplateClassResolver)
+ * @see MutableProcessingConfiguration#setNewBuiltinClassResolver(TemplateClassResolver)
*
* @since 2.3.17
*/
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
index 3d1b903..3be8b3e 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateConfiguration.java
@@ -59,11 +59,11 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
* you should be aware of a few more details:
*
* <ul>
- * <li>This class implements both {@link Configurable} and {@link ParserConfiguration}. This means that it can influence
+ * <li>This class implements both {@link MutableProcessingConfiguration} and {@link ParserConfiguration}. This means that it can influence
* both the template parsing phase and the runtime settings. For both aspects (i.e., {@link ParserConfiguration} and
- * {@link Configurable}) to take effect, you have first pass this object to the {@link Template} constructor
+ * {@link MutableProcessingConfiguration}) to take effect, you have first pass this object to the {@link Template} constructor
* (this is where the {@link ParserConfiguration} interface is used), and then you have to call {@link #apply(Template)}
- * on the resulting {@link Template} object (this is where the {@link Configurable} aspect is used).
+ * on the resulting {@link Template} object (this is where the {@link MutableProcessingConfiguration} aspect is used).
*
* <li>{@link #apply(Template)} only change the settings that weren't yet set on the {@link Template} (but are inherited
* from the {@link Configuration}). This is primarily because if the template configures itself via the {@code #ftl}
@@ -77,7 +77,8 @@ import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory;
*
* @since 2.3.24
*/
-public final class TemplateConfiguration extends Configurable implements ParserConfiguration {
+public final class TemplateConfiguration extends MutableProcessingConfiguration<TemplateConfiguration>
+ implements ParserConfiguration {
private TemplateLanguage templateLanguage;
private Integer tagSyntax;
@@ -102,13 +103,13 @@ public final class TemplateConfiguration extends Configurable implements ParserC
* Same as {@link #setParentConfiguration(Configuration)}.
*/
@Override
- void setParent(Configurable cfg) {
+ void setParent(MutableProcessingConfiguration cfg) {
_NullArgumentException.check("cfg", cfg);
if (!(cfg instanceof Configuration)) {
throw new IllegalArgumentException("The parent of a TemplateConfiguration can only be a Configuration");
}
- Configurable parent = getParent();
+ MutableProcessingConfiguration parent = getParent();
if (parent != null) {
if (parent != cfg) {
throw new IllegalStateException(
@@ -144,7 +145,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
}
private Configuration getNonNullParentConfiguration() {
- Configurable parent = getParent();
+ MutableProcessingConfiguration parent = getParent();
if (parent == null) {
throw new IllegalStateException("The TemplateConfiguration wasn't associated with a Configuration yet.");
}
@@ -253,13 +254,23 @@ public final class TemplateConfiguration extends Configurable implements ParserC
setLazyAutoImports(tc.getLazyAutoImports());
}
if (tc.isAutoImportsSet()) {
- setAutoImports(mergeMaps(getAutoImportsWithoutFallback(), tc.getAutoImportsWithoutFallback(),true));
+ setAutoImports(mergeMaps(
+ isAutoImportsSet() ? getAutoImports() : null,
+ tc.isAutoImportsSet() ? tc.getAutoImports() : null,
+ true));
}
if (tc.isAutoIncludesSet()) {
- setAutoIncludes(mergeLists(getAutoIncludesWithoutFallback(), tc.getAutoIncludesWithoutFallback()));
+ setAutoIncludes(mergeLists(
+ isAutoIncludesSet() ? getAutoIncludes() : null,
+ tc.isAutoIncludesSet() ? tc.getAutoIncludes() : null));
+ }
+
+ if (tc.isCustomAttributesSet()) {
+ setCustomAttributes(mergeMaps(
+ isCustomAttributesSet() ? getCustomAttributes() : null,
+ tc.isCustomAttributesSet() ? tc.getCustomAttributes() : null,
+ true));
}
-
- tc.copyDirectCustomAttributes(this, true);
}
/**
@@ -301,11 +312,17 @@ public final class TemplateConfiguration extends Configurable implements ParserC
}
if (isCustomDateFormatsSet()) {
template.setCustomDateFormats(
- mergeMaps(getCustomDateFormats(), template.getCustomDateFormatsWithoutFallback(), false));
+ mergeMaps(
+ getCustomDateFormats(),
+ template.isCustomDateFormatsSet() ? template.getCustomDateFormats() : null,
+ false));
}
if (isCustomNumberFormatsSet()) {
template.setCustomNumberFormats(
- mergeMaps(getCustomNumberFormats(), template.getCustomNumberFormatsWithoutFallback(), false));
+ mergeMaps(
+ getCustomNumberFormats(),
+ template.isCustomNumberFormatsSet() ? template.getCustomNumberFormats() : null,
+ false));
}
if (isDateFormatSet() && !template.isDateFormatSet()) {
template.setDateFormat(getDateFormat());
@@ -363,10 +380,15 @@ public final class TemplateConfiguration extends Configurable implements ParserC
// - Existing template-level imports have precedence over those coming from the TC (just as with the others
// apply()-ed settings), thus for clashing import prefixes they must win.
// - Template-level imports count as more specific, and so come after the more generic ones from TC.
- template.setAutoImports(mergeMaps(getAutoImports(), template.getAutoImportsWithoutFallback(), true));
+ template.setAutoImports(mergeMaps(
+ getAutoImports(),
+ template.isAutoImportsSet() ? template.getAutoImports() : null,
+ true));
}
if (isAutoIncludesSet()) {
- template.setAutoIncludes(mergeLists(getAutoIncludes(), template.getAutoIncludesWithoutFallback()));
+ template.setAutoIncludes(mergeLists(
+ getAutoIncludes(),
+ template.isAutoIncludesSet() ? template.getAutoIncludes() : null));
}
copyDirectCustomAttributes(template, false);
@@ -388,9 +410,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
return tagSyntax != null ? tagSyntax : getNonNullParentConfiguration().getTagSyntax();
}
- /**
- * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
- */
+ @Override
public boolean isTagSyntaxSet() {
return tagSyntax != null;
}
@@ -435,6 +455,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*/
+ @Override
public boolean isNamingConventionSet() {
return namingConvention != null;
}
@@ -458,6 +479,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*/
+ @Override
public boolean isWhitespaceStrippingSet() {
return whitespaceStripping != null;
}
@@ -483,6 +505,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*/
+ @Override
public boolean isAutoEscapingPolicySet() {
return autoEscapingPolicy != null;
}
@@ -506,6 +529,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*/
+ @Override
public boolean isOutputFormatSet() {
return outputFormat != null;
}
@@ -529,12 +553,14 @@ public final class TemplateConfiguration extends Configurable implements ParserC
/**
* Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
*/
+ @Override
public boolean isRecognizeStandardFileExtensionsSet() {
return recognizeStandardFileExtensions != null;
}
+ @Override
public String getEncoding() {
- return encoding != null ? encoding : getNonNullParentConfiguration().getDefaultEncoding();
+ return encoding != null ? encoding : getNonNullParentConfiguration().getEncoding();
}
/**
@@ -580,6 +606,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
*
* @since 2.3.25
*/
+ @Override
public boolean isTabSizeSet() {
return tabSize != null;
}
@@ -596,8 +623,6 @@ public final class TemplateConfiguration extends Configurable implements ParserC
return getNonNullParentConfiguration().getIncompatibleImprovements();
}
-
-
@Override
public Locale getLocale() {
try {
@@ -879,7 +904,7 @@ public final class TemplateConfiguration extends Configurable implements ParserC
}
@Override
- public Object getCustomAttribute(String name) {
+ public Object getCustomAttribute(Object name) {
try {
return super.getCustomAttribute(name);
} catch (NullPointerException e) {
@@ -888,34 +913,6 @@ public final class TemplateConfiguration extends Configurable implements ParserC
}
}
- private boolean hasAnyConfigurableSet() {
- return
- isAPIBuiltinEnabledSet()
- || isArithmeticEngineSet()
- || isAutoFlushSet()
- || isAutoImportsSet()
- || isAutoIncludesSet()
- || isBooleanFormatSet()
- || isCustomDateFormatsSet()
- || isCustomNumberFormatsSet()
- || isDateFormatSet()
- || isDateTimeFormatSet()
- || isLazyImportsSet()
- || isLazyAutoImportsSet()
- || isLocaleSet()
- || isLogTemplateExceptionsSet()
- || isNewBuiltinClassResolverSet()
- || isNumberFormatSet()
- || isObjectWrapperSet()
- || isOutputEncodingSet()
- || isShowErrorTipsSet()
- || isSQLDateAndTimeTimeZoneSet()
- || isTemplateExceptionHandlerSet()
- || isTimeFormatSet()
- || isTimeZoneSet()
- || isURLEscapingCharsetSet();
- }
-
private Map mergeMaps(Map m1, Map m2, boolean overwriteUpdatesOrder) {
if (m1 == null) return m2;
if (m2 == null) return m1;
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/TemplateExceptionHandler.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/TemplateExceptionHandler.java b/src/main/java/org/apache/freemarker/core/TemplateExceptionHandler.java
index 797a4c2..8270740 100644
--- a/src/main/java/org/apache/freemarker/core/TemplateExceptionHandler.java
+++ b/src/main/java/org/apache/freemarker/core/TemplateExceptionHandler.java
@@ -27,7 +27,7 @@ import org.apache.freemarker.core.util._StringUtil;
/**
* Used for the {@code template_exception_handler} configuration setting;
- * see {@link Configurable#setTemplateExceptionHandler(TemplateExceptionHandler)} for more.
+ * see {@link MutableProcessingConfiguration#setTemplateExceptionHandler(TemplateExceptionHandler)} for more.
*/
public interface TemplateExceptionHandler {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java b/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
index 53d09ea..e709862 100644
--- a/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
+++ b/src/main/java/org/apache/freemarker/core/_ParserConfigurationWithInheritedFormat.java
@@ -43,11 +43,21 @@ public final class _ParserConfigurationWithInheritedFormat implements ParserConf
}
@Override
+ public boolean isWhitespaceStrippingSet() {
+ return wrappedPCfg.isWhitespaceStrippingSet();
+ }
+
+ @Override
public int getTagSyntax() {
return wrappedPCfg.getTagSyntax();
}
@Override
+ public boolean isTagSyntaxSet() {
+ return wrappedPCfg.isTagSyntaxSet();
+ }
+
+ @Override
public TemplateLanguage getTemplateLanguage() {
return wrappedPCfg.getTemplateLanguage();
}
@@ -58,16 +68,31 @@ public final class _ParserConfigurationWithInheritedFormat implements ParserConf
}
@Override
+ public boolean isOutputFormatSet() {
+ return wrappedPCfg.isOutputFormatSet();
+ }
+
+ @Override
public boolean getRecognizeStandardFileExtensions() {
return false;
}
@Override
+ public boolean isRecognizeStandardFileExtensionsSet() {
+ return wrappedPCfg.isRecognizeStandardFileExtensionsSet();
+ }
+
+ @Override
public int getNamingConvention() {
return wrappedPCfg.getNamingConvention();
}
@Override
+ public boolean isNamingConventionSet() {
+ return wrappedPCfg.isNamingConventionSet();
+ }
+
+ @Override
public Version getIncompatibleImprovements() {
return wrappedPCfg.getIncompatibleImprovements();
}
@@ -78,13 +103,33 @@ public final class _ParserConfigurationWithInheritedFormat implements ParserConf
}
@Override
+ public boolean isAutoEscapingPolicySet() {
+ return wrappedPCfg.isAutoEscapingPolicySet();
+ }
+
+ @Override
public ArithmeticEngine getArithmeticEngine() {
return wrappedPCfg.getArithmeticEngine();
}
@Override
+ public boolean isArithmeticEngineSet() {
+ return wrappedPCfg.isArithmeticEngineSet();
+ }
+
+ @Override
public int getTabSize() {
return wrappedPCfg.getTabSize();
}
-
+
+ @Override
+ public boolean isTabSizeSet() {
+ return wrappedPCfg.isTabSizeSet();
+ }
+
+ @Override
+ public String getEncoding() {
+ return wrappedPCfg.getEncoding();
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/debug/DebuggedEnvironment.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/debug/DebuggedEnvironment.java b/src/main/java/org/apache/freemarker/core/debug/DebuggedEnvironment.java
index 9536ac8..dca312d 100644
--- a/src/main/java/org/apache/freemarker/core/debug/DebuggedEnvironment.java
+++ b/src/main/java/org/apache/freemarker/core/debug/DebuggedEnvironment.java
@@ -21,6 +21,8 @@ package org.apache.freemarker.core.debug;
import java.rmi.RemoteException;
+import org.apache.freemarker.core.MutableProcessingConfiguration;
+
/**
* Represents the debugger-side mirror of a debugged
* {@link org.apache.freemarker.core.Environment} object in the remote VM. This interface
@@ -32,7 +34,7 @@ import java.rmi.RemoteException;
* <p>The debug model for the configuration supports key "sharedVariables".
* <p>Additionally, all of the debug models for environment, template, and
* configuration also support all the setting keys of
- * {@link org.apache.freemarker.core.Configurable} objects.
+ * {@link MutableProcessingConfiguration} objects.
*/
public interface DebuggedEnvironment extends DebugModel {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java b/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
index 8f83eca..c42af46 100644
--- a/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
+++ b/src/main/java/org/apache/freemarker/core/debug/RmiDebuggedEnvironmentImpl.java
@@ -32,9 +32,10 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import org.apache.freemarker.core.Configurable;
import org.apache.freemarker.core.Configuration;
import org.apache.freemarker.core.Environment;
+import org.apache.freemarker.core.MutableProcessingConfiguration;
+import org.apache.freemarker.core.ProcessingConfiguration;
import org.apache.freemarker.core.Template;
import org.apache.freemarker.core.model.TemplateCollectionModel;
import org.apache.freemarker.core.model.TemplateHashModelEx;
@@ -164,17 +165,17 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
private static class DebugConfigurableModel extends DebugMapModel {
static final List KEYS = Arrays.asList(
- Configurable.ARITHMETIC_ENGINE_KEY,
- Configurable.BOOLEAN_FORMAT_KEY,
- Configurable.LOCALE_KEY,
- Configurable.NUMBER_FORMAT_KEY,
- Configurable.OBJECT_WRAPPER_KEY,
- Configurable.TEMPLATE_EXCEPTION_HANDLER_KEY);
+ MutableProcessingConfiguration.ARITHMETIC_ENGINE_KEY,
+ MutableProcessingConfiguration.BOOLEAN_FORMAT_KEY,
+ MutableProcessingConfiguration.LOCALE_KEY,
+ MutableProcessingConfiguration.NUMBER_FORMAT_KEY,
+ MutableProcessingConfiguration.OBJECT_WRAPPER_KEY,
+ MutableProcessingConfiguration.TEMPLATE_EXCEPTION_HANDLER_KEY);
- final Configurable configurable;
+ final ProcessingConfiguration ProcessingConfiguration;
- DebugConfigurableModel(Configurable configurable) {
- this.configurable = configurable;
+ DebugConfigurableModel(ProcessingConfiguration processingConfiguration) {
+ this.ProcessingConfiguration = processingConfiguration;
}
@Override
@@ -196,12 +197,12 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
{
@Override
Collection keySet() {
- return ((Configuration) configurable).getSharedVariableNames();
+ return ((Configuration) ProcessingConfiguration).getSharedVariableNames();
}
@Override
public TemplateModel get(String key) {
- return ((Configuration) configurable).getSharedVariable(key);
+ return ((Configuration) ProcessingConfiguration).getSharedVariable(key);
}
};
@@ -244,7 +245,7 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
public TemplateModel get(String key) throws TemplateModelException {
if ("configuration".equals(key)) {
try {
- return (TemplateModel) getCachedWrapperFor(((Template) configurable).getConfiguration());
+ return (TemplateModel) getCachedWrapperFor(((Template) ProcessingConfiguration).getConfiguration());
} catch (RemoteException e) {
throw new TemplateModelException(e);
}
@@ -271,7 +272,7 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
@Override
Collection keySet() {
try {
- return ((Environment) configurable).getKnownVariableNames();
+ return ((Environment) ProcessingConfiguration).getKnownVariableNames();
} catch (TemplateModelException e) {
throw new UndeclaredThrowableException(e);
}
@@ -279,7 +280,7 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
@Override
public TemplateModel get(String key) throws TemplateModelException {
- return ((Environment) configurable).getVariable(key);
+ return ((Environment) ProcessingConfiguration).getVariable(key);
}
};
@@ -295,30 +296,30 @@ class RmiDebuggedEnvironmentImpl extends RmiDebugModelImpl implements DebuggedEn
@Override
public TemplateModel get(String key) throws TemplateModelException {
if ("currentNamespace".equals(key)) {
- return ((Environment) configurable).getCurrentNamespace();
+ return ((Environment) ProcessingConfiguration).getCurrentNamespace();
}
if ("dataModel".equals(key)) {
- return ((Environment) configurable).getDataModel();
+ return ((Environment) ProcessingConfiguration).getDataModel();
}
if ("globalNamespace".equals(key)) {
- return ((Environment) configurable).getGlobalNamespace();
+ return ((Environment) ProcessingConfiguration).getGlobalNamespace();
}
if ("knownVariables".equals(key)) {
return knownVariables;
}
if ("mainNamespace".equals(key)) {
- return ((Environment) configurable).getMainNamespace();
+ return ((Environment) ProcessingConfiguration).getMainNamespace();
}
if ("mainTemplate".equals(key)) {
try {
- return (TemplateModel) getCachedWrapperFor(((Environment) configurable).getMainTemplate());
+ return (TemplateModel) getCachedWrapperFor(((Environment) ProcessingConfiguration).getMainTemplate());
} catch (RemoteException e) {
throw new TemplateModelException(e);
}
}
if ("currentTemplate".equals(key)) {
try {
- return (TemplateModel) getCachedWrapperFor(((Environment) configurable).getCurrentTemplate());
+ return (TemplateModel) getCachedWrapperFor(((Environment) ProcessingConfiguration).getCurrentTemplate());
} catch (RemoteException e) {
throw new TemplateModelException(e);
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java b/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
index d630752..91fe9dc 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
@@ -125,7 +125,7 @@ public class BeanModel
* <tt>non-void-return-type get(java.lang.String)</tt>,
* then <tt>non-void-return-type get(java.lang.Object)</tt>, or
* alternatively (if the wrapped object is a resource bundle)
- * <tt>Object getObject(java.lang.String)</tt>.
+ * <tt>Object get(java.lang.String)</tt>.
* @throws TemplateModelException if there was no property nor method nor
* a generic <tt>get</tt> method to invoke.
*/
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
index 5bc97a1..6cde3ee 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapper.java
@@ -1275,6 +1275,7 @@ public class DefaultObjectWrapper implements RichObjectWrapper {
* Returns a {@link DefaultObjectWrapper} instance that matches the settings of this builder. This will be possibly
* a singleton that is also in use elsewhere.
*/
+ @Override
public DefaultObjectWrapper build() {
return DefaultObjectWrapperTCCLSingletonUtil.getSingleton(
this, INSTANCE_CACHE, INSTANCE_CACHE_REF_QUEUE, ConstructorInvoker.INSTANCE);
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/model/impl/ResourceBundleModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/ResourceBundleModel.java b/src/main/java/org/apache/freemarker/core/model/impl/ResourceBundleModel.java
index c48b2e0..31af451 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/ResourceBundleModel.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/ResourceBundleModel.java
@@ -63,7 +63,7 @@ public class ResourceBundleModel
}
/**
- * Overridden to invoke the getObject method of the resource bundle.
+ * Overridden to invoke the get method of the resource bundle.
*/
@Override
protected TemplateModel invokeGenericGet(Map keyMap, Class clazz, String key)
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java b/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
index a4df46f..f520c3d 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/SimpleHash.java
@@ -67,11 +67,11 @@ import org.apache.freemarker.core.model.WrappingTemplateModel;
* <p>
* It also matters if for how many times will the <em>same</em> {@link Map} entry be read from the template(s) later, on
* average. If, on average, you read each entry for more than 4 times, {@link SimpleHash} will be most certainly faster,
- * but if for 2 times or less (and especially if not at all) then {@link DefaultMapAdapter} will be. Before choosing
- * based on performance though, pay attention to the behavioral differences; {@link SimpleHash} will shallow-copy
- * the original {@link Map} at construction time, so key order will be lost in some cases, and it won't reflect
- * {@link Map} content changes after the {@link SimpleHash} construction, also {@link SimpleHash} can't be unwrapped
- * to the original {@link Map} instance.
+ * but if for 2 times or less (and especially if not at all) then {@link DefaultMapAdapter} will be faster. Before
+ * choosing based on performance though, pay attention to the behavioral differences; {@link SimpleHash} will
+ * shallow-copy the original {@link Map} at construction time, so key order will be lost in some cases, and it won't
+ * reflect {@link Map} content changes after the {@link SimpleHash} construction, also {@link SimpleHash} can't be
+ * unwrapped to the original {@link Map} instance.
*
* @see DefaultMapAdapter
* @see TemplateHashModelEx
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java b/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java
index 907acb2..1b949f1 100644
--- a/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java
+++ b/src/main/java/org/apache/freemarker/core/model/impl/SimpleSequence.java
@@ -59,7 +59,7 @@ import org.apache.freemarker.core.model.WrappingTemplateModel;
* It also matters if for how many times will the <em>same</em> {@link List} entry be read from the template(s) later,
* on average. If, on average, you read each entry for more than 4 times, {@link SimpleSequence} will be most
* certainly faster, but if for 2 times or less (and especially if not at all) then {@link DefaultMapAdapter} will
- * be. Before choosing based on performance though, pay attention to the behavioral differences;
+ * be faster. Before choosing based on performance though, pay attention to the behavioral differences;
* {@link SimpleSequence} will shallow-copy the original {@link List} at construction time, so it won't reflect
* {@link List} content changes after the {@link SimpleSequence} construction, also {@link SimpleSequence} can't be
* unwrapped to the original wrapped instance.
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java b/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
index a5a574c..4436874 100644
--- a/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
+++ b/src/main/java/org/apache/freemarker/core/templateresolver/impl/DefaultTemplateResolver.java
@@ -551,10 +551,8 @@ public class DefaultTemplateResolver extends TemplateResolver {
if (tc != null && tc.isLocaleSet()) {
locale = tc.getLocale();
}
-
- String initialEncoding = tc != null && tc.isEncodingSet() ? tc.getEncoding() : config.getDefaultEncoding();
- TemplateLanguage templateLanguage = tc != null && tc.isTemplateLanguageSet() ? tc.getTemplateLanguage()
- : config .getTemplateLanguage();
+ String initialEncoding = tc != null ? tc.getEncoding() : config.getEncoding();
+ TemplateLanguage templateLanguage = tc != null ? tc.getTemplateLanguage() : config .getTemplateLanguage();
Template template;
{
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java b/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
index 51da424..8fd7b38 100644
--- a/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
+++ b/src/main/java/org/apache/freemarker/core/util/OptInTemplateClassResolver.java
@@ -26,7 +26,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-import org.apache.freemarker.core.Configurable;
+import org.apache.freemarker.core.MutableProcessingConfiguration;
import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.Template;
import org.apache.freemarker.core.TemplateClassResolver;
@@ -104,7 +104,7 @@ public class OptInTemplateClassResolver implements TemplateClassResolver {
throw new _MiscTemplateException(env,
"Instantiating ", className, " is not allowed in the template for security reasons. (If you "
+ "run into this problem when using ?new in a template, you may want to check the \"",
- Configurable.NEW_BUILTIN_CLASS_RESOLVER_KEY,
+ MutableProcessingConfiguration.NEW_BUILTIN_CLASS_RESOLVER_KEY,
"\" setting in the FreeMarker configuration.)");
} else {
try {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java b/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
index 1b54947..5d532de 100644
--- a/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
+++ b/src/main/java/org/apache/freemarker/core/util/_CollectionUtil.java
@@ -25,8 +25,8 @@ public class _CollectionUtil {
private _CollectionUtil() { }
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[] { };
-
public static final Class[] EMPTY_CLASS_ARRAY = new Class[] { };
+ public static final String[] EMPTY_STRING_ARRAY = new String[] { };
/**
* @since 2.3.22
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/util/_LocaleUtil.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/_LocaleUtil.java b/src/main/java/org/apache/freemarker/core/util/_LocaleUtil.java
index 2ee4d53..2f09c88 100644
--- a/src/main/java/org/apache/freemarker/core/util/_LocaleUtil.java
+++ b/src/main/java/org/apache/freemarker/core/util/_LocaleUtil.java
@@ -22,9 +22,7 @@ import java.util.Locale;
/**
* For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
- * This class is to work around the lack of module system in Java, i.e., so that other FreeMarker packages can
- * access things inside this package that users shouldn't.
- */
+ */
public class _LocaleUtil {
/**
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/util/_ObjectHolder.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/util/_ObjectHolder.java b/src/main/java/org/apache/freemarker/core/util/_ObjectHolder.java
new file mode 100644
index 0000000..cbd7e11
--- /dev/null
+++ b/src/main/java/org/apache/freemarker/core/util/_ObjectHolder.java
@@ -0,0 +1,55 @@
+/*
+ * 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.util;
+
+/**
+ * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
+ */
+public class _ObjectHolder<T> {
+
+ private T object;
+
+ public _ObjectHolder(T object) {
+ this.object = object;
+ }
+
+ public T get() {
+ return object;
+ }
+
+ public void set(T object) {
+ this.object = object;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ _ObjectHolder<?> that = (_ObjectHolder<?>) o;
+
+ return object != null ? object.equals(that.object) : that.object == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return object != null ? object.hashCode() : 0;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/valueformat/TemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/valueformat/TemplateDateFormatFactory.java b/src/main/java/org/apache/freemarker/core/valueformat/TemplateDateFormatFactory.java
index 5ee26e0..07c2256 100644
--- a/src/main/java/org/apache/freemarker/core/valueformat/TemplateDateFormatFactory.java
+++ b/src/main/java/org/apache/freemarker/core/valueformat/TemplateDateFormatFactory.java
@@ -23,7 +23,7 @@ import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
-import org.apache.freemarker.core.Configurable;
+import org.apache.freemarker.core.MutableProcessingConfiguration;
import org.apache.freemarker.core.Configuration;
import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.model.TemplateDateModel;
@@ -32,7 +32,7 @@ import org.apache.freemarker.core.model.TemplateDateModel;
* Factory for a certain kind of date/time/dateTime formatting ({@link TemplateDateFormat}). Usually a singleton
* (one-per-VM or one-per-{@link Configuration}), and so must be thread-safe.
*
- * @see Configurable#setCustomDateFormats(java.util.Map)
+ * @see MutableProcessingConfiguration#setCustomDateFormats(java.util.Map)
*
* @since 2.3.24
*/
@@ -50,7 +50,7 @@ public abstract class TemplateDateFormatFactory extends TemplateValueFormatFacto
*
* @param params
* The string that further describes how the format should look. For example, when the
- * {@link Configurable#getDateFormat() dateFormat} is {@code "@fooBar 1, 2"}, then it will be
+ * {@link MutableProcessingConfiguration#getDateFormat() dateFormat} is {@code "@fooBar 1, 2"}, then it will be
* {@code "1, 2"} (and {@code "@fooBar"} selects the factory). The format of this string is up to the
* {@link TemplateDateFormatFactory} implementation. Not {@code null}, often an empty string.
* @param dateType
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormatFactory.java b/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormatFactory.java
index 464e6ff..7e21cfe 100644
--- a/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormatFactory.java
+++ b/src/main/java/org/apache/freemarker/core/valueformat/TemplateNumberFormatFactory.java
@@ -20,7 +20,7 @@ package org.apache.freemarker.core.valueformat;
import java.util.Locale;
-import org.apache.freemarker.core.Configurable;
+import org.apache.freemarker.core.MutableProcessingConfiguration;
import org.apache.freemarker.core.Configuration;
import org.apache.freemarker.core.Environment;
@@ -28,7 +28,7 @@ import org.apache.freemarker.core.Environment;
* Factory for a certain kind of number formatting ({@link TemplateNumberFormat}). Usually a singleton (one-per-VM or
* one-per-{@link Configuration}), and so must be thread-safe.
*
- * @see Configurable#setCustomNumberFormats(java.util.Map)
+ * @see MutableProcessingConfiguration#setCustomNumberFormats(java.util.Map)
*
* @since 2.3.24
*/
@@ -46,7 +46,7 @@ public abstract class TemplateNumberFormatFactory extends TemplateValueFormatFac
*
* @param params
* The string that further describes how the format should look. For example, when the
- * {@link Configurable#getNumberFormat() numberFormat} is {@code "@fooBar 1, 2"}, then it will be
+ * {@link MutableProcessingConfiguration#getNumberFormat() numberFormat} is {@code "@fooBar 1, 2"}, then it will be
* {@code "1, 2"} (and {@code "@fooBar"} selects the factory). The format of this string is up to the
* {@link TemplateNumberFormatFactory} implementation. Not {@code null}, often an empty string.
* @param locale
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/core/valueformat/impl/ISOLikeTemplateDateFormatFactory.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/core/valueformat/impl/ISOLikeTemplateDateFormatFactory.java b/src/main/java/org/apache/freemarker/core/valueformat/impl/ISOLikeTemplateDateFormatFactory.java
index fb13fad..5db8f46 100644
--- a/src/main/java/org/apache/freemarker/core/valueformat/impl/ISOLikeTemplateDateFormatFactory.java
+++ b/src/main/java/org/apache/freemarker/core/valueformat/impl/ISOLikeTemplateDateFormatFactory.java
@@ -19,6 +19,7 @@
package org.apache.freemarker.core.valueformat.impl;
+import org.apache.freemarker.core.CustomStateKey;
import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.util._DateUtil.CalendarFieldsToDateConverter;
import org.apache.freemarker.core.util._DateUtil.DateToISO8601CalendarFactory;
@@ -28,27 +29,29 @@ import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory;
abstract class ISOLikeTemplateDateFormatFactory extends TemplateDateFormatFactory {
- private static final Object DATE_TO_CAL_CONVERTER_KEY = new Object();
- private static final Object CAL_TO_DATE_CONVERTER_KEY = new Object();
+ private static final CustomStateKey<TrivialDateToISO8601CalendarFactory> DATE_TO_CAL_CONVERTER_KEY
+ = new CustomStateKey<TrivialDateToISO8601CalendarFactory>() {
+ @Override
+ protected TrivialDateToISO8601CalendarFactory create() {
+ return new TrivialDateToISO8601CalendarFactory();
+ }
+ };
+ private static final CustomStateKey<TrivialCalendarFieldsToDateConverter> CAL_TO_DATE_CONVERTER_KEY
+ = new CustomStateKey<TrivialCalendarFieldsToDateConverter>() {
+ @Override
+ protected TrivialCalendarFieldsToDateConverter create() {
+ return new TrivialCalendarFieldsToDateConverter();
+ }
+ };
protected ISOLikeTemplateDateFormatFactory() { }
public DateToISO8601CalendarFactory getISOBuiltInCalendar(Environment env) {
- DateToISO8601CalendarFactory r = (DateToISO8601CalendarFactory) env.getCustomState(DATE_TO_CAL_CONVERTER_KEY);
- if (r == null) {
- r = new TrivialDateToISO8601CalendarFactory();
- env.setCustomState(DATE_TO_CAL_CONVERTER_KEY, r);
- }
- return r;
+ return (DateToISO8601CalendarFactory) env.getCustomState(DATE_TO_CAL_CONVERTER_KEY);
}
public CalendarFieldsToDateConverter getCalendarFieldsToDateCalculator(Environment env) {
- CalendarFieldsToDateConverter r = (CalendarFieldsToDateConverter) env.getCustomState(CAL_TO_DATE_CONVERTER_KEY);
- if (r == null) {
- r = new TrivialCalendarFieldsToDateConverter();
- env.setCustomState(CAL_TO_DATE_CONVERTER_KEY, r);
- }
- return r;
+ return (CalendarFieldsToDateConverter) env.getCustomState(CAL_TO_DATE_CONVERTER_KEY);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java b/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
index 36773f4..f578158 100644
--- a/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
+++ b/src/main/java/org/apache/freemarker/dom/JaxenXPathSupport.java
@@ -31,7 +31,7 @@ import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
-import org.apache.freemarker.core.CustomAttribute;
+import org.apache.freemarker.core.CustomStateKey;
import org.apache.freemarker.core.Environment;
import org.apache.freemarker.core.Template;
import org.apache.freemarker.core.TemplateException;
@@ -42,6 +42,7 @@ import org.apache.freemarker.core.model.TemplateModelException;
import org.apache.freemarker.core.model.TemplateNumberModel;
import org.apache.freemarker.core.model.TemplateScalarModel;
import org.apache.freemarker.core.util.UndeclaredThrowableException;
+import org.apache.freemarker.core.util._ObjectHolder;
import org.jaxen.BaseXPath;
import org.jaxen.Function;
import org.jaxen.FunctionCallException;
@@ -62,14 +63,14 @@ import org.xml.sax.SAXException;
/**
*/
class JaxenXPathSupport implements XPathSupport {
-
- private static final CustomAttribute XPATH_CACHE_ATTR =
- new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE) {
- @Override
- protected Object create() {
- return new HashMap<String, BaseXPath>();
- }
- };
+
+ private static final CustomStateKey<Map<String, BaseXPath>> XPATH_CACHE_ATTR
+ = new CustomStateKey<Map<String, BaseXPath>>() {
+ @Override
+ protected Map<String, BaseXPath> create() {
+ return new HashMap<String, BaseXPath>();
+ }
+ };
// [2.4] Can't we just use Collections.emptyList()?
private final static ArrayList EMPTY_ARRAYLIST = new ArrayList();
@@ -78,7 +79,8 @@ class JaxenXPathSupport implements XPathSupport {
public TemplateModel executeQuery(Object context, String xpathQuery) throws TemplateModelException {
try {
BaseXPath xpath;
- Map<String, BaseXPath> xpathCache = (Map<String, BaseXPath>) XPATH_CACHE_ATTR.get();
+ Map<String, BaseXPath> xpathCache = Environment.getCurrentEnvironmentNotNull().getCurrentTemplateNotNull()
+ .getCustomState(XPATH_CACHE_ATTR);
synchronized (xpathCache) {
xpath = xpathCache.get(xpathQuery);
if (xpath == null) {
@@ -162,29 +164,38 @@ class JaxenXPathSupport implements XPathSupport {
/**
* Stores the the template parsed as {@link Document} in the template itself.
*/
- private static final CustomAttribute FM_DOM_NAVIAGOTOR_CACHED_DOM
- = new CustomAttribute(CustomAttribute.SCOPE_TEMPLATE);
+ private static final CustomStateKey<_ObjectHolder<Document>> FM_DOM_NAVIAGOTOR_CACHED_DOM
+ = new CustomStateKey<_ObjectHolder<Document>>() {
+ @Override
+ protected _ObjectHolder<Document> create() {
+ return new _ObjectHolder<>(null);
+ }
+ };
private static final Navigator FM_DOM_NAVIGATOR = new DocumentNavigator() {
@Override
public Object getDocument(String uri) throws FunctionCallException {
try {
Template raw = getTemplate(uri);
- Document doc = (Document) FM_DOM_NAVIAGOTOR_CACHED_DOM.get(raw);
- if (doc == null) {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setNamespaceAware(true);
- DocumentBuilder builder = factory.newDocumentBuilder();
- FmEntityResolver er = new FmEntityResolver();
- builder.setEntityResolver(er);
- doc = builder.parse(createInputSource(null, raw));
- // If the entity resolver got called 0 times, the document
- // is standalone, so we can safely cache it
- if (er.getCallCount() == 0) {
- FM_DOM_NAVIAGOTOR_CACHED_DOM.set(doc, raw);
+ _ObjectHolder<Document> docHolder = Environment.getCurrentEnvironmentNotNull()
+ .getCurrentTemplateNotNull().getCustomState(FM_DOM_NAVIAGOTOR_CACHED_DOM);
+ synchronized (docHolder) {
+ Document doc = docHolder.get();
+ if (doc == null) {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ FmEntityResolver er = new FmEntityResolver();
+ builder.setEntityResolver(er);
+ doc = builder.parse(createInputSource(null, raw));
+ // If the entity resolver got called 0 times, the document
+ // is standalone, so we can safely cache it
+ if (er.getCallCount() == 0) {
+ docHolder.set(doc);
+ }
}
+ return doc;
}
- return doc;
} catch (Exception e) {
throw new FunctionCallException("Failed to parse document for URI: " + uri, e);
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
index 0853133..48fcde5 100644
--- a/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
+++ b/src/main/java/org/apache/freemarker/servlet/FreemarkerServlet.java
@@ -41,7 +41,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.apache.freemarker.core.Configurable;
+import org.apache.freemarker.core.MutableProcessingConfiguration;
import org.apache.freemarker.core.Configuration;
import org.apache.freemarker.core.ConfigurationException;
import org.apache.freemarker.core.Environment;
@@ -199,16 +199,16 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
* {@value #INIT_PARAM_VALUE_FROM_TEMPLATE} (or some of the other options) instead. {@value #INIT_PARAM_VALUE_LEGACY}
* will use the charset of the template file to set the charset of the servlet response. Except, if the
* {@value #INIT_PARAM_CONTENT_TYPE} init-param contains a charset, it will use that instead. A quirk of this legacy
- * mode is that it's not aware of the {@link Configurable#getOutputEncoding()} FreeMarker setting, and thus never reads
+ * mode is that it's not aware of the {@link MutableProcessingConfiguration#getOutputEncoding()} FreeMarker setting, and thus never reads
* or writes it (though very few applications utilize that setting anyway). Also, it sets the charset of the servlet
* response by adding it to the response content type via calling {@link HttpServletResponse#setContentType(String)} (as
* that was the only way before Servlet 2.4), not via the more modern
* {@link HttpServletResponse#setCharacterEncoding(String)} method. Note that the charset of a template usually comes
- * from {@link Configuration#getDefaultEncoding()} (i.e., from the {@code default_encoding} FreeMarker setting),
+ * from {@link Configuration#getEncoding()} (i.e., from the {@code encoding} FreeMarker setting),
* or occasionally from {@link Configuration#getTemplateConfigurations()} (when FreeMarker was
* configured to use a specific charset for certain templates).
* <li>{@value #INIT_PARAM_VALUE_FROM_TEMPLATE}: This should be used in most applications, but it's not the default for
- * backward compatibility. It reads the {@link Configurable#getOutputEncoding()} setting of the template (note that the
+ * backward compatibility. It reads the {@link MutableProcessingConfiguration#getOutputEncoding()} setting of the template (note that the
* template usually just inherits that from the {@link Configuration}), and if that's not set, then reads the source
* charset of the template, just like {@value #INIT_PARAM_VALUE_LEGACY}, and if that's {@code null} (which happens if
* the template was loaded from a non-binary source) then it will be UTF-8. Then it passes the charset acquired this way
@@ -622,16 +622,16 @@ public class FreemarkerServlet extends HttpServlet {
try {
if (name.equals(DEPR_INITPARAM_OBJECT_WRAPPER)
- || name.equals(Configurable.OBJECT_WRAPPER_KEY)
+ || name.equals(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY)
|| name.equals(INIT_PARAM_TEMPLATE_PATH)
|| name.equals(Configuration.INCOMPATIBLE_IMPROVEMENTS_KEY)) {
// ignore: we have already processed these
} else if (name.equals(DEPR_INITPARAM_ENCODING)) { // BC
- if (getInitParameter(Configuration.DEFAULT_ENCODING_KEY) != null) {
+ if (getInitParameter(Configuration.ENCODING_KEY) != null) {
throw new ConflictingInitParamsException(
- Configuration.DEFAULT_ENCODING_KEY, DEPR_INITPARAM_ENCODING);
+ Configuration.ENCODING_KEY, DEPR_INITPARAM_ENCODING);
}
- config.setDefaultEncoding(value);
+ config.setEncoding(value);
} else if (name.equals(DEPR_INITPARAM_TEMPLATE_DELAY)) { // BC
if (getInitParameter(Configuration.TEMPLATE_UPDATE_DELAY_KEY) != null) {
throw new ConflictingInitParamsException(
@@ -643,9 +643,9 @@ public class FreemarkerServlet extends HttpServlet {
// Intentionally ignored
}
} else if (name.equals(DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER)) { // BC
- if (getInitParameter(Configurable.TEMPLATE_EXCEPTION_HANDLER_KEY) != null) {
+ if (getInitParameter(MutableProcessingConfiguration.TEMPLATE_EXCEPTION_HANDLER_KEY) != null) {
throw new ConflictingInitParamsException(
- Configurable.TEMPLATE_EXCEPTION_HANDLER_KEY, DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER);
+ MutableProcessingConfiguration.TEMPLATE_EXCEPTION_HANDLER_KEY, DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER);
}
if (DEPR_INITPARAM_TEMPLATE_EXCEPTION_HANDLER_RETHROW.equals(value)) {
@@ -1279,13 +1279,13 @@ public class FreemarkerServlet extends HttpServlet {
* should override {@link #createDefaultObjectWrapper()} instead. Overriding this method is necessary when you want
* to customize how the {@link ObjectWrapper} is created <em>from the init-param values</em>, or you want to do some
* post-processing (like checking) on the created {@link ObjectWrapper}. To customize init-param interpretation,
- * call {@link #getInitParameter(String)} with {@link Configurable#OBJECT_WRAPPER_KEY} as argument, and see if it
+ * call {@link #getInitParameter(String)} with {@link MutableProcessingConfiguration#OBJECT_WRAPPER_KEY} as argument, and see if it
* returns a value that you want to interpret yourself. If was {@code null} or you don't want to interpret the
* value, fall back to the super method.
*
* <p>
* The default implementation interprets the {@code object_wrapper} servlet init-param with
- * calling {@link Configurable#setSetting(String, String)} (see valid values there), or if there's no such servlet
+ * calling {@link MutableProcessingConfiguration#setSetting(String, String)} (see valid values there), or if there's no such servlet
* init-param, then it calls {@link #createDefaultObjectWrapper()}.
*
* @return The {@link ObjectWrapper} that will be used for adapting request, session, and servlet context attributes
@@ -1294,9 +1294,9 @@ public class FreemarkerServlet extends HttpServlet {
protected ObjectWrapperAndUnwrapper createObjectWrapper() {
String wrapper = getServletConfig().getInitParameter(DEPR_INITPARAM_OBJECT_WRAPPER);
if (wrapper != null) { // BC
- if (getInitParameter(Configurable.OBJECT_WRAPPER_KEY) != null) {
+ if (getInitParameter(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY) != null) {
throw new RuntimeException("Conflicting init-params: "
- + Configurable.OBJECT_WRAPPER_KEY + " and "
+ + MutableProcessingConfiguration.OBJECT_WRAPPER_KEY + " and "
+ DEPR_INITPARAM_OBJECT_WRAPPER);
}
if (DEPR_INITPARAM_WRAPPER_RESTRICTED.equals(wrapper)) {
@@ -1304,7 +1304,7 @@ public class FreemarkerServlet extends HttpServlet {
}
return createDefaultObjectWrapper();
} else {
- wrapper = getInitParameter(Configurable.OBJECT_WRAPPER_KEY);
+ wrapper = getInitParameter(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY);
if (wrapper == null) {
if (!config.isObjectWrapperExplicitlySet()) {
return createDefaultObjectWrapper();
@@ -1313,9 +1313,9 @@ public class FreemarkerServlet extends HttpServlet {
}
} else {
try {
- config.setSetting(Configurable.OBJECT_WRAPPER_KEY, wrapper);
+ config.setSetting(MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, wrapper);
} catch (ConfigurationException e) {
- throw new RuntimeException("Failed to set " + Configurable.OBJECT_WRAPPER_KEY, e);
+ throw new RuntimeException("Failed to set " + MutableProcessingConfiguration.OBJECT_WRAPPER_KEY, e);
}
return asObjectWrapperAndUnwrapper(config.getObjectWrapper());
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/053afbf5/src/manual/en_US/FM3-CHANGE-LOG.txt
----------------------------------------------------------------------
diff --git a/src/manual/en_US/FM3-CHANGE-LOG.txt b/src/manual/en_US/FM3-CHANGE-LOG.txt
index 5330a6a..9a149b3 100644
--- a/src/manual/en_US/FM3-CHANGE-LOG.txt
+++ b/src/manual/en_US/FM3-CHANGE-LOG.txt
@@ -170,4 +170,19 @@ the FreeMarer 3 changelog here:
again, the charset of a template file is independent of how you access it.)
- Removed Configuration.setEncoding(java.util.Locale, String) and the related other methods. Because of the new logic of template
encodings, the locale to encoding mapping doesn't make much sense anymore.
-- Require customLookupCondition-s to be Serializable.
\ No newline at end of file
+- Require customLookupCondition-s to be Serializable.
+- Various refactorings of Configurable and its subclasses. This is part of the preparation for making such classes immutable, and offer
+ builders to create them.
+ - Removed CustomAttribute class. Custom attribute keys can be anything at the moment (this will be certainly restricted later)
+ - As customAttributes won't be modifiable after Builder.build(), they can't be used for on-demand created data structures anymore (such as
+ Template-scoped caches) anymore. To fulfill that role, the CustomStateKey class and the CustomStateScope interface was introduced, which
+ is somewhat similar to the now removed CustomAttribute. CustomStateScope contains one method, Object getCustomState(CustomStateKey), which
+ may calls CustomStateKey.create() to lazily create the state object for the key. Configuration, Template and Environment implements
+ CustomStateScope.
+ - Added getter/setter to access custom attributes as a Map. (This is to make it less an exceptional setting.)
+ - Environment.setCustomState(Object, Object) and getCustomState(Object) was replaced with CustomStateScope.getCustomState(CustomStateKey).
+ - Added ProcessingConfiguration interface for the read-only access of template processing settings. This is similar to the
+ already existing (in FM2) ParserConfiguration interface.
+ - Renamed Configurable to MutableProcessingAndParserConfiguration. Made it abstract too.
+ - Renamed Configuration.defaultEncoding to encoding, also added encoding ParserConfiguration. Before this, defaultEncoding was exclusive
+ to Configuration, but now it's like any other ParserConfiguration setting.
\ No newline at end of file