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 18:23:39 UTC
[1/2] incubator-freemarker git commit: Forward ported from 2.3-gae:
Fixed template interruption test (could hang if the template fails for some
reason).
Repository: incubator-freemarker
Updated Branches:
refs/heads/3 441367655 -> ef4674e84
Forward ported from 2.3-gae: 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/fa92465b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/fa92465b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/fa92465b
Branch: refs/heads/3
Commit: fa92465b4348222e692bd17392854a3b91762d33
Parents: 4413676
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 19:58:31 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 20:23:09 2017 +0200
----------------------------------------------------------------------
.../core/TheadInterruptingSupportTest.java | 32 +++++++++++++++++---
1 file changed, 27 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/fa92465b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java
----------------------------------------------------------------------
diff --git a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java
index 1468e59..933a9de 100644
--- a/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java
+++ b/freemarker-core-test/src/test/java/org/apache/freemarker/core/TheadInterruptingSupportTest.java
@@ -42,7 +42,7 @@ public class TheadInterruptingSupportTest {
private final Configuration cfg = new TestConfigurationBuilder().build();
@Test
- public void test() throws IOException, InterruptedException {
+ 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>");
@@ -59,14 +59,24 @@ public class TheadInterruptingSupportTest {
assertCanBeInterrupted("<#attempt><#list 1.. as _></#list><#recover>suppress</#attempt>");
}
- private void assertCanBeInterrupted(final String templateSourceCode) throws IOException, InterruptedException {
+ private void assertCanBeInterrupted(final String templateSourceCode)
+ throws IOException, InterruptedException, TemplateException {
TemplateRunnerThread trt = new TemplateRunnerThread(templateSourceCode);
trt.start();
synchronized (trt) {
- while (!trt.isStarted()) {
+ 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);
@@ -77,6 +87,7 @@ public class TheadInterruptingSupportTest {
private final Template template;
private boolean started;
+ private Throwable failedWith;
private boolean templateProcessingInterrupted;
public TemplateRunnerThread(String templateSourceCode) throws IOException {
@@ -95,6 +106,17 @@ public class TheadInterruptingSupportTest {
}
} 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();
+ }
+ }
}
}
@@ -102,8 +124,8 @@ public class TheadInterruptingSupportTest {
return templateProcessingInterrupted;
}
- public synchronized boolean isStarted() {
- return started;
+ public synchronized boolean isStartedOrFailed() {
+ return started || failedWith != null;
}
public TemplateDirectiveModel getStartedDirective() {
[2/2] incubator-freemarker git commit: Forward ported from 2.3-gae:
FREEMARKER-80: Avoid calling synchonized PropertyDescriptor.getReadMethod()
when getting a property in a template. Will see if it matters.
Posted by dd...@apache.org.
Forward ported from 2.3-gae: 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/ef4674e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/ef4674e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/ef4674e8
Branch: refs/heads/3
Commit: ef4674e84dd8802112555c456a1fdcc884f92f6c
Parents: fa92465
Author: ddekany <dd...@apache.org>
Authored: Tue Oct 3 20:23:32 2017 +0200
Committer: ddekany <dd...@apache.org>
Committed: Tue Oct 3 20:23:32 2017 +0200
----------------------------------------------------------------------
.../freemarker/core/model/impl/BeanModel.java | 20 ++------
.../core/model/impl/ClassIntrospector.java | 51 +++-----------------
.../core/model/impl/FastPropertyDescriptor.java | 39 +++++++++++++++
3 files changed, 50 insertions(+), 60 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef4674e8/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
index accadaf..9dbe5b6 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/BeanModel.java
@@ -19,8 +19,6 @@
package org.apache.freemarker.core.model.impl;
-import java.beans.IndexedPropertyDescriptor;
-import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -180,21 +178,9 @@ public class BeanModel
}
TemplateModel resultModel = UNKNOWN;
- if (desc instanceof PropertyDescriptor) {
- PropertyDescriptor pd = (PropertyDescriptor) desc;
- Method readMethod = pd.getReadMethod();
- if (readMethod != null) {
- // Unlike in FreeMarker 2, we prefer the normal read method even if there's an indexed read method.
- resultModel = wrapper.invokeMethod(object, readMethod, null);
- // cachedModel remains null, as we don't cache these
- } else if (desc instanceof IndexedPropertyDescriptor) {
- // In FreeMarker 2 we have exposed such indexed properties as sequences, but they can't support
- // the getCollectionSize() method, so we have discontinued that. People has to call the indexed read
- // method like any other method.
- resultModel = UNKNOWN;
- } else {
- throw new IllegalStateException("PropertyDescriptor.readMethod shouldn't be null");
- }
+ if (desc instanceof FastPropertyDescriptor) {
+ // Unlike in FreeMarker 2, we always use the normal read method, and ignore the indexed read method.
+ resultModel = wrapper.invokeMethod(object, ((FastPropertyDescriptor) desc).getReadMethod(), null);
} 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/ef4674e8/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
index cc083d4..94eca36 100644
--- a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/ClassIntrospector.java
@@ -206,7 +206,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) {
@@ -321,8 +321,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) {
@@ -336,7 +335,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);
}
@@ -359,7 +358,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,
@@ -377,6 +376,7 @@ class ClassIntrospector {
} // end if (exposureLevel < EXPOSE_PROPERTIES_ONLY)
}
+ // TODO [FM3] As we ignore indexed property getters in FM3, this might could be simplified.
/**
* Very similar to {@link BeanInfo#getPropertyDescriptors()}, but can deal with Java 8 default methods too.
*/
@@ -647,44 +647,9 @@ class ClassIntrospector {
private void addPropertyDescriptorToClassIntrospectionData(Map<Object, Object> introspData,
PropertyDescriptor pd, Class<?> clazz, Map<MethodSignature, List<Method>> accessibleMethods) {
- 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 {} indexed property {}, read method {}",
- clazz.getName(), pd.getName(), publicReadMethod,
- e);
- }
- }
- } 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 {} property {}, read method {}",
- clazz.getName(), pd.getName(), publicReadMethod,
- e);
- }
- }
+ Method readMethod = getMatchingAccessibleMethod(pd.getReadMethod(), accessibleMethods);
+ if (readMethod != null && isAllowedToExpose(readMethod)) {
+ introspData.put(pd.getName(), new FastPropertyDescriptor(readMethod));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/ef4674e8/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/FastPropertyDescriptor.java
----------------------------------------------------------------------
diff --git a/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/FastPropertyDescriptor.java b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/FastPropertyDescriptor.java
new file mode 100644
index 0000000..1019ba9
--- /dev/null
+++ b/freemarker-core/src/main/java/org/apache/freemarker/core/model/impl/FastPropertyDescriptor.java
@@ -0,0 +1,39 @@
+/*
+ * 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.model.impl;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+
+/**
+ * Used instead of {@link PropertyDescriptor}, because the methods of that are synchronized.
+ * Note that if a property has no read method (a non-indexed an one), then we don't treat is as a property.
+ */
+final class FastPropertyDescriptor {
+ private final Method readMethod;
+
+ public FastPropertyDescriptor(Method readMethod) {
+ this.readMethod = readMethod;
+ }
+
+ public Method getReadMethod() {
+ return readMethod;
+ }
+
+}