Removed the need for a static default Configuration instance.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/c9719cbc Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/c9719cbc Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/c9719cbc Branch: refs/heads/3 Commit: c9719cbc4a21769503f24932f3eac9eceb1bab86 Parents: d4dddeb Author: ddekany <[email protected]> Authored: Mon Feb 20 22:48:11 2017 +0100 Committer: ddekany <[email protected]> Committed: Mon Feb 20 22:48:11 2017 +0100 ---------------------------------------------------------------------- .../org/apache/freemarker/core/Template.java | 37 +-- .../core/ast/TemplateConfiguration.java | 326 ++++++++++++++++++- .../freemarker/servlet/jsp/FreemarkerTag.java | 138 -------- .../freemarker/core/NullConfigurationTest.java | 35 -- .../core/TemplateConstructorsTest.java | 7 - 5 files changed, 315 insertions(+), 228 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c9719cbc/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 1f7c83a..d9fa398 100644 --- a/src/main/java/org/apache/freemarker/core/Template.java +++ b/src/main/java/org/apache/freemarker/core/Template.java @@ -114,17 +114,16 @@ public class Template extends Configurable { * delegate directly or indirectly. */ private Template(String name, String sourceName, Configuration cfg, ParserConfiguration customParserConfiguration) { - super(toNonNull(cfg)); + super(cfg); + if (cfg == null) { + throw new IllegalArgumentException("\"cfg\" can't be null"); + } this.name = name; this.sourceName = sourceName; - templateLanguageVersion = normalizeTemplateLanguageVersion(toNonNull(cfg).getIncompatibleImprovements()); + templateLanguageVersion = normalizeTemplateLanguageVersion(cfg.getIncompatibleImprovements()); parserConfiguration = customParserConfiguration != null ? customParserConfiguration : getConfiguration(); } - private static Configuration toNonNull(Configuration cfg) { - return cfg != null ? cfg : Configuration.getDefaultConfiguration(); - } - /** * Same as {@link #Template(String, String, Reader, Configuration)} with {@code null} {@code sourceName} parameter. */ @@ -306,32 +305,6 @@ public class Template extends Configurable { namespaceURIToPrefixLookup = Collections.unmodifiableMap(namespaceURIToPrefixLookup); prefixToNamespaceURILookup = Collections.unmodifiableMap(prefixToNamespaceURILookup); } - - /** - * Equivalent to {@link #Template(String, Reader, Configuration) - * Template(name, reader, null)}. - * - * @deprecated This constructor uses the "default" {@link Configuration} - * instance, which can easily lead to erroneous, unpredictable behavior. - * See more {@link Configuration#getDefaultConfiguration() here...}. - */ - @Deprecated - public Template(String name, Reader reader) throws IOException { - this(name, reader, null); - } - - /** - * Only meant to be used internally. - * - * @deprecated Has problems setting actualTagSyntax and templateLanguageVersion; will be removed in 2.4. - */ - @Deprecated - // [2.4] remove this - Template(String name, TemplateElement rootElement, Configuration cfg) { - this(name, null, cfg, (ParserConfiguration) null); - this.rootElement = rootElement; - DebuggerService.registerTemplate(this); - } /** * Same as {@link #getPlainTextTemplate(String, String, String, Configuration)} with {@code null} {@code sourceName} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c9719cbc/src/main/java/org/apache/freemarker/core/ast/TemplateConfiguration.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/core/ast/TemplateConfiguration.java b/src/main/java/org/apache/freemarker/core/ast/TemplateConfiguration.java index c106859..21e5e50 100644 --- a/src/main/java/org/apache/freemarker/core/ast/TemplateConfiguration.java +++ b/src/main/java/org/apache/freemarker/core/ast/TemplateConfiguration.java @@ -22,12 +22,16 @@ import java.io.Reader; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.TimeZone; import org.apache.freemarker.core.Configuration; import org.apache.freemarker.core.Template; +import org.apache.freemarker.core.TemplateExceptionHandler; import org.apache.freemarker.core.Version; import org.apache.freemarker.core._TemplateAPI; +import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver; import org.apache.freemarker.core.util._NullArgumentException; @@ -76,7 +80,6 @@ import org.apache.freemarker.core.util._NullArgumentException; */ public final class TemplateConfiguration extends Configurable implements ParserConfiguration { - private boolean parentConfigurationSet; private Integer tagSyntax; private Integer namingConvention; private Boolean whitespaceStripping; @@ -87,12 +90,12 @@ public final class TemplateConfiguration extends Configurable implements ParserC private Integer tabSize; /** - * Creates a new instance. The parent will be {@link Configuration#getDefaultConfiguration()} initially, but it will + * Creates a new instance. The parent will be {@code null} initially, but it will * be changed to the real parent {@link Configuration} when this object is added to the {@link Configuration}. (It's * not allowed to add the same instance to multiple {@link Configuration}-s). */ public TemplateConfiguration() { - super(Configuration.getDefaultConfiguration()); + super((Configuration) null); } /** @@ -105,8 +108,9 @@ public final class TemplateConfiguration extends Configurable implements ParserC throw new IllegalArgumentException("The parent of a TemplateConfiguration can only be a Configuration"); } - if (parentConfigurationSet) { - if (getParent() != cfg) { + Configurable parent = getParent(); + if (parent != null) { + if (parent != cfg) { throw new IllegalStateException( "This TemplateConfiguration is already associated with a different Configuration instance."); } @@ -114,7 +118,6 @@ public final class TemplateConfiguration extends Configurable implements ParserC } super.setParent(cfg); - parentConfigurationSet = true; } /** @@ -137,12 +140,15 @@ public final class TemplateConfiguration extends Configurable implements ParserC * Returns the parent {@link Configuration}, or {@code null} if none was associated yet. */ public Configuration getParentConfiguration() { - return parentConfigurationSet ? (Configuration) getParent() : null; + return (Configuration) getParent(); } private Configuration getNonNullParentConfiguration() { - checkParentConfigurationSet(); - return (Configuration) getParent(); + Configurable parent = getParent(); + if (parent == null) { + throw new IllegalStateException("The TemplateConfiguration wasn't associated with a Configuration yet."); + } + return (Configuration) parent; } /** @@ -167,10 +173,12 @@ public final class TemplateConfiguration extends Configurable implements ParserC setBooleanFormat(tc.getBooleanFormat()); } if (tc.isCustomDateFormatsSet()) { - setCustomDateFormats(mergeMaps(getCustomDateFormats(), tc.getCustomDateFormats(), false)); + setCustomDateFormats(mergeMaps( + isCustomDateFormatsSet() ? getCustomDateFormats() : null, tc.getCustomDateFormats(), false)); } if (tc.isCustomNumberFormatsSet()) { - setCustomNumberFormats(mergeMaps(getCustomNumberFormats(), tc.getCustomNumberFormats(), false)); + setCustomNumberFormats(mergeMaps( + isCustomNumberFormatsSet() ? getCustomNumberFormats() : null, tc.getCustomNumberFormats(), false)); } if (tc.isDateFormatSet()) { setDateFormat(tc.getDateFormat()); @@ -242,10 +250,10 @@ public final class TemplateConfiguration extends Configurable implements ParserC setLazyAutoImports(tc.getLazyAutoImports()); } if (tc.isAutoImportsSet()) { - setAutoImports(mergeMaps(getAutoImports(), tc.getAutoImports(), true)); + setAutoImports(mergeMaps(isAutoImportsSet() ? getAutoImports() : null, tc.getAutoImports(), true)); } if (tc.isAutoIncludesSet()) { - setAutoIncludes(mergeLists(getAutoIncludes(), tc.getAutoIncludes())); + setAutoIncludes(mergeLists(isAutoIncludesSet() ? getAutoIncludes() : null, tc.getAutoIncludes())); } tc.copyDirectCustomAttributes(this, true); @@ -567,10 +575,296 @@ public final class TemplateConfiguration extends Configurable implements ParserC public Version getIncompatibleImprovements() { return getNonNullParentConfiguration().getIncompatibleImprovements(); } + + - private void checkParentConfigurationSet() { - if (!parentConfigurationSet) { - throw new IllegalStateException("The TemplateConfiguration wasn't associated with a Configuration yet."); + @Override + public Locale getLocale() { + try { + return super.getLocale(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public TimeZone getTimeZone() { + try { + return super.getTimeZone(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public TimeZone getSQLDateAndTimeTimeZone() { + try { + return super.getSQLDateAndTimeTimeZone(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getNumberFormat() { + try { + return super.getNumberFormat(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public Map<String, ? extends TemplateNumberFormatFactory> getCustomNumberFormats() { + try { + return super.getCustomNumberFormats(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public TemplateNumberFormatFactory getCustomNumberFormat(String name) { + try { + return super.getCustomNumberFormat(name); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public boolean hasCustomFormats() { + try { + return super.hasCustomFormats(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getBooleanFormat() { + try { + return super.getBooleanFormat(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getTimeFormat() { + try { + return super.getTimeFormat(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getDateFormat() { + try { + return super.getDateFormat(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getDateTimeFormat() { + try { + return super.getDateTimeFormat(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public Map<String, ? extends TemplateDateFormatFactory> getCustomDateFormats() { + try { + return super.getCustomDateFormats(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public TemplateDateFormatFactory getCustomDateFormat(String name) { + try { + return super.getCustomDateFormat(name); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public TemplateExceptionHandler getTemplateExceptionHandler() { + try { + return super.getTemplateExceptionHandler(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public ArithmeticEngine getArithmeticEngine() { + try { + return super.getArithmeticEngine(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public ObjectWrapper getObjectWrapper() { + try { + return super.getObjectWrapper(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getOutputEncoding() { + try { + return super.getOutputEncoding(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String getURLEscapingCharset() { + try { + return super.getURLEscapingCharset(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public TemplateClassResolver getNewBuiltinClassResolver() { + try { + return super.getNewBuiltinClassResolver(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public boolean getAutoFlush() { + try { + return super.getAutoFlush(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public boolean getShowErrorTips() { + try { + return super.getShowErrorTips(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public boolean isAPIBuiltinEnabled() { + try { + return super.isAPIBuiltinEnabled(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public boolean getLogTemplateExceptions() { + try { + return super.getLogTemplateExceptions(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public boolean getLazyImports() { + try { + return super.getLazyImports(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public Boolean getLazyAutoImports() { + try { + return super.getLazyAutoImports(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public Map<String, String> getAutoImports() { + try { + return super.getAutoImports(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public List<String> getAutoIncludes() { + try { + return super.getAutoIncludes(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public String[] getCustomAttributeNames() { + try { + return super.getCustomAttributeNames(); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; + } + } + + @Override + public Object getCustomAttribute(String name) { + try { + return super.getCustomAttribute(name); + } catch (NullPointerException e) { + getNonNullParentConfiguration(); + throw e; } } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c9719cbc/src/main/java/org/apache/freemarker/servlet/jsp/FreemarkerTag.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/freemarker/servlet/jsp/FreemarkerTag.java b/src/main/java/org/apache/freemarker/servlet/jsp/FreemarkerTag.java deleted file mode 100644 index da77b7d..0000000 --- a/src/main/java/org/apache/freemarker/servlet/jsp/FreemarkerTag.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.servlet.jsp; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.jsp.JspException; -import javax.servlet.jsp.PageContext; -import javax.servlet.jsp.tagext.BodyContent; -import javax.servlet.jsp.tagext.BodyTag; -import javax.servlet.jsp.tagext.Tag; - -import org.apache.freemarker.core.Template; -import org.apache.freemarker.core.model.impl.SimpleHash; - -/** - * Simple implementation of JSP tag to allow use of FreeMarker templates in - * JSP. Inspired by similar class in Velocity template engine developed by - * <a href="mailto:[email protected]">Geir Magnusson Jr.</a> - */ -public class FreemarkerTag implements BodyTag { - private Tag parent; - private BodyContent bodyContent; - private PageContext pageContext; - private SimpleHash root; - private Template template; - private boolean caching = true; - private String name = ""; - - public boolean getCaching() { - return caching; - } - - public void setCaching(boolean caching) { - this.caching = caching; - } - - public void setName(String name) { - this.name = name == null ? "" : name; - } - - @Override - public Tag getParent() { - return parent; - } - - @Override - public void setParent(Tag parent) { - this.parent = parent; - } - - @Override - public int doStartTag() { - return EVAL_BODY_BUFFERED; - } - - @Override - public void setBodyContent(BodyContent bodyContent) { - this.bodyContent = bodyContent; - } - - @Override - public void setPageContext(PageContext pageContext) { - this.pageContext = pageContext; - root = null; - } - - @Override - public void doInitBody() { - } - - @Override - public int doAfterBody() { - return SKIP_BODY; - } - - @Override - public void release() { - root = null; - template = null; - name = ""; - } - - @Override - public int doEndTag() - throws JspException { - if (bodyContent == null) - return EVAL_PAGE; - - try { - if (template == null) { - template = new Template(name, bodyContent.getReader()); - } - - if (root == null) { - root = new SimpleHash(); - root.put("page", new JspContextModel(pageContext, JspContextModel.PAGE_SCOPE)); - root.put("request", new JspContextModel(pageContext, JspContextModel.REQUEST_SCOPE)); - root.put("session", new JspContextModel(pageContext, JspContextModel.SESSION_SCOPE)); - root.put("application", new JspContextModel(pageContext, JspContextModel.APPLICATION_SCOPE)); - root.put("any", new JspContextModel(pageContext, JspContextModel.ANY_SCOPE)); - } - template.process(root, pageContext.getOut()); - } catch (Exception e) { - try { - pageContext.handlePageException(e); - } catch (ServletException e2) { - throw new JspException(e2.getMessage()); - } catch (IOException e2) { - throw new JspException(e2.getMessage()); - } - } finally { - if (!caching) { - template = null; - } - } - - return EVAL_PAGE; - } -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c9719cbc/src/test/java/org/apache/freemarker/core/NullConfigurationTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/NullConfigurationTest.java b/src/test/java/org/apache/freemarker/core/NullConfigurationTest.java deleted file mode 100644 index 6f81b52..0000000 --- a/src/test/java/org/apache/freemarker/core/NullConfigurationTest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.freemarker.core; - -import java.io.IOException; -import java.io.StringReader; - -import org.apache.freemarker.core.Template; -import org.junit.Test; - -public class NullConfigurationTest { - - @Test - public void testTemplateNPEBug() throws IOException { - new Template("legacy", new StringReader("foo")); - } - -} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c9719cbc/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java b/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java index 5e93fef..61b936e 100644 --- a/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java +++ b/src/test/java/org/apache/freemarker/core/TemplateConstructorsTest.java @@ -45,13 +45,6 @@ public class TemplateConstructorsTest { final String content = "From a String..."; final String encoding = "UTF-16LE"; { - Template t = new Template(name, createReader()); - assertEquals(name, t.getName()); - assertEquals(name, t.getSourceName()); - assertEquals(READER_CONTENT, t.toString()); - assertNull(t.getEncoding()); - } - { Template t = new Template(name, createReader(), cfg); assertEquals(name, t.getName()); assertEquals(name, t.getSourceName());
