From 351b70f7d20694cd0dad6964bedb7d30c3000d4e Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Mon, 22 Oct 2012 20:02:48 +0200 Subject: [PATCH] Fix AbstractEvaluatorFactory.toId() not taking into account constants' types AbstractEvaluatorFactory ignored the types of constants when generating a classname. As these generated classes get cached, this could result in stack traces like these: java.lang.IllegalArgumentException: Can not set com.mysema.codegen.ComplexEvaluationTest$SuperCat field Q_0606084786_65821278_65821278.a1 to com.mysema.codegen.support.Cat at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) at java.lang.reflect.Field.set(Field.java:680) at com.mysema.codegen.AbstractEvaluatorFactory.createEvaluator(AbstractEvaluatorFactory.java:86) --- .../codegen/AbstractEvaluatorFactory.java | 8 +++- .../mysema/codegen/ComplexEvaluationTest.java | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/mysema/codegen/AbstractEvaluatorFactory.java b/src/main/java/com/mysema/codegen/AbstractEvaluatorFactory.java index 2a1af1f41..d359ca1c2 100644 --- a/src/main/java/com/mysema/codegen/AbstractEvaluatorFactory.java +++ b/src/main/java/com/mysema/codegen/AbstractEvaluatorFactory.java @@ -13,6 +13,7 @@ import java.util.Map; import com.mysema.codegen.model.ClassType; import com.mysema.codegen.model.Type; import com.mysema.codegen.model.TypeCategory; +import java.util.Collection; /** * @author tiwe @@ -68,7 +69,7 @@ public abstract class AbstractEvaluatorFactory implements EvaluatorFactory{ public Evaluator createEvaluator(String source, ClassType projection, String[] names, Type[] types, Class[] classes, Map constants) { try { - String id = toId(source, projection.getJavaClass(), types); + String id = toId(source, projection.getJavaClass(), types, constants.values()); Class clazz; try { clazz = loader.loadClass(id); @@ -106,13 +107,16 @@ public abstract class AbstractEvaluatorFactory implements EvaluatorFactory{ } - protected String toId(String source, Class returnType, Type... types) { + protected String toId(String source, Class returnType, Type[] types, Collection constants) { StringBuilder b = new StringBuilder("Q"); b.append("_").append(source.hashCode()); b.append("_").append(returnType.getName().hashCode()); for (Type type : types) { b.append("_").append(type.getFullName().hashCode()); } + for (Object constant : constants) { + b.append("_").append(constant.getClass().getName().hashCode()); + } return b.toString().replace('-', '0'); } diff --git a/src/test/java/com/mysema/codegen/ComplexEvaluationTest.java b/src/test/java/com/mysema/codegen/ComplexEvaluationTest.java index 6a9d55294..12af85400 100644 --- a/src/test/java/com/mysema/codegen/ComplexEvaluationTest.java +++ b/src/test/java/com/mysema/codegen/ComplexEvaluationTest.java @@ -160,4 +160,49 @@ public class ComplexEvaluationTest { assertEquals(Arrays.asList(true, true, true), evaluator.evaluate(a_, b_)); } + + public static class SuperCat extends Cat { + private SuperCat(String name) { + super(name); + } + } + + @Test + public void ComplexDifferentConstants() { + ClassType resultType = new ClassType(TypeCategory.LIST, List.class, new ClassType(Cat.class)); + String source = new StringBuilder() + .append("java.util.List rv = new java.util.ArrayList();\n") + .append("for (com.mysema.codegen.support.Cat cat : (java.util.List)cat_){\n") + .append("if (cat.equals(a1)) {\n") + .append("rv.add(cat);\n") + .append("}\n") + .append("}\n") + .append("return rv;\n") + .toString(); + + List cats = Arrays.asList(new Cat("fuzzy"), new Cat("spot")); + String[] names = new String[] { "cat_" }; + Type[] types = new Type[] { new ClassType(TypeCategory.LIST, List.class, new ClassType(Cat.class)) }; + Class[] classes = new Class[] { List.class }; + + // first pass + factory.createEvaluator( + source, + resultType, + names, + types, + classes, + Collections.singletonMap("a1", (Object) new SuperCat("superMittens")) + ).evaluate(cats); + + // second pass + factory.createEvaluator( + source, + resultType, + names, + types, + classes, + Collections.singletonMap("a1", (Object) new Cat("normalMittens")) + ).evaluate(cats); + } }