diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java index d40daa3cba..019faf2836 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodResolver.java @@ -38,27 +38,30 @@ import org.springframework.expression.spel.SpelMessage; import org.springframework.util.CollectionUtils; /** - * A method resolver that uses reflection to locate the method that should be invoked. + * Reflection-based {@link MethodResolver} used by default in + * {@link StandardEvaluationContext} unless explicit method resolvers have been specified. * * @author Andy Clement * @author Juergen Hoeller + * @author Chris Beams * @since 3.0 + * @see StandardEvaluationContext#addMethodResolver(MethodResolver) */ public class ReflectiveMethodResolver implements MethodResolver { private static Method[] NO_METHODS = new Method[0]; private Map, MethodFilter> filters = null; - + // Using distance will ensure a more accurate match is discovered, // more closely following the Java rules. private boolean useDistance = false; - + public ReflectiveMethodResolver() { - + } - + /** * This constructors allows the ReflectiveMethodResolver to be configured such that it will * use a distance computation to check which is the better of two close matches (when there @@ -71,7 +74,7 @@ public class ReflectiveMethodResolver implements MethodResolver { public ReflectiveMethodResolver(boolean useDistance) { this.useDistance = useDistance; } - + /** * Locate a method on a type. There are three kinds of match that might occur: *
    @@ -88,14 +91,14 @@ public class ReflectiveMethodResolver implements MethodResolver { TypeConverter typeConverter = context.getTypeConverter(); Class type = (targetObject instanceof Class ? (Class) targetObject : targetObject.getClass()); Method[] methods = type.getMethods(); - + // If a filter is registered for this type, call it MethodFilter filter = (this.filters != null ? this.filters.get(type) : null); if (filter != null) { - List methodsForFiltering = new ArrayList(); - for (Method method: methods) { - methodsForFiltering.add(method); - } + List methodsForFiltering = new ArrayList(); + for (Method method: methods) { + methodsForFiltering.add(method); + } List methodsFiltered = filter.filter(methodsForFiltering); if (CollectionUtils.isEmpty(methodsFiltered)) { methods = NO_METHODS; @@ -124,7 +127,7 @@ public class ReflectiveMethodResolver implements MethodResolver { continue; } if (method.getName().equals(name)) { - Class[] paramTypes = method.getParameterTypes(); + Class[] paramTypes = method.getParameterTypes(); List paramDescriptors = new ArrayList(paramTypes.length); for (int i = 0; i < paramTypes.length; i++) { paramDescriptors.add(new TypeDescriptor(new MethodParameter(method, i))); diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java index c947e27e02..e28f9dd3a1 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java @@ -50,12 +50,12 @@ import org.springframework.expression.spel.support.StandardTypeLocator; /** * Tests based on Jiras up to the release of Spring 3.0.0 - * + * * @author Andy Clement * @author Clark Duplichien */ public class SpringEL300Tests extends ExpressionTestCase { - + @Test public void testNPE_SPR5661() { evaluate("joinThreeStrings('a',null,'c')", "anullc", String.class); @@ -66,7 +66,7 @@ public class SpringEL300Tests extends ExpressionTestCase { public void testSWF1086() { evaluate("printDouble(T(java.math.BigDecimal).valueOf(14.35))", "anullc", String.class); } - + @Test public void testDoubleCoercion() { evaluate("printDouble(14.35)", "14.35", String.class); @@ -92,15 +92,15 @@ public class SpringEL300Tests extends ExpressionTestCase { // success } eContext.setTypeLocator(new MyTypeLocator()); - + // varargs expr = new SpelExpressionParser().parseRaw("tryToInvokeWithNull3(null,'a','b')"); Assert.assertEquals("ab",expr.getValue(eContext)); - + // varargs 2 - null is packed into the varargs expr = new SpelExpressionParser().parseRaw("tryToInvokeWithNull3(12,'a',null,'c')"); Assert.assertEquals("anullc",expr.getValue(eContext)); - + // check we can find the ctor ok expr = new SpelExpressionParser().parseRaw("new Spr5899Class().toString()"); Assert.assertEquals("instance",expr.getValue(eContext)); @@ -116,7 +116,7 @@ public class SpringEL300Tests extends ExpressionTestCase { expr = new SpelExpressionParser().parseRaw("new Spr5899Class(null,'a', null, 'b').toString()"); Assert.assertEquals("instance",expr.getValue(eContext)); } - + static class MyTypeLocator extends StandardTypeLocator { public Class findType(String typename) throws EvaluationException { @@ -132,12 +132,12 @@ public class SpringEL300Tests extends ExpressionTestCase { static class Spr5899Class { public Spr5899Class() {} - public Spr5899Class(Integer i) { } - public Spr5899Class(Integer i, String... s) { } - + public Spr5899Class(Integer i) { } + public Spr5899Class(Integer i, String... s) { } + public Integer tryToInvokeWithNull(Integer value) { return value; } public Integer tryToInvokeWithNull2(int i) { return new Integer(i); } - public String tryToInvokeWithNull3(Integer value,String... strings) { + public String tryToInvokeWithNull3(Integer value,String... strings) { StringBuilder sb = new StringBuilder(); for (int i=0;i m = new HashMap(); m.put("foo", "bar"); StandardEvaluationContext eContext = new StandardEvaluationContext(m); // root is a map instance eContext.addPropertyAccessor(new MapAccessor()); Expression expr = new SpelExpressionParser().parseRaw("['foo']"); Assert.assertEquals("bar", expr.getValue(eContext)); } - + @Test public void testSPR5847() throws Exception { StandardEvaluationContext eContext = new StandardEvaluationContext(new TestProperties()); String name = null; Expression expr = null; - + expr = new SpelExpressionParser().parseRaw("jdbcProperties['username']"); name = expr.getValue(eContext,String.class); Assert.assertEquals("Dave",name); - + expr = new SpelExpressionParser().parseRaw("jdbcProperties[username]"); name = expr.getValue(eContext,String.class); Assert.assertEquals("Dave",name); @@ -209,7 +208,7 @@ public class SpringEL300Tests extends ExpressionTestCase { eContext.addPropertyAccessor(new MapAccessor()); name = expr.getValue(eContext,String.class); Assert.assertEquals("Dave",name); - + // --- dotted property names // lookup foo on the root, then bar on that, then use that as the key into jdbcProperties @@ -222,9 +221,9 @@ public class SpringEL300Tests extends ExpressionTestCase { expr = new SpelExpressionParser().parseRaw("jdbcProperties['foo.bar']"); eContext.addPropertyAccessor(new MapAccessor()); name = expr.getValue(eContext,String.class); - Assert.assertEquals("Elephant",name); + Assert.assertEquals("Elephant",name); } - + static class TestProperties { public Properties jdbcProperties = new Properties(); public Properties foo = new Properties(); @@ -239,11 +238,11 @@ public class SpringEL300Tests extends ExpressionTestCase { static class MapAccessor implements PropertyAccessor { public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException { - return (((Map) target).containsKey(name)); + return (((Map) target).containsKey(name)); } public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { - return new TypedValue(((Map) target).get(name)); + return new TypedValue(((Map) target).get(name)); } public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { @@ -252,22 +251,22 @@ public class SpringEL300Tests extends ExpressionTestCase { @SuppressWarnings("unchecked") public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException { - ((Map) target).put(name, newValue); + ((Map) target).put(name, newValue); } - public Class[] getSpecificTargetClasses() { + public Class[] getSpecificTargetClasses() { return new Class[] {Map.class}; } - + } - + @Test public void testNPE_SPR5673() throws Exception { ParserContext hashes = TemplateExpressionParsingTests.HASH_DELIMITED_PARSER_CONTEXT; ParserContext dollars = TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT; - + checkTemplateParsing("abc${'def'} ghi","abcdef ghi"); - + checkTemplateParsingError("abc${ {}( 'abc'","Missing closing ')' for '(' at position 8"); checkTemplateParsingError("abc${ {}[ 'abc'","Missing closing ']' for '[' at position 8"); checkTemplateParsingError("abc${ {}{ 'abc'","Missing closing '}' for '{' at position 8"); @@ -278,7 +277,7 @@ public class SpringEL300Tests extends ExpressionTestCase { checkTemplateParsingError("abc${ ] }","Found closing ']' at position 6 without an opening '['"); checkTemplateParsingError("abc${ } }","No expression defined within delimiter '${}' at character 3"); checkTemplateParsingError("abc$[ } ]",DOLLARSQUARE_TEMPLATE_PARSER_CONTEXT,"Found closing '}' at position 6 without an opening '{'"); - + checkTemplateParsing("abc ${\"def''g}hi\"} jkl","abc def'g}hi jkl"); checkTemplateParsing("abc ${'def''g}hi'} jkl","abc def'g}hi jkl"); checkTemplateParsing("}","}"); @@ -295,7 +294,7 @@ public class SpringEL300Tests extends ExpressionTestCase { checkTemplateParsing("Hello ${'inner literal that''s got {[(])]}an escaped quote in it'} World","Hello inner literal that's got {[(])]}an escaped quote in it World"); checkTemplateParsingError("Hello ${","No ending suffix '}' for expression starting at character 6: ${"); } - + @Test public void testAccessingNullPropertyViaReflection_SPR5663() throws AccessException { PropertyAccessor propertyAccessor = new ReflectivePropertyAccessor(); @@ -315,33 +314,33 @@ public class SpringEL300Tests extends ExpressionTestCase { // success } } - + @Test public void testNestedProperties_SPR6923() { StandardEvaluationContext eContext = new StandardEvaluationContext(new Foo()); String name = null; Expression expr = null; - + expr = new SpelExpressionParser().parseRaw("resource.resource.server"); name = expr.getValue(eContext,String.class); Assert.assertEquals("abc",name); } - + static class Foo { public ResourceSummary resource = new ResourceSummary(); } - + static class ResourceSummary { ResourceSummary() { this.resource = new Resource(); } private final Resource resource; public Resource getResource() { - return resource; - } + return resource; + } } - + static class Resource { public String getServer() { return "abc"; @@ -374,9 +373,8 @@ public class SpringEL300Tests extends ExpressionTestCase { name = expr.getValue(eContext,String.class); // will be using the cached accessor this time Assert.assertEquals("hello",name); } - + /** $ related identifiers */ - @SuppressWarnings("unchecked") @Test public void testDollarPrefixedIdentifier_SPR7100() { Holder h = new Holder(); @@ -390,7 +388,7 @@ public class SpringEL300Tests extends ExpressionTestCase { h.map.put("$_$","tribble"); String name = null; Expression expr = null; - + expr = new SpelExpressionParser().parseRaw("map.$foo"); name = expr.getValue(eContext,String.class); Assert.assertEquals("wibble",name); @@ -430,8 +428,11 @@ public class SpringEL300Tests extends ExpressionTestCase { name = expr.getValue(eContext,String.class); // will be using the cached accessor this time Assert.assertEquals("wobble",name); } - - /** Should be accessing (setting) Goo.wibble field because 'bar' variable evaluates to "wibble" */ + + /** + * Should be accessing (setting) Goo.wibble field because 'bar' variable evaluates to + * "wibble" + */ @Test public void testIndexingAsAPropertyAccess_SPR6968_4() { Goo g = Goo.instance; @@ -458,7 +459,7 @@ public class SpringEL300Tests extends ExpressionTestCase { expr.getValue(eContext,String.class); // will be using the cached accessor this time Assert.assertEquals("world",g.value); } - + @Test public void testDollars() { StandardEvaluationContext eContext = new StandardEvaluationContext(new XX()); @@ -467,7 +468,7 @@ public class SpringEL300Tests extends ExpressionTestCase { eContext.setVariable("file_name","$foo"); Assert.assertEquals("wibble",expr.getValue(eContext,String.class)); } - + @Test public void testDollars2() { StandardEvaluationContext eContext = new StandardEvaluationContext(new XX()); @@ -476,12 +477,12 @@ public class SpringEL300Tests extends ExpressionTestCase { eContext.setVariable("file_name","$foo"); Assert.assertEquals("wibble",expr.getValue(eContext,String.class)); } - + static class XX { public Map m; - + public String floo ="bar"; - + public XX() { m = new HashMap(); m.put("$foo","wibble"); @@ -490,34 +491,34 @@ public class SpringEL300Tests extends ExpressionTestCase { } static class Goo { - + public static Goo instance = new Goo(); public String bar = "key"; public String value = null; public String wibble = "wobble"; - + public String getKey() { return "hello"; } - + public void setKey(String s) { value = s; } - + } - + static class Holder { - - public Map map = new HashMap(); + + public Map map = new HashMap(); } - + // --- private void checkTemplateParsing(String expression, String expectedValue) throws Exception { checkTemplateParsing(expression,TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT, expectedValue); } - + private void checkTemplateParsing(String expression, ParserContext context, String expectedValue) throws Exception { SpelExpressionParser parser = new SpelExpressionParser(); Expression expr = parser.parseExpression(expression,context); @@ -527,7 +528,7 @@ public class SpringEL300Tests extends ExpressionTestCase { private void checkTemplateParsingError(String expression,String expectedMessage) throws Exception { checkTemplateParsingError(expression, TemplateExpressionParsingTests.DEFAULT_TEMPLATE_PARSER_CONTEXT,expectedMessage); } - + private void checkTemplateParsingError(String expression,ParserContext context, String expectedMessage) throws Exception { SpelExpressionParser parser = new SpelExpressionParser(); try { @@ -540,7 +541,7 @@ public class SpringEL300Tests extends ExpressionTestCase { Assert.assertEquals(expectedMessage,e.getMessage()); } } - + private static final ParserContext DOLLARSQUARE_TEMPLATE_PARSER_CONTEXT = new ParserContext() { public String getExpressionPrefix() { return "$["; @@ -552,28 +553,13 @@ public class SpringEL300Tests extends ExpressionTestCase { return true; } }; - -// @Test -// public void testFails() { -// -// StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); -// evaluationContext.setVariable("target", new Foo2()); -// for (int i = 0; i < 300000; i++) { -// evaluationContext.addPropertyAccessor(new MapAccessor()); -// ExpressionParser parser = new SpelExpressionParser(); -// Expression expression = parser.parseExpression("#target.execute(payload)"); -// Message message = new Message(); -// message.setPayload(i+""); -// expression.getValue(evaluationContext, message); -// } -// } - + static class Foo2 { public void execute(String str){ System.out.println("Value: " + str); } } - + static class Message{ private String payload; @@ -587,7 +573,7 @@ public class SpringEL300Tests extends ExpressionTestCase { } // bean resolver tests - + @Test public void beanResolution() { StandardEvaluationContext eContext = new StandardEvaluationContext(new XX()); @@ -601,7 +587,7 @@ public class SpringEL300Tests extends ExpressionTestCase { Assert.assertEquals(SpelMessage.NO_BEAN_RESOLVER_REGISTERED,see.getMessageCode()); Assert.assertEquals("foo",see.getInserts()[0]); } - + eContext.setBeanResolver(new MyBeanResolver()); // bean exists @@ -622,11 +608,11 @@ public class SpringEL300Tests extends ExpressionTestCase { Assert.assertTrue(see.getCause() instanceof AccessException); Assert.assertTrue(((AccessException)see.getCause()).getMessage().startsWith("DONT")); } - + // bean exists expr = new SpelExpressionParser().parseRaw("@'foo.bar'"); Assert.assertEquals("trouble",expr.getValue(eContext,String.class)); - + // bean exists try { expr = new SpelExpressionParser().parseRaw("@378"); @@ -635,7 +621,7 @@ public class SpringEL300Tests extends ExpressionTestCase { Assert.assertEquals(SpelMessage.INVALID_BEAN_REFERENCE,spe.getMessageCode()); } } - + static class MyBeanResolver implements BeanResolver { public Object resolve(EvaluationContext context, String beanname) throws AccessException { if (beanname.equals("foo")) { @@ -648,14 +634,14 @@ public class SpringEL300Tests extends ExpressionTestCase { return null; } } - + // end bean resolver tests @Test public void elvis_SPR7209_1() { StandardEvaluationContext eContext = new StandardEvaluationContext(new XX()); Expression expr = null; - + // Different parts of elvis expression are null expr = new SpelExpressionParser().parseRaw("(?:'default')"); Assert.assertEquals("default", expr.getValue()); @@ -696,68 +682,67 @@ public class SpringEL300Tests extends ExpressionTestCase { expr = new SpelExpressionParser().parseRaw("''?:'default'"); Assert.assertEquals("default", expr.getValue()); } - - @Test - @SuppressWarnings("unchecked") - public void testMapOfMap_SPR7244() throws Exception { - Map map = new LinkedHashMap(); - map.put("uri", "http:"); - Map nameMap = new LinkedHashMap(); - nameMap.put("givenName", "Arthur"); - map.put("value", nameMap); - - StandardEvaluationContext ctx = new StandardEvaluationContext(map); - ExpressionParser parser = new SpelExpressionParser(); - String el1 = "#root['value'].get('givenName')"; - Expression exp = parser.parseExpression(el1); - Object evaluated = exp.getValue(ctx); - Assert.assertEquals("Arthur", evaluated); - String el2 = "#root['value']['givenName']"; - exp = parser.parseExpression(el2); - evaluated = exp.getValue(ctx); - Assert.assertEquals("Arthur",evaluated); - } - + @Test + public void testMapOfMap_SPR7244() throws Exception { + Map map = new LinkedHashMap(); + map.put("uri", "http:"); + Map nameMap = new LinkedHashMap(); + nameMap.put("givenName", "Arthur"); + map.put("value", nameMap); + + StandardEvaluationContext ctx = new StandardEvaluationContext(map); + ExpressionParser parser = new SpelExpressionParser(); + String el1 = "#root['value'].get('givenName')"; + Expression exp = parser.parseExpression(el1); + Object evaluated = exp.getValue(ctx); + Assert.assertEquals("Arthur", evaluated); + + String el2 = "#root['value']['givenName']"; + exp = parser.parseExpression(el2); + evaluated = exp.getValue(ctx); + Assert.assertEquals("Arthur",evaluated); + } + @Test public void testProjectionTypeDescriptors_1() throws Exception { - StandardEvaluationContext ctx = new StandardEvaluationContext(new C()); - SpelExpressionParser parser = new SpelExpressionParser(); - String el1 = "ls.![#this.equals('abc')]"; - SpelExpression exp = parser.parseRaw(el1); - List value = (List)exp.getValue(ctx); - // value is list containing [true,false] - Assert.assertEquals(Boolean.class,value.get(0).getClass()); - TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx); - Assert.assertEquals(null, evaluated.getElementTypeDescriptor()); + StandardEvaluationContext ctx = new StandardEvaluationContext(new C()); + SpelExpressionParser parser = new SpelExpressionParser(); + String el1 = "ls.![#this.equals('abc')]"; + SpelExpression exp = parser.parseRaw(el1); + List value = (List)exp.getValue(ctx); + // value is list containing [true,false] + Assert.assertEquals(Boolean.class,value.get(0).getClass()); + TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx); + Assert.assertEquals(null, evaluated.getElementTypeDescriptor()); } - + @Test public void testProjectionTypeDescriptors_2() throws Exception { - StandardEvaluationContext ctx = new StandardEvaluationContext(new C()); - SpelExpressionParser parser = new SpelExpressionParser(); - String el1 = "as.![#this.equals('abc')]"; - SpelExpression exp = parser.parseRaw(el1); - Object[] value = (Object[])exp.getValue(ctx); - // value is array containing [true,false] - Assert.assertEquals(Boolean.class,value[0].getClass()); - TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx); - Assert.assertEquals(Boolean.class, evaluated.getElementTypeDescriptor().getType()); + StandardEvaluationContext ctx = new StandardEvaluationContext(new C()); + SpelExpressionParser parser = new SpelExpressionParser(); + String el1 = "as.![#this.equals('abc')]"; + SpelExpression exp = parser.parseRaw(el1); + Object[] value = (Object[])exp.getValue(ctx); + // value is array containing [true,false] + Assert.assertEquals(Boolean.class,value[0].getClass()); + TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx); + Assert.assertEquals(Boolean.class, evaluated.getElementTypeDescriptor().getType()); } - + @Test public void testProjectionTypeDescriptors_3() throws Exception { - StandardEvaluationContext ctx = new StandardEvaluationContext(new C()); - SpelExpressionParser parser = new SpelExpressionParser(); - String el1 = "ms.![key.equals('abc')]"; - SpelExpression exp = parser.parseRaw(el1); - List value = (List)exp.getValue(ctx); - // value is list containing [true,false] - Assert.assertEquals(Boolean.class,value.get(0).getClass()); - TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx); - Assert.assertEquals(null, evaluated.getElementTypeDescriptor()); + StandardEvaluationContext ctx = new StandardEvaluationContext(new C()); + SpelExpressionParser parser = new SpelExpressionParser(); + String el1 = "ms.![key.equals('abc')]"; + SpelExpression exp = parser.parseRaw(el1); + List value = (List)exp.getValue(ctx); + // value is list containing [true,false] + Assert.assertEquals(Boolean.class,value.get(0).getClass()); + TypeDescriptor evaluated = exp.getValueTypeDescriptor(ctx); + Assert.assertEquals(null, evaluated.getElementTypeDescriptor()); } - + static class C { public List ls; public String[] as; @@ -772,19 +757,19 @@ public class SpringEL300Tests extends ExpressionTestCase { ms.put("def","pqr"); } } - + static class D { public String a; - + private D(String s) { a=s; } - + public String toString() { return "D("+a+")"; } } - + @Test public void testGreaterThanWithNulls_SPR7840() throws Exception { List list = new ArrayList(); @@ -794,30 +779,31 @@ public class SpringEL300Tests extends ExpressionTestCase { list.add(new D("ccc")); list.add(new D(null)); list.add(new D("zzz")); - - StandardEvaluationContext ctx = new StandardEvaluationContext(list); - SpelExpressionParser parser = new SpelExpressionParser(); - String el1 = "#root.?[a < 'hhh']"; - SpelExpression exp = parser.parseRaw(el1); - Object value = exp.getValue(ctx); - assertEquals("[D(aaa), D(bbb), D(null), D(ccc), D(null)]",value.toString()); + StandardEvaluationContext ctx = new StandardEvaluationContext(list); + SpelExpressionParser parser = new SpelExpressionParser(); - String el2 = "#root.?[a > 'hhh']"; - SpelExpression exp2 = parser.parseRaw(el2); - Object value2 = exp2.getValue(ctx); - assertEquals("[D(zzz)]",value2.toString()); - - // trim out the nulls first - String el3 = "#root.?[a!=null].?[a < 'hhh']"; - SpelExpression exp3 = parser.parseRaw(el3); - Object value3 = exp3.getValue(ctx); - assertEquals("[D(aaa), D(bbb), D(ccc)]",value3.toString()); + String el1 = "#root.?[a < 'hhh']"; + SpelExpression exp = parser.parseRaw(el1); + Object value = exp.getValue(ctx); + assertEquals("[D(aaa), D(bbb), D(null), D(ccc), D(null)]",value.toString()); + + String el2 = "#root.?[a > 'hhh']"; + SpelExpression exp2 = parser.parseRaw(el2); + Object value2 = exp2.getValue(ctx); + assertEquals("[D(zzz)]",value2.toString()); + + // trim out the nulls first + String el3 = "#root.?[a!=null].?[a < 'hhh']"; + SpelExpression exp3 = parser.parseRaw(el3); + Object value3 = exp3.getValue(ctx); + assertEquals("[D(aaa), D(bbb), D(ccc)]",value3.toString()); } /** - * Test whether {@link ReflectiveMethodResolver} follows Java Method Invocation Conversion order. And more precisely - * that widening reference conversion is 'higher' than a unboxing conversion. + * Test whether {@link ReflectiveMethodResolver} follows Java Method Invocation + * Conversion order. And more precisely that widening reference conversion is 'higher' + * than a unboxing conversion. */ @Test public void testConversionPriority_8224() throws Exception { @@ -904,16 +890,16 @@ public class SpringEL300Tests extends ExpressionTestCase { } - + @Test public void varargsAndPrimitives_SPR8174() throws Exception { EvaluationContext emptyEvalContext = new StandardEvaluationContext(); List args = new ArrayList(); - + args.add(TypeDescriptor.forObject(34L)); ReflectionUtil ru = new ReflectionUtil(); MethodExecutor me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"methodToCall",args); - + args.set(0,TypeDescriptor.forObject(23)); me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); me.execute(emptyEvalContext, ru, 45); @@ -941,127 +927,126 @@ public class SpringEL300Tests extends ExpressionTestCase { args.set(0,TypeDescriptor.forObject((byte)23)); me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); me.execute(emptyEvalContext, ru, (byte)23); - + args.set(0,TypeDescriptor.forObject(true)); me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); me.execute(emptyEvalContext, ru, true); - + // trickier: args.set(0,TypeDescriptor.forObject(12)); args.add(TypeDescriptor.forObject(23f)); me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"bar",args); me.execute(emptyEvalContext, ru, 12,23f); - + } - - - + + + public class ReflectionUtil { - public Object methodToCall(T param) { - System.out.println(param+" "+param.getClass()); - return "Object methodToCall(T param)"; - } - - public void foo(int... array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(float...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(double...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(short...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(long...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(boolean...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(char...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - public void foo(byte...array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - - public void bar(int... array) { - if (array.length==0) { - throw new RuntimeException(); - } - } - } - + public Object methodToCall(T param) { + System.out.println(param+" "+param.getClass()); + return "Object methodToCall(T param)"; + } + + public void foo(int... array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(float...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(double...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(short...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(long...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(boolean...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(char...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(byte...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + + public void bar(int... array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + } + @Test public void testReservedWords_8228() throws Exception { // "DIV","EQ","GE","GT","LE","LT","MOD","NE","NOT" - @SuppressWarnings("unused") - class Reserver { - public Reserver getReserver() { - return this; - } - public String NE = "abc"; - public String ne = "def"; - - public int DIV = 1; - public int div = 3; - - public Map m = new HashMap(); - - @SuppressWarnings("unchecked") + @SuppressWarnings("unused") + class Reserver { + public Reserver getReserver() { + return this; + } + public String NE = "abc"; + public String ne = "def"; + + public int DIV = 1; + public int div = 3; + + public Map m = new HashMap(); + Reserver() { - m.put("NE","xyz"); - } - } - StandardEvaluationContext ctx = new StandardEvaluationContext(new Reserver()); - SpelExpressionParser parser = new SpelExpressionParser(); - String ex = "getReserver().NE"; - SpelExpression exp = null; - exp = parser.parseRaw(ex); - String value = (String)exp.getValue(ctx); - Assert.assertEquals("abc",value); + m.put("NE","xyz"); + } + } + StandardEvaluationContext ctx = new StandardEvaluationContext(new Reserver()); + SpelExpressionParser parser = new SpelExpressionParser(); + String ex = "getReserver().NE"; + SpelExpression exp = null; + exp = parser.parseRaw(ex); + String value = (String)exp.getValue(ctx); + Assert.assertEquals("abc",value); - ex = "getReserver().ne"; - exp = parser.parseRaw(ex); - value = (String)exp.getValue(ctx); - Assert.assertEquals("def",value); + ex = "getReserver().ne"; + exp = parser.parseRaw(ex); + value = (String)exp.getValue(ctx); + Assert.assertEquals("def",value); - ex = "getReserver().m[NE]"; - exp = parser.parseRaw(ex); - value = (String)exp.getValue(ctx); - Assert.assertEquals("xyz",value); - - ex = "getReserver().DIV"; - exp = parser.parseRaw(ex); - Assert.assertEquals(1,exp.getValue(ctx)); + ex = "getReserver().m[NE]"; + exp = parser.parseRaw(ex); + value = (String)exp.getValue(ctx); + Assert.assertEquals("xyz",value); - ex = "getReserver().div"; - exp = parser.parseRaw(ex); - Assert.assertEquals(3,exp.getValue(ctx)); - - exp = parser.parseRaw("NE"); - Assert.assertEquals("abc",exp.getValue(ctx)); + ex = "getReserver().DIV"; + exp = parser.parseRaw(ex); + Assert.assertEquals(1,exp.getValue(ctx)); + + ex = "getReserver().div"; + exp = parser.parseRaw(ex); + Assert.assertEquals(3,exp.getValue(ctx)); + + exp = parser.parseRaw("NE"); + Assert.assertEquals("abc",exp.getValue(ctx)); } - + /** * We add property accessors in the order: * First, Second, Third, Fourth. @@ -1071,39 +1056,24 @@ public class SpringEL300Tests extends ExpressionTestCase { @Test public void testPropertyAccessorOrder_8211() { ExpressionParser expressionParser = new SpelExpressionParser(); - StandardEvaluationContext evaluationContext = + StandardEvaluationContext evaluationContext = new StandardEvaluationContext(new ContextObject()); - + evaluationContext.addPropertyAccessor(new TestPropertyAccessor("firstContext")); evaluationContext.addPropertyAccessor(new TestPropertyAccessor("secondContext")); evaluationContext.addPropertyAccessor(new TestPropertyAccessor("thirdContext")); evaluationContext.addPropertyAccessor(new TestPropertyAccessor("fourthContext")); - - assertEquals("first", + + assertEquals("first", expressionParser.parseExpression("shouldBeFirst").getValue(evaluationContext)); - assertEquals("second", + assertEquals("second", expressionParser.parseExpression("shouldBeSecond").getValue(evaluationContext)); - assertEquals("third", + assertEquals("third", expressionParser.parseExpression("shouldBeThird").getValue(evaluationContext)); - assertEquals("fourth", + assertEquals("fourth", expressionParser.parseExpression("shouldBeFourth").getValue(evaluationContext)); } - - // test not quite complete, it doesn't check that the list of resolvers at the end of - // PropertyOrFieldReference.getPropertyAccessorsToTry() doesn't contain duplicates, which - // is what it is trying to test by having a property accessor that returns specific - // classes Integer and Number -// @Test -// public void testPropertyAccessorOrder_8211_2() { -// ExpressionParser expressionParser = new SpelExpressionParser(); -// StandardEvaluationContext evaluationContext = -// new StandardEvaluationContext(new Integer(42)); -// -// evaluationContext.addPropertyAccessor(new TestPropertyAccessor2()); -// -// assertEquals("42", expressionParser.parseExpression("x").getValue(evaluationContext)); -// } - + class TestPropertyAccessor implements PropertyAccessor { private String mapName; public TestPropertyAccessor(String mapName) { @@ -1139,38 +1109,13 @@ public class SpringEL300Tests extends ExpressionTestCase { } } - -// class TestPropertyAccessor2 implements PropertyAccessor { -// -// public Class[] getSpecificTargetClasses() { -// return new Class[]{Integer.class,Number.class}; -// } -// -// public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException { -// return true; -// } -// -// public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { -// return new TypedValue(target.toString(),TypeDescriptor.valueOf(String.class)); -// } -// -// public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { -// return false; -// } -// -// public void write(EvaluationContext context, Object target, String name, Object newValue) -// throws AccessException { -// throw new UnsupportedOperationException(); -// } -// -// } class ContextObject { public Map firstContext = new HashMap(); public Map secondContext = new HashMap(); public Map thirdContext = new HashMap(); public Map fourthContext = new HashMap(); - + public ContextObject() { firstContext.put("shouldBeFirst", "first"); secondContext.put("shouldBeFirst", "second"); @@ -1180,10 +1125,10 @@ public class SpringEL300Tests extends ExpressionTestCase { secondContext.put("shouldBeSecond", "second"); thirdContext.put("shouldBeSecond", "third"); fourthContext.put("shouldBeSecond", "fourth"); - + thirdContext.put("shouldBeThird", "third"); fourthContext.put("shouldBeThird", "fourth"); - + fourthContext.put("shouldBeFourth", "fourth"); } public Map getFirstContext() {return firstContext;}