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/10/03 19:31:44 UTC
[1/6] incubator-freemarker git commit: Slight modification to spare
the extra pd.getReadMethod() when we have an IndexedPropertyDescriptor and
preferIndexedReadMethod is false.
Repository: incubator-freemarker
Updated Branches:
refs/heads/2.3 8f56810ff -> f73b8447c
Slight modification to spare the extra pd.getReadMethod() when we have an IndexedPropertyDescriptor and preferIndexedReadMethod is false.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/a072921d
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/a072921d
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/a072921d
Branch: refs/heads/2.3
Commit: a072921d212e63ddb6bff6ec71b95509d6c91e9f
Parents: 66af279
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 15:24:20 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 15:24:20 2017 +0200
----------------------------------------------------------------------
src/main/java/freemarker/ext/beans/BeanModel.java | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/a072921d/src/main/java/freemarker/ext/beans/BeanModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeanModel.java b/src/main/java/freemarker/ext/beans/BeanModel.java
index 4139b09..01d779a 100644
--- a/src/main/java/freemarker/ext/beans/BeanModel.java
+++ b/src/main/java/freemarker/ext/beans/BeanModel.java
@@ -220,14 +220,15 @@ implements
TemplateModel resultModel = UNKNOWN;
if (desc instanceof IndexedPropertyDescriptor) {
IndexedPropertyDescriptor pd = (IndexedPropertyDescriptor) desc;
- if (!wrapper.getPreferIndexedReadMethod() && pd.getReadMethod() != null) {
- resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
+ Method readMethod;
+ if (!wrapper.getPreferIndexedReadMethod() && (readMethod = pd.getReadMethod()) != null) {
+ resultModel = wrapper.invokeMethod(object, readMethod, null);
// cachedModel remains null, as we don't cache these
} else {
- Method readMethod = pd.getIndexedReadMethod();
+ Method indexedReadMethod = pd.getIndexedReadMethod();
resultModel = cachedModel =
- new SimpleMethodModel(object, readMethod,
- ClassIntrospector.getArgTypes(classInfo, readMethod), wrapper);
+ new SimpleMethodModel(object, indexedReadMethod,
+ ClassIntrospector.getArgTypes(classInfo, indexedReadMethod), wrapper);
}
} else if (desc instanceof PropertyDescriptor) {
PropertyDescriptor pd = (PropertyDescriptor) desc;
[4/6] incubator-freemarker git commit: FREEMARKER-80: Avoid calling
synchonized PropertyDescriptor.getReadMethod() when getting a property in a
template. Will see if it matters.
Posted by dd...@apache.org.
FREEMARKER-80: Avoid calling synchonized PropertyDescriptor.getReadMethod() when getting a property in a template. Will see if it matters.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/8f787963
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/8f787963
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/8f787963
Branch: refs/heads/2.3
Commit: 8f787963600b5ebaafd39bbdcc10121d8f82ce9a
Parents: c01f1a2
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 19:53:49 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 19:54:15 2017 +0200
----------------------------------------------------------------------
.../java/freemarker/ext/beans/BeanModel.java | 33 +++++-----
.../freemarker/ext/beans/ClassIntrospector.java | 64 +++++++-------------
.../ext/beans/FastPropertyDescriptor.java | 46 ++++++++++++++
3 files changed, 84 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8f787963/src/main/java/freemarker/ext/beans/BeanModel.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeanModel.java b/src/main/java/freemarker/ext/beans/BeanModel.java
index 01d779a..1f885fa 100644
--- a/src/main/java/freemarker/ext/beans/BeanModel.java
+++ b/src/main/java/freemarker/ext/beans/BeanModel.java
@@ -19,8 +19,6 @@
package freemarker.ext.beans;
-import java.beans.IndexedPropertyDescriptor;
-import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -63,8 +61,7 @@ import freemarker.template.utility.StringUtil;
*/
public class BeanModel
-implements
- TemplateHashModelEx, AdapterTemplateModel, WrapperTemplateModel, TemplateModelWithAPISupport {
+implements TemplateHashModelEx, AdapterTemplateModel, WrapperTemplateModel, TemplateModelWithAPISupport {
private static final Logger LOG = Logger.getLogger("freemarker.beans");
protected final Object object;
protected final BeansWrapper wrapper;
@@ -218,22 +215,22 @@ implements
}
TemplateModel resultModel = UNKNOWN;
- if (desc instanceof IndexedPropertyDescriptor) {
- IndexedPropertyDescriptor pd = (IndexedPropertyDescriptor) desc;
- Method readMethod;
- if (!wrapper.getPreferIndexedReadMethod() && (readMethod = pd.getReadMethod()) != null) {
- resultModel = wrapper.invokeMethod(object, readMethod, null);
- // cachedModel remains null, as we don't cache these
+ if (desc instanceof FastPropertyDescriptor) {
+ FastPropertyDescriptor pd = (FastPropertyDescriptor) desc;
+ Method indexedReadMethod = pd.getIndexedReadMethod();
+ if (indexedReadMethod != null) {
+ if (!wrapper.getPreferIndexedReadMethod() && (pd.getReadMethod()) != null) {
+ resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
+ // cachedModel remains null, as we don't cache these
+ } else {
+ resultModel = cachedModel =
+ new SimpleMethodModel(object, indexedReadMethod,
+ ClassIntrospector.getArgTypes(classInfo, indexedReadMethod), wrapper);
+ }
} else {
- Method indexedReadMethod = pd.getIndexedReadMethod();
- resultModel = cachedModel =
- new SimpleMethodModel(object, indexedReadMethod,
- ClassIntrospector.getArgTypes(classInfo, indexedReadMethod), wrapper);
+ resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
+ // cachedModel remains null, as we don't cache these
}
- } else if (desc instanceof PropertyDescriptor) {
- PropertyDescriptor pd = (PropertyDescriptor) desc;
- resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null);
- // cachedModel remains null, as we don't cache these
} else if (desc instanceof Field) {
resultModel = wrapper.wrap(((Field) desc).get(object));
// cachedModel remains null, as we don't cache these
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8f787963/src/main/java/freemarker/ext/beans/ClassIntrospector.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/ClassIntrospector.java b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
index 72e8855..ce8bbd3 100644
--- a/src/main/java/freemarker/ext/beans/ClassIntrospector.java
+++ b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
@@ -218,7 +218,7 @@ class ClassIntrospector {
* Gets the class introspection data from {@link #cache}, automatically creating the cache entry if it's missing.
*
* @return A {@link Map} where each key is a property/method/field name (or a special {@link Object} key like
- * {@link #CONSTRUCTORS_KEY}), each value is a {@link PropertyDescriptor} or {@link Method} or
+ * {@link #CONSTRUCTORS_KEY}), each value is a {@link FastPropertyDescriptor} or {@link Method} or
* {@link OverloadedMethods} or {@link Field} (but better check the source code...).
*/
Map<Object, Object> get(Class<?> clazz) {
@@ -335,8 +335,7 @@ class ClassIntrospector {
int mdsSize = mds.size();
IdentityHashMap<Method, Void> argTypesUsedByIndexerPropReaders = null;
for (int i = mdsSize - 1; i >= 0; --i) {
- final MethodDescriptor md = mds.get(i);
- final Method method = getMatchingAccessibleMethod(md.getMethod(), accessibleMethods);
+ final Method method = getMatchingAccessibleMethod(mds.get(i).getMethod(), accessibleMethods);
if (method != null && isAllowedToExpose(method)) {
decision.setDefaults(method);
if (methodAppearanceFineTuner != null) {
@@ -350,7 +349,7 @@ class ClassIntrospector {
}
PropertyDescriptor propDesc = decision.getExposeAsProperty();
- if (propDesc != null && !(introspData.get(propDesc.getName()) instanceof PropertyDescriptor)) {
+ if (propDesc != null && !(introspData.get(propDesc.getName()) instanceof FastPropertyDescriptor)) {
addPropertyDescriptorToClassIntrospectionData(
introspData, propDesc, clazz, accessibleMethods);
}
@@ -373,7 +372,7 @@ class ClassIntrospector {
// Already overloaded method - add new overload
((OverloadedMethods) previous).addMethod(method);
} else if (decision.getMethodShadowsProperty()
- || !(previous instanceof PropertyDescriptor)) {
+ || !(previous instanceof FastPropertyDescriptor)) {
// Simple method (this far)
introspData.put(methodKey, method);
Class<?>[] replaced = getArgTypesByMethod(introspData).put(method,
@@ -661,45 +660,28 @@ class ClassIntrospector {
private void addPropertyDescriptorToClassIntrospectionData(Map<Object, Object> introspData,
PropertyDescriptor pd, Class<?> clazz, Map<MethodSignature, List<Method>> accessibleMethods) {
+ Method readMethod = getMatchingAccessibleMethod(pd.getReadMethod(), accessibleMethods);
+ if (readMethod != null && !isAllowedToExpose(readMethod)) {
+ readMethod = null;
+ }
+
+ Method indexedReadMethod;
if (pd instanceof IndexedPropertyDescriptor) {
- IndexedPropertyDescriptor ipd =
- (IndexedPropertyDescriptor) pd;
- Method readMethod = ipd.getIndexedReadMethod();
- Method publicReadMethod = getMatchingAccessibleMethod(readMethod, accessibleMethods);
- if (publicReadMethod != null && isAllowedToExpose(publicReadMethod)) {
- try {
- if (readMethod != publicReadMethod) {
- ipd = new IndexedPropertyDescriptor(
- ipd.getName(), ipd.getReadMethod(),
- null, publicReadMethod,
- null);
- }
- introspData.put(ipd.getName(), ipd);
- getArgTypesByMethod(introspData).put(publicReadMethod, publicReadMethod.getParameterTypes());
- } catch (IntrospectionException e) {
- LOG.warn("Failed creating a publicly-accessible " +
- "property descriptor for " + clazz.getName() +
- " indexed property " + pd.getName() +
- ", read method " + publicReadMethod,
- e);
- }
+ indexedReadMethod = getMatchingAccessibleMethod(
+ ((IndexedPropertyDescriptor) pd).getIndexedReadMethod(), accessibleMethods);
+ if (indexedReadMethod != null && !isAllowedToExpose(indexedReadMethod)) {
+ indexedReadMethod = null;
}
- } else {
- Method readMethod = pd.getReadMethod();
- Method publicReadMethod = getMatchingAccessibleMethod(readMethod, accessibleMethods);
- if (publicReadMethod != null && isAllowedToExpose(publicReadMethod)) {
- try {
- if (readMethod != publicReadMethod) {
- pd = new PropertyDescriptor(pd.getName(), publicReadMethod, null);
- }
- introspData.put(pd.getName(), pd);
- } catch (IntrospectionException e) {
- LOG.warn("Failed creating a publicly-accessible " +
- "property descriptor for " + clazz.getName() +
- " property " + pd.getName() + ", read method " +
- publicReadMethod, e);
- }
+ if (indexedReadMethod != null) {
+ getArgTypesByMethod(introspData).put(
+ indexedReadMethod, indexedReadMethod.getParameterTypes());
}
+ } else {
+ indexedReadMethod = null;
+ }
+
+ if (readMethod != null || indexedReadMethod != null) {
+ introspData.put(pd.getName(), new FastPropertyDescriptor(readMethod, indexedReadMethod));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8f787963/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java b/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
new file mode 100644
index 0000000..12d43de
--- /dev/null
+++ b/src/main/java/freemarker/ext/beans/FastPropertyDescriptor.java
@@ -0,0 +1,46 @@
+/*
+ * 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 freemarker.ext.beans;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+
+/**
+ * Used instead of {@link PropertyDescriptor}, because the methods of that are synchronized.
+ *
+ * @since 2.3.27
+ */
+final class FastPropertyDescriptor {
+ private final Method readMethod;
+ private final Method indexedReadMethod;
+
+ public FastPropertyDescriptor(Method readMethod, Method indexedReadMethod) {
+ this.readMethod = readMethod;
+ this.indexedReadMethod = indexedReadMethod;
+ }
+
+ public Method getReadMethod() {
+ return readMethod;
+ }
+
+ public Method getIndexedReadMethod() {
+ return indexedReadMethod;
+ }
+
+}
[2/6] incubator-freemarker git commit: preparing 2.3.27-gae release.
Posted by dd...@apache.org.
preparing 2.3.27-gae release.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/13750608
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/13750608
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/13750608
Branch: refs/heads/2.3
Commit: 137506085e4daa4741191dcfc60db292e81e2b2f
Parents: a072921
Author: Woonsan Ko <wo...@bloomreach.com>
Authored: Tue Oct 3 09:39:55 2017 -0400
Committer: Woonsan Ko <wo...@bloomreach.com>
Committed: Tue Oct 3 09:39:55 2017 -0400
----------------------------------------------------------------------
src/main/resources/freemarker/version.properties | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/13750608/src/main/resources/freemarker/version.properties
----------------------------------------------------------------------
diff --git a/src/main/resources/freemarker/version.properties b/src/main/resources/freemarker/version.properties
index 9a1a8c5..fc1445d 100644
--- a/src/main/resources/freemarker/version.properties
+++ b/src/main/resources/freemarker/version.properties
@@ -58,11 +58,11 @@
# - When the major version number is increased, major backward
# compatibility violations are allowed, but still should be avoided.
# During Apache Incubation, "-incubating" is added to this string.
-version=2.3.27-nightly_@timestampInVersion@-incubating
+version=2.3.27-incubating
# This exists as for Maven we use "-SNAPSHOT" for non-final releases.
# For final releases it's the same as "version". During Apache
# Incubation, "-incubating" is added *before* "-SNAPSHOT".
-mavenVersion=2.3.27-incubating-SNAPSHOT
+mavenVersion=2.3.27-incubating
# Version string that conforms to OSGi
# ------------------------------------
@@ -76,7 +76,7 @@ mavenVersion=2.3.27-incubating-SNAPSHOT
# 2.4.0.pre01
# 2.4.0.nightly_@timestampInVersion@
# During Apache Incubation, "-incubating" is added to this string.
-versionForOSGi=2.3.27.nightly_@timestampInVersion@-incubating
+versionForOSGi=2.3.27.stable-incubating
# Version string that conforms to legacy MF
# -----------------------------------------
@@ -95,7 +95,7 @@ versionForOSGi=2.3.27.nightly_@timestampInVersion@-incubating
# "97 denotes "nightly", 98 denotes "pre", 99 denotes "rc" build.
# In general, for the nightly/preview/rc Y of version 2.X, the versionForMf is
# 2.X-1.(99|98).Y. Note the X-1.
-versionForMf=2.3.26.97
+versionForMf=2.3.27
# The date of the build.
# This should be automatically filled by the building tool (Ant).
[5/6] incubator-freemarker git commit: Reverting version to
2.3.27-nightly for now...
Posted by dd...@apache.org.
Reverting version to 2.3.27-nightly for now...
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/1986341b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/1986341b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/1986341b
Branch: refs/heads/2.3
Commit: 1986341b959797dfebafcf49c54ccae221d6500c
Parents: 8f78796
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 20:26:30 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 20:26:30 2017 +0200
----------------------------------------------------------------------
src/main/resources/freemarker/version.properties | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/1986341b/src/main/resources/freemarker/version.properties
----------------------------------------------------------------------
diff --git a/src/main/resources/freemarker/version.properties b/src/main/resources/freemarker/version.properties
index fc1445d..9a1a8c5 100644
--- a/src/main/resources/freemarker/version.properties
+++ b/src/main/resources/freemarker/version.properties
@@ -58,11 +58,11 @@
# - When the major version number is increased, major backward
# compatibility violations are allowed, but still should be avoided.
# During Apache Incubation, "-incubating" is added to this string.
-version=2.3.27-incubating
+version=2.3.27-nightly_@timestampInVersion@-incubating
# This exists as for Maven we use "-SNAPSHOT" for non-final releases.
# For final releases it's the same as "version". During Apache
# Incubation, "-incubating" is added *before* "-SNAPSHOT".
-mavenVersion=2.3.27-incubating
+mavenVersion=2.3.27-incubating-SNAPSHOT
# Version string that conforms to OSGi
# ------------------------------------
@@ -76,7 +76,7 @@ mavenVersion=2.3.27-incubating
# 2.4.0.pre01
# 2.4.0.nightly_@timestampInVersion@
# During Apache Incubation, "-incubating" is added to this string.
-versionForOSGi=2.3.27.stable-incubating
+versionForOSGi=2.3.27.nightly_@timestampInVersion@-incubating
# Version string that conforms to legacy MF
# -----------------------------------------
@@ -95,7 +95,7 @@ versionForOSGi=2.3.27.stable-incubating
# "97 denotes "nightly", 98 denotes "pre", 99 denotes "rc" build.
# In general, for the nightly/preview/rc Y of version 2.X, the versionForMf is
# 2.X-1.(99|98).Y. Note the X-1.
-versionForMf=2.3.27
+versionForMf=2.3.26.97
# The date of the build.
# This should be automatically filled by the building tool (Ant).
[6/6] incubator-freemarker git commit: Merge remote-tracking branch
'origin/2.3-gae' into 2.3
Posted by dd...@apache.org.
Merge remote-tracking branch 'origin/2.3-gae' into 2.3
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/f73b8447
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/f73b8447
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/f73b8447
Branch: refs/heads/2.3
Commit: f73b8447c466e9f74c440557794f473af029b42c
Parents: 8f56810 1986341
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 21:31:26 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 21:31:26 2017 +0200
----------------------------------------------------------------------
.../java/freemarker/ext/beans/BeanModel.java | 30 ++-
.../freemarker/ext/beans/ClassIntrospector.java | 64 +++----
.../ext/beans/FastPropertyDescriptor.java | 46 +++++
.../core/TheadInterruptingSupportTest.java | 162 ----------------
.../core/ThreadInterruptingSupportTest.java | 184 +++++++++++++++++++
5 files changed, 267 insertions(+), 219 deletions(-)
----------------------------------------------------------------------
[3/6] incubator-freemarker git commit: Fixed template interruption
test (could hang if the template fails for some reason).
Posted by dd...@apache.org.
Fixed template interruption test (could hang if the template fails for some reason).
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/c01f1a22
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/c01f1a22
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/c01f1a22
Branch: refs/heads/2.3
Commit: c01f1a223a04dcff27eb3b71bbbdc759c1628384
Parents: 1375060
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 19:50:40 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 19:54:13 2017 +0200
----------------------------------------------------------------------
.../core/TheadInterruptingSupportTest.java | 162 ----------------
.../core/ThreadInterruptingSupportTest.java | 184 +++++++++++++++++++
2 files changed, 184 insertions(+), 162 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c01f1a22/src/test/java/freemarker/core/TheadInterruptingSupportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/TheadInterruptingSupportTest.java b/src/test/java/freemarker/core/TheadInterruptingSupportTest.java
deleted file mode 100644
index cbba0c3..0000000
--- a/src/test/java/freemarker/core/TheadInterruptingSupportTest.java
+++ /dev/null
@@ -1,162 +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 freemarker.core;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import freemarker.core.ThreadInterruptionSupportTemplatePostProcessor.TemplateProcessingThreadInterruptedException;
-import freemarker.template.Configuration;
-import freemarker.template.Template;
-import freemarker.template.TemplateDirectiveBody;
-import freemarker.template.TemplateDirectiveModel;
-import freemarker.template.TemplateException;
-import freemarker.template.TemplateModel;
-import freemarker.template.utility.NullWriter;
-
-public class TheadInterruptingSupportTest {
-
- private static final Logger LOG = LoggerFactory.getLogger(TheadInterruptingSupportTest.class);
-
- private static final int TEMPLATE_INTERRUPTION_TIMEOUT = 5000;
- private final Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
-
- @Test
- public void test() throws IOException, InterruptedException {
- assertCanBeInterrupted("<#list 1.. as x></#list>");
- assertCanBeInterrupted("<#list 1.. as x>${x}</#list>");
- assertCanBeInterrupted("<#list 1.. as x>t${x}</#list>");
- assertCanBeInterrupted("<#list 1.. as x><#list 1.. as y>${y}</#list></#list>");
- assertCanBeInterrupted("<#list 1.. as x>${x}<#else>nope</#list>");
- assertCanBeInterrupted("<#list 1..>[<#items as x>${x}</#items>]<#else>nope</#list>");
- assertCanBeInterrupted("<@customLoopDirective />");
- assertCanBeInterrupted("<@customLoopDirective>x</@>");
- assertCanBeInterrupted("<@customLoopDirective><#if true>x</#if></@>");
- assertCanBeInterrupted("<#macro selfCalling><@sleepDirective/><@selfCalling /></#macro><@selfCalling />");
- assertCanBeInterrupted("<#function selfCalling><@sleepDirective/>${selfCalling()}</#function>${selfCalling()}");
- assertCanBeInterrupted("<#list 1.. as _><#attempt><@sleepDirective/><#recover>suppress</#attempt></#list>");
- assertCanBeInterrupted("<#attempt><#list 1.. as _></#list><#recover>suppress</#attempt>");
- }
-
- private void assertCanBeInterrupted(final String templateSourceCode) throws IOException, InterruptedException {
- TemplateRunnerThread trt = new TemplateRunnerThread(templateSourceCode);
- trt.start();
- synchronized (trt) {
- while (!trt.isStarted()) {
- trt.wait();
- }
- }
- Thread.sleep(50); // Just to ensure (hope...) that the template execution reaches "deep" enough
- trt.interrupt();
- trt.join(TEMPLATE_INTERRUPTION_TIMEOUT);
- assertTrue(trt.isTemplateProcessingInterrupted());
- }
-
- public class TemplateRunnerThread extends Thread {
-
- private final Template template;
- private boolean started;
- private boolean templateProcessingInterrupted;
-
- public TemplateRunnerThread(String templateSourceCode) throws IOException {
- template = new Template(null, "<@startedDirective/>" + templateSourceCode, cfg);
- _CoreAPI.addThreadInterruptedChecks(template);
- }
-
- @Override
- public void run() {
- try {
- template.process(this, NullWriter.INSTANCE);
- } catch (TemplateProcessingThreadInterruptedException e) {
- //LOG.debug("Template processing interrupted", e);
- synchronized (this) {
- templateProcessingInterrupted = true;
- }
- } catch (Throwable e) {
- LOG.error("Template processing failed", e);
- }
- }
-
- public synchronized boolean isTemplateProcessingInterrupted() {
- return templateProcessingInterrupted;
- }
-
- public synchronized boolean isStarted() {
- return started;
- }
-
- public TemplateDirectiveModel getStartedDirective() {
- return new StartedDirective();
- }
-
- public TemplateDirectiveModel getCustomLoopDirective() {
- return new CustomLoopDirective();
- }
-
- public TemplateDirectiveModel getSleepDirective() {
- return new SleepDirective();
- }
-
- public class StartedDirective implements TemplateDirectiveModel {
-
- public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
- throws TemplateException, IOException {
- synchronized (TemplateRunnerThread.this) {
- started = true;
- TemplateRunnerThread.this.notifyAll();
- }
- }
-
- }
-
- public class CustomLoopDirective implements TemplateDirectiveModel {
-
- public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
- throws TemplateException, IOException {
- while (true) {
- body.render(NullWriter.INSTANCE);
- }
- }
-
- }
-
- public class SleepDirective implements TemplateDirectiveModel {
-
- public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
- throws TemplateException, IOException {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // Thread.sleep has reset the interrupted flag (because it has thrown InterruptedException).
- Thread.currentThread().interrupt();
- }
- }
-
- }
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c01f1a22/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java b/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java
new file mode 100644
index 0000000..6b9d86a
--- /dev/null
+++ b/src/test/java/freemarker/core/ThreadInterruptingSupportTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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 freemarker.core;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import freemarker.core.ThreadInterruptionSupportTemplatePostProcessor.TemplateProcessingThreadInterruptedException;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateDirectiveBody;
+import freemarker.template.TemplateDirectiveModel;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateModel;
+import freemarker.template.utility.NullWriter;
+
+public class ThreadInterruptingSupportTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ThreadInterruptingSupportTest.class);
+
+ private static final int TEMPLATE_INTERRUPTION_TIMEOUT = 5000;
+ private final Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
+
+ @Test
+ public void test() throws IOException, InterruptedException, TemplateException {
+ assertCanBeInterrupted("<#list 1.. as x></#list>");
+ assertCanBeInterrupted("<#list 1.. as x>${x}</#list>");
+ assertCanBeInterrupted("<#list 1.. as x>t${x}</#list>");
+ assertCanBeInterrupted("<#list 1.. as x><#list 1.. as y>${y}</#list></#list>");
+ assertCanBeInterrupted("<#list 1.. as x>${x}<#else>nope</#list>");
+ assertCanBeInterrupted("<#list 1..>[<#items as x>${x}</#items>]<#else>nope</#list>");
+ assertCanBeInterrupted("<@customLoopDirective />");
+ assertCanBeInterrupted("<@customLoopDirective>x</@>");
+ assertCanBeInterrupted("<@customLoopDirective><#if true>x</#if></@>");
+ assertCanBeInterrupted("<#macro selfCalling><@sleepDirective/><@selfCalling /></#macro><@selfCalling />");
+ assertCanBeInterrupted("<#function selfCalling><@sleepDirective/>${selfCalling()}</#function>${selfCalling()}");
+ assertCanBeInterrupted("<#list 1.. as _><#attempt><@sleepDirective/><#recover>suppress</#attempt></#list>");
+ assertCanBeInterrupted("<#attempt><#list 1.. as _></#list><#recover>suppress</#attempt>");
+ }
+
+ private void assertCanBeInterrupted(final String templateSourceCode)
+ throws IOException, InterruptedException, TemplateException {
+ TemplateRunnerThread trt = new TemplateRunnerThread(templateSourceCode);
+ trt.start();
+ synchronized (trt) {
+ while (!trt.isStartedOrFailed()) {
+ trt.wait();
+ }
+ }
+ if (trt.failedWith != null) {
+ if (trt.failedWith instanceof TemplateException) {
+ throw (TemplateException) trt.failedWith;
+ } else if (trt.failedWith instanceof IOException) {
+ throw (IOException) trt.failedWith;
+ } else {
+ throw new RuntimeException("Template processing has failed", trt.failedWith);
+ }
+ }
+ Thread.sleep(50); // Just to ensure (hope...) that the template execution reaches "deep" enough
+ trt.interrupt();
+ trt.join(TEMPLATE_INTERRUPTION_TIMEOUT);
+ assertTrue(trt.isTemplateProcessingInterrupted());
+ }
+
+ public class TemplateRunnerThread extends Thread {
+
+ private final Template template;
+ private boolean started;
+ private Throwable failedWith;
+ private boolean templateProcessingInterrupted;
+
+ public TemplateRunnerThread(String templateSourceCode) throws IOException {
+ template = new Template(null, "<@startedDirective/>" + templateSourceCode, cfg);
+ _CoreAPI.addThreadInterruptedChecks(template);
+ }
+
+ @Override
+ public void run() {
+ try {
+ template.process(this, NullWriter.INSTANCE);
+ } catch (TemplateProcessingThreadInterruptedException e) {
+ //LOG.debug("Template processing interrupted", e);
+ synchronized (this) {
+ templateProcessingInterrupted = true;
+ }
+ } catch (Throwable e) {
+ LOG.error("Template processing failed", e);
+ synchronized (TemplateRunnerThread.this) {
+ failedWith = e;
+ TemplateRunnerThread.this.notifyAll();
+ }
+ } finally {
+ synchronized (TemplateRunnerThread.this) {
+ if (!started && failedWith == null) {
+ failedWith = new IllegalStateException("Start directive was never called");
+ TemplateRunnerThread.this.notifyAll();
+ }
+ }
+ }
+ }
+
+ public synchronized boolean isTemplateProcessingInterrupted() {
+ return templateProcessingInterrupted;
+ }
+
+ public synchronized boolean isStartedOrFailed() {
+ return started || failedWith != null;
+ }
+
+ public TemplateDirectiveModel getStartedDirective() {
+ return new StartedDirective();
+ }
+
+ public TemplateDirectiveModel getCustomLoopDirective() {
+ return new CustomLoopDirective();
+ }
+
+ public TemplateDirectiveModel getSleepDirective() {
+ return new SleepDirective();
+ }
+
+ public class StartedDirective implements TemplateDirectiveModel {
+
+ public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
+ throws TemplateException, IOException {
+ synchronized (TemplateRunnerThread.this) {
+ started = true;
+ TemplateRunnerThread.this.notifyAll();
+ }
+ }
+
+ }
+
+ public class CustomLoopDirective implements TemplateDirectiveModel {
+
+ public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
+ throws TemplateException, IOException {
+ while (true) {
+ body.render(NullWriter.INSTANCE);
+ }
+ }
+
+ }
+
+ public class SleepDirective implements TemplateDirectiveModel {
+
+ public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody body)
+ throws TemplateException, IOException {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // Thread.sleep has reset the interrupted flag (because it has thrown InterruptedException).
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ }
+
+ }
+
+}