001 /*
002 * $Id: TestOgnlRuntime.java 1203594 2011-11-18 11:04:51Z mcucchiara $
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 */
020 package org.apache.commons.ognl;
021
022 import org.apache.commons.ognl.enhance.OgnlExpressionCompiler;
023 import org.apache.commons.ognl.internal.CacheException;
024 import org.apache.commons.ognl.test.objects.BaseGeneric;
025 import org.apache.commons.ognl.test.objects.Bean1;
026 import org.apache.commons.ognl.test.objects.Bean2;
027 import org.apache.commons.ognl.test.objects.FormImpl;
028 import org.apache.commons.ognl.test.objects.GameGeneric;
029 import org.apache.commons.ognl.test.objects.GameGenericObject;
030 import org.apache.commons.ognl.test.objects.GenericCracker;
031 import org.apache.commons.ognl.test.objects.GenericService;
032 import org.apache.commons.ognl.test.objects.GenericServiceImpl;
033 import org.apache.commons.ognl.test.objects.GetterMethods;
034 import org.apache.commons.ognl.test.objects.IComponent;
035 import org.apache.commons.ognl.test.objects.IForm;
036 import org.apache.commons.ognl.test.objects.ListSource;
037 import org.apache.commons.ognl.test.objects.ListSourceImpl;
038 import org.apache.commons.ognl.test.objects.OtherObjectIndexed;
039 import org.apache.commons.ognl.test.objects.Root;
040 import org.apache.commons.ognl.test.objects.SetterReturns;
041 import org.apache.commons.ognl.test.objects.SubclassSyntheticObject;
042 import org.junit.Test;
043
044 import java.beans.IntrospectionException;
045 import java.beans.PropertyDescriptor;
046 import java.io.Serializable;
047 import java.lang.reflect.Field;
048 import java.lang.reflect.Method;
049 import java.util.Arrays;
050 import java.util.List;
051
052 import static junit.framework.Assert.*;
053
054 /**
055 * Tests various methods / functionality of {@link org.apache.commons.ognl.OgnlRuntime}.
056 */
057 public class TestOgnlRuntime
058 {
059
060 @Test
061 public void test_Get_Super_Or_Interface_Class()
062 throws Exception
063 {
064 ListSource list = new ListSourceImpl();
065
066 Method method = OgnlRuntime.getReadMethod( list.getClass(), "total" );
067 assertNotNull( method );
068
069 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
070 assertEquals( ListSource.class,
071 OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( method, list.getClass() ) );
072 }
073
074 @Test
075 public void test_Get_Private_Class()
076 throws Exception
077 {
078 List list = Arrays.asList( "hello", "world" );
079
080 Method m = OgnlRuntime.getReadMethod( list.getClass(), "iterator" );
081 assertNotNull( m );
082
083 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
084 assertEquals( Iterable.class,
085 OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( m, list.getClass() ) );
086 }
087
088 @Test
089 public void test_Complicated_Inheritance()
090 throws Exception
091 {
092 IForm form = new FormImpl();
093
094 Method method = OgnlRuntime.getWriteMethod( form.getClass(), "clientId" );
095 assertNotNull( method );
096
097 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
098 assertEquals( IComponent.class,
099 OgnlRuntime.getCompiler( context ).getSuperOrInterfaceClass( method, form.getClass() ) );
100 }
101
102 @Test
103 public void test_Get_Read_Method()
104 throws Exception
105 {
106 Method method = OgnlRuntime.getReadMethod( Bean2.class, "pageBreakAfter" );
107 assertNotNull( method );
108
109 assertEquals( "isPageBreakAfter", method.getName() );
110 }
111
112 class TestGetters
113 {
114 public boolean isEditorDisabled()
115 {
116 return false;
117 }
118
119 public boolean isDisabled()
120 {
121 return true;
122 }
123
124 public boolean isNotAvailable()
125 {
126 return false;
127 }
128
129 public boolean isAvailable()
130 {
131 return true;
132 }
133 }
134
135 @Test
136 public void test_Get_Read_Method_Multiple()
137 throws Exception
138 {
139 Method method = OgnlRuntime.getReadMethod( TestGetters.class, "disabled" );
140 assertNotNull( method );
141
142 assertEquals( "isDisabled", method.getName() );
143 }
144
145 @Test
146 public void test_Get_Read_Method_Multiple_Boolean_Getters()
147 throws Exception
148 {
149 Method method = OgnlRuntime.getReadMethod( TestGetters.class, "available" );
150 assertNotNull( method );
151
152 assertEquals( "isAvailable", method.getName() );
153
154 method = OgnlRuntime.getReadMethod( TestGetters.class, "notAvailable" );
155 assertNotNull( method );
156
157 assertEquals( "isNotAvailable", method.getName() );
158 }
159
160 @Test
161 public void test_Find_Method_Mixed_Boolean_Getters()
162 throws Exception
163 {
164 Method method = OgnlRuntime.getReadMethod( GetterMethods.class, "allowDisplay" );
165 assertNotNull( method );
166
167 assertEquals( "getAllowDisplay", method.getName() );
168 }
169
170 @Test
171 public void test_Get_Appropriate_Method()
172 throws Exception
173 {
174 ListSource list = new ListSourceImpl();
175 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
176
177 Object ret = OgnlRuntime.callMethod( context, list, "addValue", new String[]{ null } );
178
179 assert ret != null;
180 }
181
182 @Test
183 public void test_Call_Static_Method_Invalid_Class()
184 {
185
186 try
187 {
188 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
189 OgnlRuntime.callStaticMethod( context, "made.up.Name", "foo", null );
190
191 fail( "ClassNotFoundException should have been thrown by previous reference to <made.up.Name> class." );
192 }
193 catch ( Exception et )
194 {
195 assertTrue( MethodFailedException.class.isInstance( et ) );
196 assertTrue( et.getMessage().contains( "made.up.Name" ) );
197 }
198 }
199
200 @Test
201 public void test_Setter_Returns()
202 throws Exception
203 {
204 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
205 SetterReturns root = new SetterReturns();
206
207 Method m = OgnlRuntime.getWriteMethod( root.getClass(), "value" );
208 assertTrue( m != null );
209
210 Ognl.setValue( "value", context, root, "12__" );
211 assertEquals( Ognl.getValue( "value", context, root ), "12__" );
212 }
213
214 @Test
215 public void test_Call_Method_VarArgs()
216 throws Exception
217 {
218 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
219 GenericService service = new GenericServiceImpl();
220
221 GameGenericObject argument = new GameGenericObject();
222
223 Object[] args = OgnlRuntime.getObjectArrayPool().create( 2 );
224 args[0] = argument;
225
226 assertEquals( "Halo 3", OgnlRuntime.callMethod( context, service, "getFullMessageFor", args ) );
227 }
228
229 @Test
230 public void test_Class_Cache_Inspector()
231 throws Exception
232 {
233 OgnlRuntime.cache.clear();
234
235 assertEquals( 0, OgnlRuntime.cache.propertyDescriptorCache.getSize() );
236
237 Root root = new Root();
238 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
239 Node expr = Ognl.compileExpression( context, root, "property.bean3.value != null" );
240
241 assertTrue( (Boolean) expr.getAccessor().get( context, root ) );
242
243 int size = OgnlRuntime.cache.propertyDescriptorCache.getSize();
244 assertTrue( size > 0 );
245
246 OgnlRuntime.clearCache();
247 assertEquals( 0, OgnlRuntime.cache.propertyDescriptorCache.getSize() );
248
249 // now register class cache prevention
250
251 OgnlRuntime.setClassCacheInspector( new TestCacheInspector() );
252
253 expr = Ognl.compileExpression( context, root, "property.bean3.value != null" );
254 assertTrue( (Boolean) expr.getAccessor().get( context, root ) );
255
256 assertEquals( ( size - 1 ), OgnlRuntime.cache.propertyDescriptorCache.getSize() );
257 }
258
259 class TestCacheInspector
260 implements ClassCacheInspector
261 {
262
263 public boolean shouldCache( Class<?> type )
264 {
265 return !( type == null || type == Root.class );
266 }
267 }
268
269 @Test
270 public void test_Set_Generic_Parameter_Types()
271 throws Exception
272 {
273 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
274
275 Method method = OgnlRuntime.getSetMethod( context, GenericCracker.class, "param" );
276 assertNotNull( method );
277
278 Class[] types = method.getParameterTypes();
279 assertEquals( 1, types.length );
280 assertEquals( Integer.class, types[0] );
281 }
282
283 @Test
284 public void test_Get_Generic_Parameter_Types()
285 throws Exception
286 {
287 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
288
289 Method method = OgnlRuntime.getGetMethod( context, GenericCracker.class, "param" );
290 assertNotNull( method );
291
292 assertEquals( Integer.class, method.getReturnType() );
293 }
294
295 @Test
296 public void test_Find_Parameter_Types()
297 throws Exception
298 {
299 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
300
301 Method method = OgnlRuntime.getSetMethod( context, GameGeneric.class, "ids" );
302 assertNotNull( method );
303
304 Class[] types = OgnlRuntime.findParameterTypes( GameGeneric.class, method );
305 assertEquals( 1, types.length );
306 assertEquals( Long[].class, types[0] );
307 }
308
309 @Test
310 public void test_Find_Parameter_Types_Superclass()
311 throws Exception
312 {
313 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
314
315 Method method = OgnlRuntime.getSetMethod( context, BaseGeneric.class, "ids" );
316 assertNotNull( method );
317
318 Class[] types = OgnlRuntime.findParameterTypes( BaseGeneric.class, method );
319 assertEquals( 1, types.length );
320 assertEquals( Serializable[].class, types[0] );
321 }
322
323 @Test
324 public void test_Get_Declared_Methods_With_Synthetic_Methods()
325 throws Exception
326 {
327 List result = OgnlRuntime.getDeclaredMethods( SubclassSyntheticObject.class, "list", false );
328
329 // synthetic method would be
330 // "public volatile java.util.List org.ognl.test.objects.SubclassSyntheticObject.getList()",
331 // causing method return size to be 3
332
333 assertEquals( 2, result.size() );
334 }
335
336 @Test
337 public void test_Get_Property_Descriptors_With_Synthetic_Methods()
338 throws Exception
339 {
340 PropertyDescriptor propertyDescriptor = OgnlRuntime.getPropertyDescriptor( SubclassSyntheticObject.class, "list" );
341
342 assert propertyDescriptor != null;
343 assert OgnlRuntime.isMethodCallable( propertyDescriptor.getReadMethod() );
344 }
345
346 private static class GenericParent<T>
347 {
348 public void save( T entity )
349 {
350
351 }
352 }
353
354 private static class StringChild
355 extends GenericParent<String>
356 {
357
358 }
359
360 private static class LongChild
361 extends GenericParent<Long>
362 {
363
364 }
365
366 /**
367 * Tests OGNL parameter discovery.
368 */
369 @Test
370 public void testOGNLParameterDiscovery()
371 throws NoSuchMethodException, CacheException
372 {
373 Method saveMethod = GenericParent.class.getMethod( "save", Object.class );
374 System.out.println( saveMethod );
375
376 Class[] longClass = OgnlRuntime.findParameterTypes( LongChild.class, saveMethod );
377 assertNotSame( longClass[0], String.class );
378 assertSame( longClass[0], Long.class );
379
380 Class[] stringClass = OgnlRuntime.findParameterTypes( StringChild.class, saveMethod );
381 assertNotSame( "The cached parameter types from previous calls are used", stringClass[0], Long.class );
382 assertSame( stringClass[0], String.class );
383 }
384
385 @Test
386 public void testGetField()
387 throws OgnlException
388 {
389 Field field = OgnlRuntime.getField( OtherObjectIndexed.class, "attributes" );
390 assertNotNull( "Field is null", field );
391 }
392
393 @Test
394 public void testGetSetMethod()
395 throws IntrospectionException, OgnlException
396 {
397 Method setter = OgnlRuntime.getSetMethod( null, Bean1.class, "bean2" );
398 Method getter = OgnlRuntime.getGetMethod( null, Bean1.class, "bean2" );
399 assertNotNull( getter );
400 assertNull( setter );
401 }
402
403 @Test
404 public void testGetCompiler()
405 {
406 OgnlContext context = (OgnlContext) Ognl.createDefaultContext( null );
407 OgnlExpressionCompiler compiler1 = OgnlRuntime.getCompiler( context );
408 context.put( "root2", new Root() );
409 OgnlExpressionCompiler compiler2 = OgnlRuntime.getCompiler( context );
410 assertSame( "compilers are not the same", compiler1, compiler2 );
411 }
412
413 @Test
414 public void testGetPropertyDescriptorFromArray()
415 throws Exception
416 {
417 PropertyDescriptor propertyDescriptor =
418 OgnlRuntime.getPropertyDescriptorFromArray( Root.class, "disabled" );
419 assertEquals( "disabled", propertyDescriptor.getName() );
420 }
421 }