View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.jexl3.internal.introspection;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
21  import static org.junit.jupiter.api.Assertions.assertNotEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  
24  import java.io.Serializable;
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.commons.jexl3.JexlTestCase;
31  import org.apache.commons.jexl3.internal.Engine;
32  import org.apache.commons.jexl3.introspection.JexlMethod;
33  import org.apache.commons.jexl3.introspection.JexlPropertyGet;
34  import org.apache.commons.jexl3.introspection.JexlPropertySet;
35  import org.apache.commons.jexl3.introspection.JexlUberspect;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Tests for checking introspection discovery.
40   */
41  @SuppressWarnings("unused")
42  class DiscoveryTest extends JexlTestCase {
43      public static class Bean {
44          private String value;
45          private String eulav;
46          private boolean flag;
47  
48          public Bean(final String v, final String e) {
49              value = v;
50              eulav = e;
51              flag = true;
52          }
53  
54          public String getEulav() {
55              return eulav;
56          }
57  
58          public String getValue() {
59              return value;
60          }
61  
62          public boolean isFlag() {
63              return flag;
64          }
65  
66          public void setEulav(final String v) {
67              eulav = v;
68          }
69  
70          public void setFlag(final boolean f) {
71              flag = f;
72          }
73  
74          public void setValue(final String v) {
75              value = v;
76          }
77      }
78  
79      public static class Bulgroz {
80          public Object amb(final Number x) {
81              return -2;
82          }
83          public Object amb(final Serializable x) {
84              return -1;
85          }
86          public Object list(final int x) {
87              return 0;
88          }
89          public Object list(final int x, final int y) {
90              return 4;
91          }
92          public Object list(final int x, final Object...y) {
93              return 3;
94          }
95          public Object list(final Object x) {
96              return 2;
97          }
98          public Object list(final Object x, final Object...y) {
99              return 7;
100         }
101         public Object list(final Object x, final Object y) {
102             return 8;
103         }
104         public Object list(final String x) {
105             return 1;
106         }
107         public Object list(final String x, final Object...y) {
108             return 5;
109         }
110         public Object list(final String x, final String y) {
111             return 6;
112         }
113     }
114 
115     public static class Duck {
116         private String value;
117         private String eulav;
118 
119         public Duck(final String v, final String e) {
120             value = v;
121             eulav = e;
122         }
123 
124         public String get(final String prop) {
125             if ("value".equals(prop)) {
126                 return value;
127             }
128             if ("eulav".equals(prop)) {
129                 return eulav;
130             }
131             return "no such property";
132         }
133 
134         public void set(final String prop, final String v) {
135             if ("value".equals(prop)) {
136                 value = v;
137             } else if ("eulav".equals(prop)) {
138                 eulav = v;
139             }
140         }
141     }
142 
143     public DiscoveryTest() {
144         super("DiscoveryTest");
145     }
146 
147     @Test
148     void testBeanIntrospection() throws Exception {
149         final JexlUberspect uber = Engine.getUberspect(null, null, JexlTestCase.TEST_PERMS);
150         final Bean bean = new Bean("JEXL", "LXEJ");
151 
152         final JexlPropertyGet get = uber.getPropertyGet(bean, "value");
153         final JexlPropertySet set = uber.getPropertySet(bean, "value", "foo");
154         assertInstanceOf(PropertyGetExecutor.class, get, "bean property getter");
155         assertInstanceOf(PropertySetExecutor.class, set, "bean property setter");
156         // introspector and uberspect should return same result
157         assertEquals(get, uber.getPropertyGet(bean, "value"));
158         assertEquals(set, uber.getPropertySet(bean, "value", "foo"));
159         // different property should return different setter/getter
160         assertNotEquals(get, uber.getPropertyGet(bean, "eulav"));
161         assertNotEquals(set, uber.getPropertySet(bean, "eulav", "foo"));
162         // setter returns argument
163         final Object bar = set.invoke(bean, "bar");
164         assertEquals("bar", bar);
165         // getter should return last value
166         assertEquals("bar", get.invoke(bean));
167         // tryExecute should succeed on same property
168         final Object quux = set.tryInvoke(bean, "value", "quux");
169         assertEquals("quux", quux);
170         assertEquals("quux", get.invoke(bean));
171         // tryExecute should fail on different property
172         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(bean, "eulav", "nope"));
173 
174     }
175 
176     @Test
177     void testDuckIntrospection() throws Exception {
178         final JexlUberspect uber = Engine.getUberspect(null, null, JexlTestCase.TEST_PERMS);
179         final Duck duck = new Duck("JEXL", "LXEJ");
180 
181         final JexlPropertyGet get = uber.getPropertyGet(duck, "value");
182         final JexlPropertySet set = uber.getPropertySet(duck, "value", "foo");
183         assertInstanceOf(DuckGetExecutor.class, get, "duck property getter");
184         assertInstanceOf(DuckSetExecutor.class, set, "duck property setter");
185         // introspector and uberspect should return same result
186         assertEquals(get, uber.getPropertyGet(duck, "value"));
187         assertEquals(set, uber.getPropertySet(duck, "value", "foo"));
188         // different property should return different setter/getter
189         assertNotEquals(get, uber.getPropertyGet(duck, "eulav"));
190         assertNotEquals(set, uber.getPropertySet(duck, "eulav", "foo"));
191         // setter returns argument
192         final Object bar = set.invoke(duck, "bar");
193         assertEquals("bar", bar);
194         // getter should return last value
195         assertEquals("bar", get.invoke(duck));
196         // tryExecute should succeed on same property
197         final Object quux = set.tryInvoke(duck, "value", "quux");
198         assertEquals("quux", quux);
199         assertEquals("quux", get.invoke(duck));
200         // tryExecute should fail on different property
201         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(duck, "eulav", "nope"));
202     }
203 
204     @Test
205     void testListIntrospection() throws Exception {
206         final JexlUberspect uber = new Uberspect(null, null);
207         final List<Object> list = new ArrayList<>();
208         list.add("LIST");
209         list.add("TSIL");
210 
211         final JexlPropertyGet get = uber.getPropertyGet(list, 1);
212         final JexlPropertySet set = uber.getPropertySet(list, 1, "foo");
213         assertInstanceOf(ListGetExecutor.class, get, "list property getter");
214         assertInstanceOf(ListSetExecutor.class, set, "list property setter");
215         // introspector and uberspect should return same result
216         assertEquals(get, uber.getPropertyGet(list, 1));
217         assertEquals(set, uber.getPropertySet(list, 1, "foo"));
218         // different property should return different setter/getter
219         assertNotEquals(get, uber.getPropertyGet(list, 0));
220         assertNotEquals(set, uber.getPropertySet(list, 0, "foo"));
221         // setter returns argument
222         final Object bar = set.invoke(list, "bar");
223         assertEquals("bar", bar);
224         // getter should return last value
225         assertEquals("bar", get.invoke(list));
226         // tryExecute should succeed on integer property
227         final Object quux = set.tryInvoke(list, 1, "quux");
228         assertEquals("quux", quux);
229         // getter should return last value
230         assertEquals("quux", get.invoke(list));
231         // tryExecute should fail on non-integer property class
232         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(list, "eulav", "nope"));
233     }
234 
235     @Test
236     void testMapIntrospection() throws Exception {
237         final JexlUberspect uber = new Uberspect(null, null);
238         final Map<String, Object> map = new HashMap<>();
239         map.put("value", "MAP");
240         map.put("eulav", "PAM");
241 
242         final JexlPropertyGet get = uber.getPropertyGet(map, "value");
243         final JexlPropertySet set = uber.getPropertySet(map, "value", "foo");
244         assertInstanceOf(MapGetExecutor.class, get, "map property getter");
245         assertInstanceOf(MapSetExecutor.class, set, "map property setter");
246         // introspector and uberspect should return same result
247         assertEquals(get, uber.getPropertyGet(map, "value"));
248         assertEquals(set, uber.getPropertySet(map, "value", "foo"));
249         // different property should return different setter/getter
250         assertNotEquals(get, uber.getPropertyGet(map, "eulav"));
251         assertNotEquals(set, uber.getPropertySet(map, "eulav", "foo"));
252         // setter returns argument
253         final Object bar = set.invoke(map, "bar");
254         assertEquals("bar", bar);
255         // getter should return last value
256         assertEquals("bar", get.invoke(map));
257         // tryExecute should succeed on same property class
258         final Object quux = set.tryInvoke(map, "value", "quux");
259         assertEquals("quux", quux);
260         // getter should return last value
261         assertEquals("quux", get.invoke(map));
262         // tryExecute should fail on different property class
263         assertEquals(AbstractExecutor.TRY_FAILED, set.tryInvoke(map, 1, "nope"));
264     }
265 
266     @Test
267     void testMethodIntrospection() throws Exception {
268         final JexlUberspect uber = new Uberspect(null, null, JexlTestCase.TEST_PERMS);
269         final Bulgroz bulgroz = new Bulgroz();
270         JexlMethod jmethod;
271         Object result;
272         jmethod = uber.getMethod(bulgroz, "list", 0);
273         result = jmethod.invoke(bulgroz, 0);
274         assertEquals(0, result);
275         jmethod = uber.getMethod(bulgroz, "list", "1");
276         result = jmethod.invoke(bulgroz, "1");
277         assertEquals(1, result);
278         jmethod = uber.getMethod(bulgroz, "list", bulgroz);
279         result = jmethod.invoke(bulgroz, bulgroz);
280         assertEquals(2, result);
281         jmethod = uber.getMethod(bulgroz, "list", 1, bulgroz);
282         result = jmethod.invoke(bulgroz, 1, bulgroz);
283         assertEquals(3, result);
284         jmethod = uber.getMethod(bulgroz, "list", 1, bulgroz, bulgroz);
285         result = jmethod.invoke(bulgroz, 1, bulgroz, bulgroz);
286         assertEquals(3, result);
287         jmethod = uber.getMethod(bulgroz, "list", 1, 2);
288         result = jmethod.invoke(bulgroz, 1, 2);
289         assertEquals(4, result);
290         jmethod = uber.getMethod(bulgroz, "list", "1", bulgroz);
291         result = jmethod.invoke(bulgroz, "1", bulgroz);
292         assertEquals(5, result);
293         jmethod = uber.getMethod(bulgroz, "list", "1", "2");
294         result = jmethod.invoke(bulgroz, "1", "2");
295         assertEquals(6, result);
296         jmethod = uber.getMethod(bulgroz, "list", bulgroz, bulgroz);
297         result = jmethod.invoke(bulgroz, bulgroz, bulgroz);
298         assertEquals(8, result);
299         jmethod = uber.getMethod(bulgroz, "list", bulgroz, 1, bulgroz);
300         result = jmethod.invoke(bulgroz, bulgroz, 1, bulgroz);
301         assertEquals(7, result);
302         jmethod = uber.getMethod(bulgroz, "list", bulgroz, 1, "1");
303         result = jmethod.invoke(bulgroz, bulgroz, 1, "1");
304         assertEquals(7, result);
305         jmethod = uber.getMethod(bulgroz, "list", (Object) null);
306         result = jmethod.invoke(bulgroz,  (Object) null);
307         assertEquals(2, result);
308         jmethod = uber.getMethod(bulgroz, "list", bulgroz, (Object) null);
309         result = jmethod.invoke(bulgroz, bulgroz, (Object) null);
310         assertEquals(8, result);
311         jmethod = uber.getMethod(bulgroz, "list", null, "1");
312         result = jmethod.invoke(bulgroz, null, "1");
313         assertEquals(8, result);
314         jmethod = uber.getMethod(bulgroz, "list", bulgroz, null, null);
315         result = jmethod.invoke(bulgroz, bulgroz, null, null);
316         assertEquals(7, result);
317 
318         jmethod = uber.getMethod(bulgroz, "amb", 3d);
319         assertNotNull(jmethod);
320     }
321 }