This is an automated email from the ASF dual-hosted git repository. ddekany pushed a commit to branch 3 in repository https://gitbox.apache.org/repos/asf/freemarker.git
commit f27a127666c37e8400d8dd4cf079247e9e25605d Author: ddekany <[email protected]> AuthorDate: Sat Dec 31 23:46:38 2022 +0100 Forward ported from 2.3-gae: FREEMARKER-198: To avoid deadlock when class initialization happens on multiple threads (like _TemplateAPI->DefaultObjectWrapper, and DefaultObjectWrapper->_TemplateAPI), factored out static fields from _TemplateAPI into their owns classes. --- .../apache/freemarker/core/ConfigurationTest.java | 85 ++++++---------------- .../core/model/impl/DefaultObjectWrapperTest.java | 60 +++------------ .../org/apache/freemarker/core/NativeSequence.java | 10 +-- .../java/org/apache/freemarker/core/_CoreAPI.java | 6 +- .../org/apache/freemarker/core/_VersionInts.java | 32 ++++++++ 5 files changed, 75 insertions(+), 118 deletions(-) diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java index 8c1791de..f5486e5b 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/ConfigurationTest.java @@ -19,42 +19,11 @@ package org.apache.freemarker.core; -import static org.apache.freemarker.core.Configuration.*; -import static org.apache.freemarker.core.Configuration.ExtendableBuilder.*; -import static org.apache.freemarker.test.hamcerst.Matchers.*; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - -import java.io.File; -import java.io.IOException; -import java.io.Serializable; -import java.io.StringWriter; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; -import java.util.TreeSet; - -import org.apache.freemarker.core.Configuration.*; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import org.apache.freemarker.core.model.TemplateHashModel; import org.apache.freemarker.core.model.TemplateStringModel; -import org.apache.freemarker.core.model.impl.DefaultObjectWrapper; -import org.apache.freemarker.core.model.impl.MemberAccessPolicy; -import org.apache.freemarker.core.model.impl.MemberSelectorListMemberAccessPolicy; -import org.apache.freemarker.core.model.impl.RestrictedObjectWrapper; -import org.apache.freemarker.core.model.impl.SimpleString; -import org.apache.freemarker.core.model.impl.WhitelistMemberAccessPolicy; +import org.apache.freemarker.core.model.impl.*; import org.apache.freemarker.core.outputformat.MarkupOutputFormat; import org.apache.freemarker.core.outputformat.OutputFormat; import org.apache.freemarker.core.outputformat.UnregisteredOutputFormatException; @@ -62,31 +31,9 @@ import org.apache.freemarker.core.outputformat.impl.CombinedMarkupOutputFormat; import org.apache.freemarker.core.outputformat.impl.HTMLOutputFormat; import org.apache.freemarker.core.outputformat.impl.RTFOutputFormat; import org.apache.freemarker.core.outputformat.impl.XMLOutputFormat; -import org.apache.freemarker.core.templateresolver.CacheStorageWithGetSize; -import org.apache.freemarker.core.templateresolver.ConditionalTemplateConfigurationFactory; -import org.apache.freemarker.core.templateresolver.FileNameGlobMatcher; -import org.apache.freemarker.core.templateresolver.TemplateConfigurationFactory; -import org.apache.freemarker.core.templateresolver.TemplateConfigurationFactoryException; -import org.apache.freemarker.core.templateresolver.TemplateLookupContext; -import org.apache.freemarker.core.templateresolver.TemplateLookupResult; -import org.apache.freemarker.core.templateresolver.TemplateLookupStrategy; -import org.apache.freemarker.core.templateresolver.impl.ByteArrayTemplateLoader; -import org.apache.freemarker.core.templateresolver.impl.ClassTemplateLoader; -import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateLookupStrategy; -import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateNameFormat; -import org.apache.freemarker.core.templateresolver.impl.DefaultTemplateResolver; -import org.apache.freemarker.core.templateresolver.impl.NullCacheStorage; -import org.apache.freemarker.core.templateresolver.impl.SoftCacheStorage; -import org.apache.freemarker.core.templateresolver.impl.StringTemplateLoader; -import org.apache.freemarker.core.templateresolver.impl.StrongCacheStorage; -import org.apache.freemarker.core.userpkg.BaseNTemplateNumberFormatFactory; -import org.apache.freemarker.core.userpkg.CustomHTMLOutputFormat; -import org.apache.freemarker.core.userpkg.DummyOutputFormat; -import org.apache.freemarker.core.userpkg.EpochMillisDivTemplateDateFormatFactory; -import org.apache.freemarker.core.userpkg.EpochMillisTemplateDateFormatFactory; -import org.apache.freemarker.core.userpkg.HexTemplateNumberFormatFactory; -import org.apache.freemarker.core.userpkg.NameClashingDummyOutputFormat; -import org.apache.freemarker.core.userpkg.SeldomEscapedOutputFormat; +import org.apache.freemarker.core.templateresolver.*; +import org.apache.freemarker.core.templateresolver.impl.*; +import org.apache.freemarker.core.userpkg.*; import org.apache.freemarker.core.util._CollectionUtils; import org.apache.freemarker.core.util._DateUtils; import org.apache.freemarker.core.util._NullWriter; @@ -94,8 +41,22 @@ import org.apache.freemarker.core.valueformat.TemplateDateFormatFactory; import org.apache.freemarker.core.valueformat.TemplateNumberFormatFactory; import org.junit.Test; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; + +import static org.apache.freemarker.core.Configuration.*; +import static org.apache.freemarker.core.Configuration.ExtendableBuilder.*; +import static org.apache.freemarker.test.hamcerst.Matchers.containsStringIgnoringCase; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; public class ConfigurationTest { @@ -223,7 +184,7 @@ public class ConfigurationTest { @Test public void testVersion() { Version v = getVersion(); - assertTrue(v.intValue() >= _CoreAPI.VERSION_INT_3_0_0); + assertTrue(v.intValue() >= _VersionInts.VERSION_INT_3_0_0); try { new Builder(new Version(999, 1, 2)).build(); diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java index 010705c2..80d8096b 100644 --- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java +++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/model/impl/DefaultObjectWrapperTest.java @@ -19,57 +19,21 @@ package org.apache.freemarker.core.model.impl; -import static org.apache.freemarker.test.hamcerst.Matchers.*; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; -import java.util.Vector; - -import org.apache.freemarker.core.Configuration; -import org.apache.freemarker.core.NonTemplateCallPlace; -import org.apache.freemarker.core.Template; -import org.apache.freemarker.core.TemplateException; -import org.apache.freemarker.core.Version; -import org.apache.freemarker.core._CoreAPI; -import org.apache.freemarker.core.model.AdapterTemplateModel; -import org.apache.freemarker.core.model.ObjectWrapper; -import org.apache.freemarker.core.model.ObjectWrappingException; -import org.apache.freemarker.core.model.TemplateBooleanModel; -import org.apache.freemarker.core.model.TemplateCollectionModel; -import org.apache.freemarker.core.model.TemplateHashModel; -import org.apache.freemarker.core.model.TemplateHashModelEx; -import org.apache.freemarker.core.model.TemplateIterableModel; -import org.apache.freemarker.core.model.TemplateModel; -import org.apache.freemarker.core.model.TemplateModelIterator; -import org.apache.freemarker.core.model.TemplateModelWithAPISupport; -import org.apache.freemarker.core.model.TemplateNumberModel; -import org.apache.freemarker.core.model.TemplateSequenceModel; -import org.apache.freemarker.core.model.TemplateStringModel; -import org.apache.freemarker.core.model.WrapperTemplateModel; -import org.apache.freemarker.core.model.WrappingTemplateModel; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import org.apache.freemarker.core.*; +import org.apache.freemarker.core.model.*; import org.apache.freemarker.core.util.CallableUtils; import org.apache.freemarker.test.TestConfigurationBuilder; import org.junit.Test; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; + +import static org.apache.freemarker.test.hamcerst.Matchers.containsStringIgnoringCase; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; public class DefaultObjectWrapperTest { @@ -83,7 +47,7 @@ public class DefaultObjectWrapperTest { expected.add(Configuration.VERSION_3_0_0); List<Version> actual = new ArrayList<>(); - int i = _CoreAPI.VERSION_INT_3_0_0; + int i = _VersionInts.VERSION_INT_3_0_0; while (i <= Configuration.getVersion().intValue()) { int major = i / 1000000; int minor = i % 1000000 / 1000; diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java b/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java index a56febfc..cf99ea0e 100644 --- a/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java +++ b/freemarker-core/src/main/java/org/apache/freemarker/core/NativeSequence.java @@ -19,17 +19,17 @@ package org.apache.freemarker.core; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collection; - import org.apache.freemarker.core.model.ObjectWrapper; import org.apache.freemarker.core.model.TemplateModel; import org.apache.freemarker.core.model.TemplateModelIterator; import org.apache.freemarker.core.model.TemplateSequenceModel; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; + /** - * A sequence where each items is already a {@link TemplateModel}, so no {@link ObjectWrapper} need to be specified. + * A sequence where each item is already a {@link TemplateModel}, so no {@link ObjectWrapper} need to be specified. * * <p>While this class allows adding items, doing so is not thread-safe, and thus only meant to be done during the * initialization of the sequence. diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java index 14de157d..b408c9e1 100644 --- a/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java +++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_CoreAPI.java @@ -28,8 +28,8 @@ import org.apache.freemarker.core.util._NullArgumentException; * access things inside this package that users shouldn't. */ public final class _CoreAPI { - - public static final int VERSION_INT_3_0_0 = Configuration.VERSION_3_0_0.intValue(); + // ATTENTION! Don't refer to other classes in the static initializer of this class! Fields that need that must be + // moved into a separate class, to avoid class init deadlocks. // Can't be instantiated private _CoreAPI() { } @@ -66,7 +66,7 @@ public final class _CoreAPI { + incompatibleImprovements + ", but the installed FreeMarker version is only " + Configuration.getVersion() + ". You may need to upgrade FreeMarker in your project."); } - if (iciV < VERSION_INT_3_0_0) { + if (iciV < _VersionInts.VERSION_INT_3_0_0) { throw new IllegalArgumentException("\"incompatibleImprovements\" must be at least 3.0.0, but was " + incompatibleImprovements); } diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/_VersionInts.java b/freemarker-core/src/main/java/org/apache/freemarker/core/_VersionInts.java new file mode 100644 index 00000000..711f4c3c --- /dev/null +++ b/freemarker-core/src/main/java/org/apache/freemarker/core/_VersionInts.java @@ -0,0 +1,32 @@ +/* + * 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; + +/** + * 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. + */ +// Because we refer to other classes in the static initializer of this class, be careful with referring this class in +// the static initializers of other classes, as that can lead to deadlock if the class initialization locks are acquired +// by the JVM in different orders! This is also why this was extracted from _CoreAPI. +public class _VersionInts { + public static final int VERSION_INT_3_0_0 = Configuration.VERSION_3_0_0.intValue(); +}
