|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2016 the original author or authors. |
| 2 | + * Copyright 2002-2017 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
17 | 17 | package org.springframework.expression.spel;
|
18 | 18 |
|
19 | 19 | import java.io.IOException;
|
| 20 | +import java.lang.reflect.Field; |
20 | 21 | import java.lang.reflect.Method;
|
21 | 22 | import java.util.ArrayList;
|
| 23 | +import java.util.Collections; |
22 | 24 | import java.util.HashMap;
|
23 | 25 | import java.util.List;
|
24 | 26 | import java.util.Map;
|
@@ -4626,6 +4628,164 @@ public void indexerMapAccessor_12045() throws Exception {
|
4626 | 4628 | assertEquals(3, expression.getValue(root));
|
4627 | 4629 | assertEquals(3, expression.getValue(root));
|
4628 | 4630 | }
|
| 4631 | + |
| 4632 | + @Test |
| 4633 | + public void elvisOperator_SPR15192() { |
| 4634 | + SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null); |
| 4635 | + Expression exp; |
| 4636 | + |
| 4637 | + exp = new SpelExpressionParser(configuration).parseExpression("bar()"); |
| 4638 | + assertEquals("BAR", exp.getValue(new Foo(), String.class)); |
| 4639 | + assertCanCompile(exp); |
| 4640 | + assertEquals("BAR", exp.getValue(new Foo(), String.class)); |
| 4641 | + assertIsCompiled(exp); |
| 4642 | + |
| 4643 | + exp = new SpelExpressionParser(configuration).parseExpression("bar('baz')"); |
| 4644 | + assertEquals("BAZ", exp.getValue(new Foo(), String.class)); |
| 4645 | + assertCanCompile(exp); |
| 4646 | + assertEquals("BAZ", exp.getValue(new Foo(), String.class)); |
| 4647 | + assertIsCompiled(exp); |
| 4648 | + |
| 4649 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 4650 | + context.setVariable("map", Collections.singletonMap("foo", "qux")); |
| 4651 | + |
| 4652 | + exp = new SpelExpressionParser(configuration).parseExpression("bar(#map['foo'])"); |
| 4653 | + assertEquals("QUX", exp.getValue(context, new Foo(), String.class)); |
| 4654 | + assertCanCompile(exp); |
| 4655 | + assertEquals("QUX", exp.getValue(context, new Foo(), String.class)); |
| 4656 | + assertIsCompiled(exp); |
| 4657 | + |
| 4658 | + exp = new SpelExpressionParser(configuration).parseExpression("bar(#map['foo'] ?: 'qux')"); |
| 4659 | + assertEquals("QUX", exp.getValue(context, new Foo(), String.class)); |
| 4660 | + assertCanCompile(exp); |
| 4661 | + assertEquals("QUX", exp.getValue(context, new Foo(), String.class)); |
| 4662 | + assertIsCompiled(exp); |
| 4663 | + |
| 4664 | + // When the condition is a primitive |
| 4665 | + exp = new SpelExpressionParser(configuration).parseExpression("3?:'foo'"); |
| 4666 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4667 | + assertCanCompile(exp); |
| 4668 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4669 | + assertIsCompiled(exp); |
| 4670 | + |
| 4671 | + // When the condition is a double slot primitive |
| 4672 | + exp = new SpelExpressionParser(configuration).parseExpression("3L?:'foo'"); |
| 4673 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4674 | + assertCanCompile(exp); |
| 4675 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4676 | + assertIsCompiled(exp); |
| 4677 | + |
| 4678 | + // When the condition is an empty string |
| 4679 | + exp = new SpelExpressionParser(configuration).parseExpression("''?:4L"); |
| 4680 | + assertEquals("4", exp.getValue(context, new Foo(), String.class)); |
| 4681 | + assertCanCompile(exp); |
| 4682 | + assertEquals("4", exp.getValue(context, new Foo(), String.class)); |
| 4683 | + assertIsCompiled(exp); |
| 4684 | + |
| 4685 | + // null condition |
| 4686 | + exp = new SpelExpressionParser(configuration).parseExpression("null?:4L"); |
| 4687 | + assertEquals("4", exp.getValue(context, new Foo(), String.class)); |
| 4688 | + assertCanCompile(exp); |
| 4689 | + assertEquals("4", exp.getValue(context, new Foo(), String.class)); |
| 4690 | + assertIsCompiled(exp); |
| 4691 | + |
| 4692 | + // variable access returning primitive |
| 4693 | + exp = new SpelExpressionParser(configuration).parseExpression("#x?:'foo'"); |
| 4694 | + context.setVariable("x",50); |
| 4695 | + assertEquals("50", exp.getValue(context, new Foo(), String.class)); |
| 4696 | + assertCanCompile(exp); |
| 4697 | + assertEquals("50", exp.getValue(context, new Foo(), String.class)); |
| 4698 | + assertIsCompiled(exp); |
| 4699 | + |
| 4700 | + exp = new SpelExpressionParser(configuration).parseExpression("#x?:'foo'"); |
| 4701 | + context.setVariable("x",null); |
| 4702 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4703 | + assertCanCompile(exp); |
| 4704 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4705 | + assertIsCompiled(exp); |
| 4706 | + |
| 4707 | + // variable access returning array |
| 4708 | + exp = new SpelExpressionParser(configuration).parseExpression("#x?:'foo'"); |
| 4709 | + context.setVariable("x",new int[]{1,2,3}); |
| 4710 | + assertEquals("1,2,3", exp.getValue(context, new Foo(), String.class)); |
| 4711 | + assertCanCompile(exp); |
| 4712 | + assertEquals("1,2,3", exp.getValue(context, new Foo(), String.class)); |
| 4713 | + assertIsCompiled(exp); |
| 4714 | + } |
| 4715 | + |
| 4716 | + @Test |
| 4717 | + public void ternaryOperator_SPR15192() { |
| 4718 | + SpelParserConfiguration configuration = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, null); |
| 4719 | + Expression exp; |
| 4720 | + StandardEvaluationContext context = new StandardEvaluationContext(); |
| 4721 | + context.setVariable("map", Collections.singletonMap("foo", "qux")); |
| 4722 | + |
| 4723 | + exp = new SpelExpressionParser(configuration).parseExpression("bar(#map['foo'] != null ? #map['foo'] : 'qux')"); |
| 4724 | + assertEquals("QUX", exp.getValue(context, new Foo(), String.class)); |
| 4725 | + assertCanCompile(exp); |
| 4726 | + assertEquals("QUX", exp.getValue(context, new Foo(), String.class)); |
| 4727 | + assertIsCompiled(exp); |
| 4728 | + |
| 4729 | + exp = new SpelExpressionParser(configuration).parseExpression("3==3?3:'foo'"); |
| 4730 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4731 | + assertCanCompile(exp); |
| 4732 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4733 | + assertIsCompiled(exp); |
| 4734 | + exp = new SpelExpressionParser(configuration).parseExpression("3!=3?3:'foo'"); |
| 4735 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4736 | + assertCanCompile(exp); |
| 4737 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4738 | + assertIsCompiled(exp); |
| 4739 | + |
| 4740 | + // When the condition is a double slot primitive |
| 4741 | + exp = new SpelExpressionParser(configuration).parseExpression("3==3?3L:'foo'"); |
| 4742 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4743 | + assertCanCompile(exp); |
| 4744 | + assertEquals("3", exp.getValue(context, new Foo(), String.class)); |
| 4745 | + assertIsCompiled(exp); |
| 4746 | + exp = new SpelExpressionParser(configuration).parseExpression("3!=3?3L:'foo'"); |
| 4747 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4748 | + assertCanCompile(exp); |
| 4749 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4750 | + assertIsCompiled(exp); |
| 4751 | + |
| 4752 | + // When the condition is an empty string |
| 4753 | + exp = new SpelExpressionParser(configuration).parseExpression("''==''?'abc':4L"); |
| 4754 | + assertEquals("abc", exp.getValue(context, new Foo(), String.class)); |
| 4755 | + assertCanCompile(exp); |
| 4756 | + assertEquals("abc", exp.getValue(context, new Foo(), String.class)); |
| 4757 | + assertIsCompiled(exp); |
| 4758 | + |
| 4759 | + // null condition |
| 4760 | + exp = new SpelExpressionParser(configuration).parseExpression("3==3?null:4L"); |
| 4761 | + assertEquals(null, exp.getValue(context, new Foo(), String.class)); |
| 4762 | + assertCanCompile(exp); |
| 4763 | + assertEquals(null, exp.getValue(context, new Foo(), String.class)); |
| 4764 | + assertIsCompiled(exp); |
| 4765 | + |
| 4766 | + // variable access returning primitive |
| 4767 | + exp = new SpelExpressionParser(configuration).parseExpression("#x==#x?50:'foo'"); |
| 4768 | + context.setVariable("x",50); |
| 4769 | + assertEquals("50", exp.getValue(context, new Foo(), String.class)); |
| 4770 | + assertCanCompile(exp); |
| 4771 | + assertEquals("50", exp.getValue(context, new Foo(), String.class)); |
| 4772 | + assertIsCompiled(exp); |
| 4773 | + |
| 4774 | + exp = new SpelExpressionParser(configuration).parseExpression("#x!=#x?50:'foo'"); |
| 4775 | + context.setVariable("x",null); |
| 4776 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4777 | + assertCanCompile(exp); |
| 4778 | + assertEquals("foo", exp.getValue(context, new Foo(), String.class)); |
| 4779 | + assertIsCompiled(exp); |
| 4780 | + |
| 4781 | + // variable access returning array |
| 4782 | + exp = new SpelExpressionParser(configuration).parseExpression("#x==#x?'1,2,3':'foo'"); |
| 4783 | + context.setVariable("x",new int[]{1,2,3}); |
| 4784 | + assertEquals("1,2,3", exp.getValue(context, new Foo(), String.class)); |
| 4785 | + assertCanCompile(exp); |
| 4786 | + assertEquals("1,2,3", exp.getValue(context, new Foo(), String.class)); |
| 4787 | + assertIsCompiled(exp); |
| 4788 | + } |
4629 | 4789 |
|
4630 | 4790 |
|
4631 | 4791 | // helper methods
|
@@ -4687,6 +4847,20 @@ private void assertGetValueFail(Expression expression) {
|
4687 | 4847 | }
|
4688 | 4848 | }
|
4689 | 4849 |
|
| 4850 | + private void assertIsCompiled(Expression expression) { |
| 4851 | + try { |
| 4852 | + Field field = SpelExpression.class.getDeclaredField("compiledAst"); |
| 4853 | + field.setAccessible(true); |
| 4854 | + Object object = field.get(expression); |
| 4855 | + assertNotNull(object); |
| 4856 | + } |
| 4857 | + catch (Exception ex) { |
| 4858 | + fail(ex.toString()); |
| 4859 | + } |
| 4860 | + } |
| 4861 | + |
| 4862 | + |
| 4863 | + // nested types |
4690 | 4864 |
|
4691 | 4865 | public interface Message<T> {
|
4692 | 4866 |
|
@@ -4803,7 +4977,7 @@ public void generateCode(String propertyName, MethodVisitor mv,CodeFlow cf) {
|
4803 | 4977 | try {
|
4804 | 4978 | method = Payload2.class.getDeclaredMethod("getField", String.class);
|
4805 | 4979 | }
|
4806 |
| - catch (Exception e) { |
| 4980 | + catch (Exception ex) { |
4807 | 4981 | }
|
4808 | 4982 | }
|
4809 | 4983 | String descriptor = cf.lastDescriptor();
|
@@ -5661,4 +5835,16 @@ public Map<String, String> getData() {
|
5661 | 5835 | }
|
5662 | 5836 | }
|
5663 | 5837 |
|
| 5838 | + |
| 5839 | + public static class Foo { |
| 5840 | + |
| 5841 | + public String bar() { |
| 5842 | + return "BAR"; |
| 5843 | + } |
| 5844 | + |
| 5845 | + public String bar(String arg) { |
| 5846 | + return arg.toUpperCase(); |
| 5847 | + } |
| 5848 | + } |
| 5849 | + |
5664 | 5850 | }
|
0 commit comments