From dc99908057b194eb27ed1e87aed24ea946441fca Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Tue, 7 Jan 2020 09:37:17 +0000 Subject: [engine] Fix VELOCITY-924 - cache collision between an object and its class git-svn-id: https://svn.apache.org/repos/asf/velocity/engine/trunk@1872422 13f79535-47bb-0310-9956-ffa450edef68 --- .../velocity/runtime/parser/node/ASTMethod.java | 22 +++++++- .../java/org/apache/velocity/util/ClassUtils.java | 5 +- .../velocity/test/MethodCacheKeyTestCase.java | 19 ++++--- .../velocity/test/issues/Velocity855TestCase.java | 2 +- .../velocity/test/issues/Velocity924TestCase.java | 64 ++++++++++++++++++++++ 5 files changed, 98 insertions(+), 14 deletions(-) create mode 100755 velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity924TestCase.java (limited to 'velocity-engine-core') diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java index c7fab881..29a6739b 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/runtime/parser/node/ASTMethod.java @@ -334,10 +334,26 @@ public class ASTMethod extends SimpleNode */ public static class MethodCacheKey { + /** + * method name + */ private final String methodName; + + /** + * parameters classes + */ private final Class[] params; - public MethodCacheKey(String methodName, Class[] params) + /** + * whether the target object is of Class type + * (meaning we're searching either for methods + * of Class, or for static methods of the class + * this Class objects refers to) + * @since 2.2 + */ + private boolean classObject; + + public MethodCacheKey(String methodName, Class[] params, boolean classObject) { /** * Should never be initialized with nulls, but to be safe we refuse @@ -345,6 +361,7 @@ public class ASTMethod extends SimpleNode */ this.methodName = (methodName != null) ? methodName : StringUtils.EMPTY; this.params = (params != null) ? params : EMPTY_CLASS_ARRAY; + this.classObject = classObject; } /** @@ -360,7 +377,8 @@ public class ASTMethod extends SimpleNode { final MethodCacheKey other = (MethodCacheKey) o; if (params.length == other.params.length && - methodName.equals(other.methodName)) + methodName.equals(other.methodName) && + classObject == other.classObject) { for (int i = 0; i < params.length; ++i) { diff --git a/velocity-engine-core/src/main/java/org/apache/velocity/util/ClassUtils.java b/velocity-engine-core/src/main/java/org/apache/velocity/util/ClassUtils.java index d33bd978..b17eb681 100644 --- a/velocity-engine-core/src/main/java/org/apache/velocity/util/ClassUtils.java +++ b/velocity-engine-core/src/main/java/org/apache/velocity/util/ClassUtils.java @@ -179,9 +179,10 @@ public class ClassUtils { /* * check the cache */ - MethodCacheKey mck = new MethodCacheKey(methodName, paramClasses); + boolean classObject = (o instanceof Class); + MethodCacheKey mck = new MethodCacheKey(methodName, paramClasses, classObject); IntrospectionCacheData icd = context.icacheGet(mck); - Class clazz = o instanceof Class ? (Class)o : o.getClass(); + Class clazz = classObject ? (Class)o : o.getClass(); /* * like ASTIdentifier, if we have cache information, and the Class of diff --git a/velocity-engine-core/src/test/java/org/apache/velocity/test/MethodCacheKeyTestCase.java b/velocity-engine-core/src/test/java/org/apache/velocity/test/MethodCacheKeyTestCase.java index c78d56de..37b54e72 100644 --- a/velocity-engine-core/src/test/java/org/apache/velocity/test/MethodCacheKeyTestCase.java +++ b/velocity-engine-core/src/test/java/org/apache/velocity/test/MethodCacheKeyTestCase.java @@ -20,6 +20,7 @@ package org.apache.velocity.test; */ import junit.framework.TestCase; +import org.apache.commons.io.filefilter.FalseFileFilter; import org.apache.commons.lang3.ArrayUtils; import org.apache.velocity.runtime.parser.node.ASTMethod; @@ -35,44 +36,44 @@ public class MethodCacheKeyTestCase extends TestCase public void testMethodKeyCacheEquals() { Class [] elements1 = new Class [] { Object.class }; - ASTMethod.MethodCacheKey mck1 = new ASTMethod.MethodCacheKey("test",elements1); + ASTMethod.MethodCacheKey mck1 = new ASTMethod.MethodCacheKey("test",elements1, false); selfEqualsAssertions(mck1); Class [] elements2 = new Class [] { Object.class }; - ASTMethod.MethodCacheKey mck2 = new ASTMethod.MethodCacheKey("test",elements2); + ASTMethod.MethodCacheKey mck2 = new ASTMethod.MethodCacheKey("test",elements2, false); assertTrue(mck1.equals(mck2)); Class [] elements3 = new Class [] { String.class }; - ASTMethod.MethodCacheKey mck3 = new ASTMethod.MethodCacheKey("test",elements3); + ASTMethod.MethodCacheKey mck3 = new ASTMethod.MethodCacheKey("test",elements3, false); assertFalse(mck1.equals(mck3)); Class [] elements4 = new Class [] { Object.class }; - ASTMethod.MethodCacheKey mck4 = new ASTMethod.MethodCacheKey("boo",elements4); + ASTMethod.MethodCacheKey mck4 = new ASTMethod.MethodCacheKey("boo",elements4, false); assertFalse(mck1.equals(mck4)); /** check for potential NPE's **/ Class [] elements5 = ArrayUtils.EMPTY_CLASS_ARRAY; - ASTMethod.MethodCacheKey mck5 = new ASTMethod.MethodCacheKey("boo",elements5); + ASTMethod.MethodCacheKey mck5 = new ASTMethod.MethodCacheKey("boo",elements5, false); selfEqualsAssertions(mck5); Class [] elements6 = null; - ASTMethod.MethodCacheKey mck6 = new ASTMethod.MethodCacheKey("boo",elements6); + ASTMethod.MethodCacheKey mck6 = new ASTMethod.MethodCacheKey("boo",elements6, false); selfEqualsAssertions(mck6); Class [] elements7 = new Class [] {}; - ASTMethod.MethodCacheKey mck7 = new ASTMethod.MethodCacheKey("boo",elements7); + ASTMethod.MethodCacheKey mck7 = new ASTMethod.MethodCacheKey("boo",elements7, false); selfEqualsAssertions(mck7); Class [] elements8 = new Class [] {null}; - ASTMethod.MethodCacheKey mck8 = new ASTMethod.MethodCacheKey("boo",elements8); + ASTMethod.MethodCacheKey mck8 = new ASTMethod.MethodCacheKey("boo",elements8, false); selfEqualsAssertions(mck8); Class [] elements9 = new Class [] { Object.class }; - ASTMethod.MethodCacheKey mck9 = new ASTMethod.MethodCacheKey("boo",elements9); + ASTMethod.MethodCacheKey mck9 = new ASTMethod.MethodCacheKey("boo",elements9, false); selfEqualsAssertions(mck9); } diff --git a/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity855TestCase.java b/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity855TestCase.java index a1f93c8b..6dcf2f6e 100755 --- a/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity855TestCase.java +++ b/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity855TestCase.java @@ -39,7 +39,7 @@ public class Velocity855TestCase extends BaseTestCase context.put("typeKind", javax.lang.model.type.TypeKind.class); } - public void testSpaceBeforeRParen() + public void testVelocity855() { assertEvalEquals("ENUM DECLARED", "$elementKind.valueOf('ENUM') $typeKind.valueOf('DECLARED')"); } diff --git a/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity924TestCase.java b/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity924TestCase.java new file mode 100755 index 00000000..af1a9c62 --- /dev/null +++ b/velocity-engine-core/src/test/java/org/apache/velocity/test/issues/Velocity924TestCase.java @@ -0,0 +1,64 @@ +package org.apache.velocity.test.issues; + +/* + * 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. + */ + +import org.apache.velocity.VelocityContext; +import org.apache.velocity.test.BaseTestCase; + +/** + * This class tests VELOCITY-855. + */ +public class Velocity924TestCase extends BaseTestCase +{ + public Velocity924TestCase(String name) + { + super(name); + } + + public static class Foo + { + public String getName() { return "foo"; } + } + + protected void setUpContext(VelocityContext context) + { + context.put("var", new Foo()); + } + + public void testVelocity924Getter() + { + assertEvalEquals("org.apache.velocity.test.issues.Velocity924TestCase$Foo foo", "$var.class.name $var.name"); + } + + public void testVelocity924Method() + { + assertEvalEquals("org.apache.velocity.test.issues.Velocity924TestCase$Foo foo", "$var.class.getName() $var.getName()");assertEvalEquals("org.apache.velocity.test.issues.Velocity924TestCase$Foo foo", "$var.class.name $var.name"); + } + + public void testVelocity924Getter2() + { + assertEvalEquals("foo org.apache.velocity.test.issues.Velocity924TestCase$Foo", "$var.name $var.class.name"); + } + + public void testVelocity924Method2() + { + assertEvalEquals("foo org.apache.velocity.test.issues.Velocity924TestCase$Foo", "$var.getName() $var.class.getName()");assertEvalEquals("org.apache.velocity.test.issues.Velocity924TestCase$Foo foo", "$var.class.name $var.name"); + } +} -- cgit v1.2.3