1 package org.apache.commons.ognl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.ognl.enhance.ExpressionCompiler;
23 import org.apache.commons.ognl.enhance.OgnlExpressionCompiler;
24 import org.apache.commons.ognl.internal.CacheException;
25 import org.apache.commons.ognl.internal.entry.DeclaredMethodCacheEntry;
26 import org.apache.commons.ognl.internal.entry.GenericMethodParameterTypeCacheEntry;
27 import org.apache.commons.ognl.internal.entry.MethodAccessEntryValue;
28 import org.apache.commons.ognl.internal.entry.PermissionCacheEntry;
29
30 import java.beans.BeanInfo;
31 import java.beans.IndexedPropertyDescriptor;
32 import java.beans.IntrospectionException;
33 import java.beans.Introspector;
34 import java.beans.MethodDescriptor;
35 import java.beans.PropertyDescriptor;
36 import java.lang.reflect.Constructor;
37 import java.lang.reflect.Field;
38 import java.lang.reflect.InvocationTargetException;
39 import java.lang.reflect.Member;
40 import java.lang.reflect.Method;
41 import java.lang.reflect.Modifier;
42 import java.lang.reflect.ParameterizedType;
43 import java.lang.reflect.Proxy;
44 import java.security.Permission;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.Collections;
48 import java.util.HashMap;
49 import java.util.List;
50 import java.util.Map;
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public class OgnlRuntime
67 {
68
69
70
71
72 public static final Object NotFound = new Object();
73
74 public static final Object[] NoArguments = new Object[]{ };
75
76
77
78
79 public static final Object NoConversionPossible = "ognl.NoConversionPossible";
80
81
82
83
84 public static final int INDEXED_PROPERTY_NONE = 0;
85
86
87
88
89 public static final int INDEXED_PROPERTY_INT = 1;
90
91
92
93
94 public static final int INDEXED_PROPERTY_OBJECT = 2;
95
96
97
98
99 public static final String NULL_STRING = "" + null;
100
101
102
103
104 public static final String SET_PREFIX = "set";
105
106
107
108
109 public static final String GET_PREFIX = "get";
110
111
112
113
114 public static final String IS_PREFIX = "is";
115
116
117
118
119 private static final Map<Integer, String> HEX_PADDING = new HashMap<Integer, String>();
120
121 private static final int HEX_LENGTH = 8;
122
123
124
125
126 private static final String NULL_OBJECT_STRING = "<null>";
127
128 static OgnlCache cache = new OgnlCache();
129
130 private static final PrimitiveTypes primitiveTypes = new PrimitiveTypes();
131
132 private static final PrimitiveDefaults primitiveDefaults = new PrimitiveDefaults();
133
134 private static SecurityManager securityManager = System.getSecurityManager();
135
136 private static final EvaluationPool evaluationPool = new EvaluationPool();
137
138 private static final ObjectArrayPool objectArrayPool = new ObjectArrayPool();
139
140
141
142
143 private static OgnlExpressionCompiler compiler;
144
145
146
147
148 private static final PrimitiveWrapperClasses primitiveWrapperClasses = new PrimitiveWrapperClasses();
149
150
151
152
153 private static final NumericCasts numericCasts = new NumericCasts();
154
155
156
157
158
159 private static final NumericValues numericValues = new NumericValues();
160
161
162
163
164 private static final NumericLiterals numericLiterals = new NumericLiterals();
165
166 private static final NumericDefaults numericDefaults = new NumericDefaults();
167
168
169
170
171
172
173
174
175
176 public static void clearCache()
177 {
178 cache.clear();
179 }
180
181
182
183
184
185 public static boolean isJdk15()
186 {
187 return true;
188 }
189
190 public static String getNumericValueGetter( Class<?> type )
191 {
192 return numericValues.get( type );
193 }
194
195 public static Class<?> getPrimitiveWrapperClass( Class<?> primitiveClass )
196 {
197 return primitiveWrapperClasses.get( primitiveClass );
198 }
199
200 public static String getNumericCast( Class<? extends Number> type )
201 {
202 return numericCasts.get( type );
203 }
204
205 public static String getNumericLiteral( Class<? extends Number> type )
206 {
207 return numericLiterals.get( type );
208 }
209
210 public static void setCompiler( OgnlExpressionCompiler compiler )
211 {
212 OgnlRuntime.compiler = compiler;
213 }
214
215
216
217
218 public static OgnlExpressionCompiler getCompiler()
219 {
220 return getCompiler( null );
221 }
222
223 public static OgnlExpressionCompiler getCompiler( OgnlContext ognlContext )
224 {
225 if ( compiler == null )
226 {
227 try
228 {
229 OgnlRuntime.classForName( ognlContext, "javassist.ClassPool" );
230 compiler = new ExpressionCompiler();
231 }
232 catch ( ClassNotFoundException e )
233 {
234 throw new IllegalArgumentException(
235 "Javassist library is missing in classpath! Please add missed dependency!", e );
236 }
237 }
238 return compiler;
239 }
240
241 public static void compileExpression( OgnlContext context, Node expression, Object root )
242 throws Exception
243 {
244 getCompiler( context ).compileExpression( context, expression, root );
245 }
246
247
248
249
250
251 public static Class<?> getTargetClass( Object o )
252 {
253 return ( o == null ) ? null : ( ( o instanceof Class ) ? (Class<?>) o : o.getClass() );
254 }
255
256
257
258
259 public static String getBaseName( Object o )
260 {
261 return ( o == null ) ? null : getClassBaseName( o.getClass() );
262 }
263
264
265
266
267 public static String getClassBaseName( Class<?> clazz )
268 {
269 String className = clazz.getName();
270 return className.substring( className.lastIndexOf( '.' ) + 1 );
271 }
272
273 public static String getClassName( Object object, boolean fullyQualified )
274 {
275 if ( !( object instanceof Class ) )
276 {
277 object = object.getClass();
278 }
279
280 return getClassName( (Class<?>) object, fullyQualified );
281 }
282
283 public static String getClassName( Class<?> clazz, boolean fullyQualified )
284 {
285 return fullyQualified ? clazz.getName() : getClassBaseName( clazz );
286 }
287
288
289
290
291 public static String getPackageName( Object object )
292 {
293 return ( object == null ) ? null : getClassPackageName( object.getClass() );
294 }
295
296
297
298
299 public static String getClassPackageName( Class<?> clazz )
300 {
301 String className = clazz.getName();
302 int index = className.lastIndexOf( '.' );
303
304 return ( index < 0 ) ? null : className.substring( 0, index );
305 }
306
307
308
309
310 public static String getPointerString( int num )
311 {
312 String hex = Integer.toHexString( num ), pad;
313 Integer l = hex.length();
314
315
316 if ( ( pad = HEX_PADDING.get( l ) ) == null )
317 {
318 StringBuilder paddingStringBuilder = new StringBuilder();
319
320 for ( int i = hex.length(); i < HEX_LENGTH; i++ )
321 {
322 paddingStringBuilder.append( '0' );
323 }
324 pad = paddingStringBuilder.toString();
325 HEX_PADDING.put( l, pad );
326 }
327 return new StringBuilder().append( pad ).append( hex ).toString();
328 }
329
330
331
332
333
334 public static String getPointerString( Object object )
335 {
336 return getPointerString( ( object == null ) ? 0 : System.identityHashCode( object ) );
337 }
338
339
340
341
342
343
344 public static String getUniqueDescriptor( Object object, boolean fullyQualified )
345 {
346 StringBuilder stringBuilder = new StringBuilder();
347
348 if ( object != null )
349 {
350 if ( object instanceof Proxy )
351 {
352 Class<?> interfaceClass = object.getClass().getInterfaces()[0];
353
354 String className = getClassName( interfaceClass, fullyQualified );
355 stringBuilder.append( className ).append( '^' );
356 object = Proxy.getInvocationHandler( object );
357 }
358 String className = getClassName( object, fullyQualified );
359 String pointerString = getPointerString( object );
360 stringBuilder.append( className ).append( '@' ).append( pointerString );
361 }
362 else
363 {
364 stringBuilder.append( NULL_OBJECT_STRING );
365 }
366 return stringBuilder.toString();
367 }
368
369
370
371
372 public static String getUniqueDescriptor( Object object )
373 {
374 return getUniqueDescriptor( object, false );
375 }
376
377
378
379
380
381 public static <T> Object[] toArray( List<T> list )
382 {
383 Object[] array;
384 int size = list.size();
385
386 if ( size == 0 )
387 {
388 array = NoArguments;
389 }
390 else
391 {
392 array = getObjectArrayPool().create( size );
393 for ( int i = 0; i < size; i++ )
394 {
395 array[i] = list.get( i );
396 }
397 }
398 return array;
399 }
400
401
402
403
404 public static Class<?>[] getParameterTypes( Method method )
405 throws CacheException
406 {
407 return cache.getMethodParameterTypes( method );
408 }
409
410
411
412
413
414
415
416
417
418
419 public static Class<?>[] findParameterTypes( Class<?> type, Method method )
420 throws CacheException
421 {
422 if ( type == null || type.getGenericSuperclass() == null || !ParameterizedType.class.isInstance(
423 type.getGenericSuperclass() ) || method.getDeclaringClass().getTypeParameters() == null )
424 {
425 return getParameterTypes( method );
426 }
427
428 GenericMethodParameterTypeCacheEntry key = new GenericMethodParameterTypeCacheEntry( method, type );
429 return cache.getGenericMethodParameterTypes( key );
430 }
431
432
433
434
435
436
437
438 public static Class<?>[] getParameterTypes( Constructor<?> constructor )
439 throws CacheException
440 {
441 return cache.getParameterTypes( constructor );
442 }
443
444
445
446
447
448
449 public static SecurityManager getSecurityManager()
450 {
451 return securityManager;
452 }
453
454
455
456
457
458
459 public static void setSecurityManager( SecurityManager securityManager )
460 {
461 OgnlRuntime.securityManager = securityManager;
462 cache.setSecurityManager(securityManager);
463 }
464
465
466
467
468
469
470
471 public static Permission getPermission( Method method )
472 throws CacheException
473 {
474 PermissionCacheEntry key = new PermissionCacheEntry( method );
475 return cache.getInvokePermission( key );
476 }
477
478 public static Object invokeMethod( Object target, Method method, Object[] argsArray )
479 throws InvocationTargetException, IllegalAccessException, CacheException
480 {
481 Object result;
482
483 if ( securityManager != null )
484 {
485 if ( !cache.getMethodPerm( method ) )
486 {
487 throw new IllegalAccessException( "Method [" + method + "] cannot be accessed." );
488 }
489 }
490
491 MethodAccessEntryValue entry = cache.getMethodAccess( method );
492 if ( !entry.isAccessible() )
493 {
494
495 synchronized ( method )
496 {
497
498 if ( entry.isNotPublic() && !entry.isAccessible() )
499 {
500 method.setAccessible( true );
501 }
502
503 result = method.invoke( target, argsArray );
504
505 if ( !entry.isAccessible() )
506 {
507 method.setAccessible( false );
508 }
509 }
510 }
511 else
512 {
513 result = method.invoke( target, argsArray );
514 }
515
516 return result;
517 }
518
519
520
521
522
523
524
525
526
527 public static Class<?> getArgClass( Object arg )
528 {
529 if ( arg == null )
530 {
531 return null;
532 }
533 Class<?> clazz = arg.getClass();
534 if ( clazz == Boolean.class )
535 {
536 return Boolean.TYPE;
537 }
538 else if ( clazz.getSuperclass() == Number.class )
539 {
540 if ( clazz == Integer.class )
541 {
542 return Integer.TYPE;
543 }
544 if ( clazz == Double.class )
545 {
546 return Double.TYPE;
547 }
548 if ( clazz == Byte.class )
549 {
550 return Byte.TYPE;
551 }
552 if ( clazz == Long.class )
553 {
554 return Long.TYPE;
555 }
556 if ( clazz == Float.class )
557 {
558 return Float.TYPE;
559 }
560 if ( clazz == Short.class )
561 {
562 return Short.TYPE;
563 }
564 }
565 else if ( clazz == Character.class )
566 {
567 return Character.TYPE;
568 }
569 return clazz;
570 }
571
572
573
574
575
576
577 public static boolean isTypeCompatible( Object object, Class<?> clazz )
578 {
579 boolean result = true;
580
581 if ( object != null )
582 {
583 if ( clazz.isPrimitive() )
584 {
585 if ( getArgClass( object ) != clazz )
586 {
587 result = false;
588 }
589 }
590 else if ( !clazz.isInstance( object ) )
591 {
592 result = false;
593 }
594 }
595 return result;
596 }
597
598
599
600
601
602
603 public static boolean areArgsCompatible( Object[] args, Class<?>[] classes )
604 {
605 return areArgsCompatible( args, classes, null );
606 }
607
608 public static boolean areArgsCompatible( Object[] args, Class<?>[] classes, Method method )
609 {
610 boolean result = true;
611 boolean varArgs = method != null && method.isVarArgs();
612
613 if ( args.length != classes.length && !varArgs )
614 {
615 result = false;
616 }
617 else if ( varArgs )
618 {
619 for ( int index = 0; result && ( index < args.length ); ++index )
620 {
621 if ( index >= classes.length )
622 {
623 break;
624 }
625
626 result = isTypeCompatible( args[index], classes[index] );
627
628 if ( !result && classes[index].isArray() )
629 {
630 result = isTypeCompatible( args[index], classes[index].getComponentType() );
631 }
632 }
633 }
634 else
635 {
636 for ( int index = 0; result && ( index < args.length ); ++index )
637 {
638 result = isTypeCompatible( args[index], classes[index] );
639 }
640 }
641 return result;
642 }
643
644
645
646
647
648 public static boolean isMoreSpecific( Class<?>[] classes1, Class<?>[] classes2 )
649 {
650 for ( int index = 0; index < classes1.length; ++index )
651 {
652 Class<?> class1 = classes1[index], class2 = classes2[index];
653 if ( class1 != class2 )
654 {
655 if ( class1.isPrimitive() )
656 {
657 return true;
658 }
659 else if ( class1.isAssignableFrom( class2 ) )
660 {
661 return false;
662 }
663 else if ( class2.isAssignableFrom( class1 ) )
664 {
665 return true;
666 }
667 }
668 }
669
670
671 return false;
672 }
673
674
675
676
677
678
679 public static String getModifierString( int modifiers )
680 {
681 String modifierString;
682
683 if ( Modifier.isPublic( modifiers ) )
684 {
685 modifierString = "public";
686 }
687 else if ( Modifier.isProtected( modifiers ) )
688 {
689 modifierString = "protected";
690 }
691 else if ( Modifier.isPrivate( modifiers ) )
692 {
693 modifierString = "private";
694 }
695 else
696 {
697 modifierString = "";
698 }
699 if ( Modifier.isStatic( modifiers ) )
700 {
701 modifierString = "static " + modifierString;
702 }
703 if ( Modifier.isFinal( modifiers ) )
704 {
705 modifierString = "final " + modifierString;
706 }
707 if ( Modifier.isNative( modifiers ) )
708 {
709 modifierString = "native " + modifierString;
710 }
711 if ( Modifier.isSynchronized( modifiers ) )
712 {
713 modifierString = "synchronized " + modifierString;
714 }
715 if ( Modifier.isTransient( modifiers ) )
716 {
717 modifierString = "transient " + modifierString;
718 }
719 return modifierString;
720 }
721
722 public static Class<?> classForName( OgnlContext context, String className )
723 throws ClassNotFoundException
724 {
725 Class<?> result = primitiveTypes.get( className );
726
727 if ( result == null )
728 {
729 ClassResolver resolver;
730
731 if ( ( context == null ) || ( ( resolver = context.getClassResolver() ) == null ) )
732 {
733 resolver = OgnlContext.DEFAULT_CLASS_RESOLVER;
734 }
735 result = resolver.classForName( className, context );
736 }
737
738 if ( result == null )
739 {
740 throw new ClassNotFoundException( "Unable to resolve class: " + className );
741 }
742
743 return result;
744 }
745
746 public static boolean isInstance( OgnlContext context, Object value, String className )
747 throws OgnlException
748 {
749 try
750 {
751 Class<?> clazz = classForName( context, className );
752 return clazz.isInstance( value );
753 }
754 catch ( ClassNotFoundException e )
755 {
756 throw new OgnlException( "No such class: " + className, e );
757 }
758 }
759
760 public static Object getPrimitiveDefaultValue( Class<?> forClass )
761 {
762 return primitiveDefaults.get( forClass );
763 }
764
765 public static Object getNumericDefaultValue( Class<?> forClass )
766 {
767 return numericDefaults.get( forClass );
768 }
769
770 public static Object getConvertedType( OgnlContext context, Object target, Member member, String propertyName,
771 Object value, Class<?> type )
772 {
773 return context.getTypeConverter().convertValue( context, target, member, propertyName, value, type );
774 }
775
776 public static boolean getConvertedTypes( OgnlContext context, Object target, Member member, String propertyName,
777 Class<?>[] parameterTypes, Object[] args, Object[] newArgs )
778
779 {
780 boolean result = false;
781
782 if ( parameterTypes.length == args.length )
783 {
784 result = true;
785 for ( int i = 0; result && ( i <= parameterTypes.length - 1 ); i++ )
786 {
787 Object arg = args[i];
788 Class<?> type = parameterTypes[i];
789
790 if ( isTypeCompatible( arg, type ) )
791 {
792 newArgs[i] = arg;
793 }
794 else
795 {
796 Object convertedType = getConvertedType( context, target, member, propertyName, arg, type );
797
798 if ( convertedType == OgnlRuntime.NoConversionPossible )
799 {
800 result = false;
801 }
802 else
803 {
804 newArgs[i] = convertedType;
805 }
806 }
807 }
808 }
809 return result;
810 }
811
812 public static Method getConvertedMethodAndArgs( OgnlContext context, Object target, String propertyName,
813 List<Method> methods, Object[] args, Object[] newArgs )
814
815 {
816 Method convertedMethod = null;
817 TypeConverter typeConverter = context.getTypeConverter();
818
819 if ( ( typeConverter != null ) && ( methods != null ) )
820 {
821 int methodsSize = methods.size();
822 for ( int i = 0; ( convertedMethod == null ) && ( i < methodsSize ); i++ )
823 {
824 Method method = methods.get( i );
825 Class<?>[] parameterTypes =
826 findParameterTypes( target != null ? target.getClass() : null, method );
827
828 if ( getConvertedTypes( context, target, method, propertyName, parameterTypes, args, newArgs ) )
829 {
830 convertedMethod = method;
831 }
832 }
833 }
834 return convertedMethod;
835 }
836
837 public static Constructor<?> getConvertedConstructorAndArgs( OgnlContext context, Object target,
838 List<Constructor<?>> constructors, Object[] args,
839 Object[] newArgs )
840
841 {
842 Constructor<?> constructor = null;
843 TypeConverter typeConverter = context.getTypeConverter();
844
845 if ( ( typeConverter != null ) && ( constructors != null ) )
846 {
847 for ( int i = 0; ( constructor == null ) && ( i < constructors.size() ); i++ )
848 {
849 Constructor<?> ctor = constructors.get( i );
850 Class<?>[] parameterTypes = getParameterTypes( ctor );
851
852 if ( getConvertedTypes( context, target, ctor, null, parameterTypes, args, newArgs ) )
853 {
854 constructor = ctor;
855 }
856 }
857 }
858 return constructor;
859 }
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875 public static Method getAppropriateMethod( OgnlContext context, Object source, Object target, String propertyName,
876 List<Method> methods, Object[] args, Object[] actualArgs )
877
878 {
879 Method appropriateMethod = null;
880 Class<?>[] resultParameterTypes = null;
881
882 if ( methods != null )
883 {
884 for ( Method method : methods )
885 {
886 Class<?> typeClass = target != null ? target.getClass() : null;
887 if ( typeClass == null && source != null && Class.class.isInstance( source ) )
888 {
889 typeClass = (Class<?>) source;
890 }
891
892 Class<?>[] mParameterTypes = findParameterTypes( typeClass, method );
893
894 if ( areArgsCompatible( args, mParameterTypes, method ) &&
895 ( ( appropriateMethod == null ) || isMoreSpecific( mParameterTypes, resultParameterTypes ) ) )
896 {
897 appropriateMethod = method;
898 resultParameterTypes = mParameterTypes;
899 System.arraycopy( args, 0, actualArgs, 0, args.length );
900
901 for ( int i = 0; i < mParameterTypes.length; i++ )
902 {
903 Class<?> type = mParameterTypes[i];
904
905 if ( type.isPrimitive() && ( actualArgs[i] == null ) )
906 {
907 actualArgs[i] = getConvertedType( context, source, appropriateMethod, propertyName, null, type );
908 }
909 }
910 }
911 }
912 }
913
914 if ( appropriateMethod == null )
915 {
916 appropriateMethod = getConvertedMethodAndArgs( context, target, propertyName, methods, args, actualArgs );
917 }
918
919 return appropriateMethod;
920 }
921
922 public static Object callAppropriateMethod( OgnlContext context, Object source, Object target, String methodName,
923 String propertyName, List<Method> methods, Object[] args )
924 throws MethodFailedException
925 {
926 Throwable cause = null;
927 Object[] actualArgs = objectArrayPool.create( args.length );
928
929 try
930 {
931 Method method = getAppropriateMethod( context, source, target, propertyName, methods, args, actualArgs );
932
933 if ( ( method == null ) || !isMethodAccessible( context, source, method, propertyName ) )
934 {
935 StringBuilder buffer = new StringBuilder();
936 String className = "";
937
938 if ( target != null )
939 {
940 className = target.getClass().getName() + ".";
941 }
942
943 for ( int i = 0, ilast = args.length - 1; i <= ilast; i++ )
944 {
945 Object arg = args[i];
946
947 buffer.append( ( arg == null ) ? NULL_STRING : arg.getClass().getName() );
948 if ( i < ilast )
949 {
950 buffer.append( ", " );
951 }
952 }
953
954 throw new NoSuchMethodException( className + methodName + "(" + buffer + ")" );
955 }
956
957 Object[] convertedArgs = actualArgs;
958
959 if ( method.isVarArgs() )
960 {
961 Class<?>[] parmTypes = method.getParameterTypes();
962
963
964
965
966
967 for ( int i = 0; i < parmTypes.length; i++ )
968 {
969 if ( parmTypes[i].isArray() )
970 {
971 convertedArgs = new Object[i + 1];
972 System.arraycopy( actualArgs, 0, convertedArgs, 0, convertedArgs.length );
973
974 Object[] varArgs;
975
976
977
978 if ( actualArgs.length > i )
979 {
980 List<Object> varArgsList = new ArrayList<Object>();
981 for ( int j = i; j < actualArgs.length; j++ )
982 {
983 if ( actualArgs[j] != null )
984 {
985 varArgsList.add( actualArgs[j] );
986 }
987 }
988
989 varArgs = varArgsList.toArray();
990 }
991 else
992 {
993 varArgs = new Object[0];
994 }
995
996 convertedArgs[i] = varArgs;
997 break;
998 }
999 }
1000 }
1001
1002 return invokeMethod( target, method, convertedArgs );
1003
1004 }
1005 catch ( NoSuchMethodException e )
1006 {
1007 cause = e;
1008 }
1009 catch ( IllegalAccessException e )
1010 {
1011 cause = e;
1012 }
1013 catch ( InvocationTargetException e )
1014 {
1015 cause = e.getTargetException();
1016 }
1017 finally
1018 {
1019 objectArrayPool.recycle( actualArgs );
1020 }
1021
1022 throw new MethodFailedException( source, methodName, cause );
1023 }
1024
1025 public static Object callStaticMethod( OgnlContext context, String className, String methodName, Object[] args )
1026 throws OgnlException
1027 {
1028 try
1029 {
1030 Class<?> targetClass = classForName( context, className );
1031 if ( targetClass == null )
1032 {
1033 throw new ClassNotFoundException( "Unable to resolve class with name " + className );
1034 }
1035
1036 MethodAccessor methodAccessor = getMethodAccessor( targetClass );
1037
1038 return methodAccessor.callStaticMethod( context, targetClass, methodName, args );
1039 }
1040 catch ( ClassNotFoundException ex )
1041 {
1042 throw new MethodFailedException( className, methodName, ex );
1043 }
1044 }
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 public static Object callMethod( OgnlContext context, Object target, String methodName, Object[] args )
1057 throws OgnlException
1058 {
1059 if ( target == null )
1060 {
1061 throw new NullPointerException( "target is null for method " + methodName );
1062 }
1063
1064 return getMethodAccessor( target.getClass() ).callMethod( context, target, methodName, args );
1065 }
1066
1067 public static Object callConstructor( OgnlContext context, String className, Object[] args )
1068 throws OgnlException
1069 {
1070 Throwable cause = null;
1071 Object[] actualArgs = args;
1072
1073 try
1074 {
1075 Constructor<?> ctor = null;
1076 Class<?>[] ctorParameterTypes = null;
1077 Class<?> target = classForName( context, className );
1078 List<Constructor<?>> constructors = getConstructors( target );
1079
1080 for ( Constructor<?> constructor : constructors )
1081 {
1082 Class<?>[] cParameterTypes = getParameterTypes( constructor );
1083
1084 if ( areArgsCompatible( args, cParameterTypes ) && ( ctor == null || isMoreSpecific( cParameterTypes,
1085 ctorParameterTypes ) ) )
1086 {
1087 ctor = constructor;
1088 ctorParameterTypes = cParameterTypes;
1089 }
1090 }
1091 if ( ctor == null )
1092 {
1093 actualArgs = objectArrayPool.create( args.length );
1094 if ( ( ctor = getConvertedConstructorAndArgs( context, target, constructors, args, actualArgs ) )
1095 == null )
1096 {
1097 throw new NoSuchMethodException();
1098 }
1099 }
1100 if ( !context.getMemberAccess().isAccessible( context, target, ctor, null ) )
1101 {
1102 throw new IllegalAccessException( "access denied to " + target.getName() + "()" );
1103 }
1104 return ctor.newInstance( actualArgs );
1105 }
1106 catch ( ClassNotFoundException e )
1107 {
1108 cause = e;
1109 }
1110 catch ( NoSuchMethodException e )
1111 {
1112 cause = e;
1113 }
1114 catch ( IllegalAccessException e )
1115 {
1116 cause = e;
1117 }
1118 catch ( InvocationTargetException e )
1119 {
1120 cause = e.getTargetException();
1121 }
1122 catch ( InstantiationException e )
1123 {
1124 cause = e;
1125 }
1126 finally
1127 {
1128 if ( actualArgs != args )
1129 {
1130 objectArrayPool.recycle( actualArgs );
1131 }
1132 }
1133
1134 throw new MethodFailedException( className, "new", cause );
1135 }
1136
1137 public static Object getMethodValue( OgnlContext context, Object target, String propertyName )
1138 throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
1139 {
1140 return getMethodValue( context, target, propertyName, false );
1141 }
1142
1143
1144
1145
1146
1147 public static Object getMethodValue( OgnlContext context, Object target, String propertyName,
1148 boolean checkAccessAndExistence )
1149 throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
1150 {
1151 Object methodValue = null;
1152 Class<?> targetClass = target == null ? null : target.getClass();
1153 Method method = getGetMethod( context, targetClass, propertyName );
1154 if ( method == null )
1155 {
1156 method = getReadMethod( targetClass, propertyName, 0 );
1157 }
1158
1159 if ( checkAccessAndExistence )
1160 {
1161 if ( ( method == null ) || !context.getMemberAccess().isAccessible( context, target, method, propertyName ) )
1162 {
1163 methodValue = NotFound;
1164 }
1165 }
1166 if ( methodValue == null )
1167 {
1168 if ( method != null )
1169 {
1170 try
1171 {
1172 methodValue = invokeMethod( target, method, NoArguments );
1173 }
1174 catch ( InvocationTargetException ex )
1175 {
1176 throw new OgnlException( propertyName, ex.getTargetException() );
1177 }
1178 }
1179 else
1180 {
1181 throw new NoSuchMethodException( propertyName );
1182 }
1183 }
1184 return methodValue;
1185 }
1186
1187 public static boolean setMethodValue( OgnlContext context, Object target, String propertyName, Object value )
1188 throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
1189 {
1190 return setMethodValue( context, target, propertyName, value, false );
1191 }
1192
1193 public static boolean setMethodValue( OgnlContext context, Object target, String propertyName, Object value,
1194 boolean checkAccessAndExistence )
1195 throws OgnlException, IllegalAccessException, NoSuchMethodException, IntrospectionException
1196 {
1197 boolean result = true;
1198 Method method = getSetMethod( context, ( target == null ) ? null : target.getClass(), propertyName );
1199
1200 if ( checkAccessAndExistence )
1201 {
1202 if ( ( method == null ) || !context.getMemberAccess().isAccessible( context, target, method, propertyName ) )
1203 {
1204 result = false;
1205 }
1206 }
1207
1208 if ( result )
1209 {
1210 if ( method != null )
1211 {
1212 Object[] args = objectArrayPool.create( value );
1213
1214 try
1215 {
1216 callAppropriateMethod( context, target, target, method.getName(), propertyName,
1217 Collections.nCopies( 1, method ), args );
1218 }
1219 finally
1220 {
1221 objectArrayPool.recycle( args );
1222 }
1223 }
1224 else
1225 {
1226 result = false;
1227 }
1228 }
1229
1230 return result;
1231 }
1232
1233 public static List<Constructor<?>> getConstructors( Class<?> targetClass )
1234 {
1235 return cache.getConstructor( targetClass );
1236 }
1237
1238
1239
1240
1241
1242
1243 public static Map<String, List<Method>> getMethods( Class<?> targetClass, boolean staticMethods )
1244 {
1245 DeclaredMethodCacheEntry.MethodType type = staticMethods ?
1246 DeclaredMethodCacheEntry.MethodType.STATIC :
1247 DeclaredMethodCacheEntry.MethodType.NON_STATIC;
1248 DeclaredMethodCacheEntry key = new DeclaredMethodCacheEntry( targetClass, type );
1249 return cache.getMethod( key );
1250 }
1251
1252 public static List<Method> getMethods( Class<?> targetClass, String name, boolean staticMethods )
1253 {
1254 return getMethods( targetClass, staticMethods ).get( name );
1255 }
1256
1257 public static Map<String, Field> getFields( Class<?> targetClass )
1258 {
1259 return cache.getField( targetClass );
1260 }
1261
1262 public static Field getField( Class<?> inClass, String name )
1263 {
1264 Field field = getFields( inClass ).get( name );
1265
1266 if ( field == null )
1267 {
1268
1269 Class<?> superClass = inClass.getSuperclass();
1270 while ( superClass != null )
1271 {
1272 field = getFields( superClass ).get( name );
1273 if ( field != null )
1274 {
1275 return field;
1276 }
1277 superClass = superClass.getSuperclass();
1278 }
1279 }
1280 return field;
1281 }
1282
1283 public static Object getFieldValue( OgnlContext context, Object target, String propertyName )
1284 throws NoSuchFieldException
1285 {
1286 return getFieldValue( context, target, propertyName, false );
1287 }
1288
1289 public static Object getFieldValue( OgnlContext context, Object target, String propertyName,
1290 boolean checkAccessAndExistence )
1291 throws NoSuchFieldException
1292 {
1293 Object result = null;
1294 Class<?> targetClass = target == null ? null : target.getClass();
1295 Field field = getField( targetClass, propertyName );
1296
1297 if ( checkAccessAndExistence )
1298 {
1299 if ( ( field == null ) || !context.getMemberAccess().isAccessible( context, target, field, propertyName ) )
1300 {
1301 result = NotFound;
1302 }
1303 }
1304 if ( result == null )
1305 {
1306 if ( field == null )
1307 {
1308 throw new NoSuchFieldException( propertyName );
1309 }
1310 try
1311 {
1312 Object state;
1313
1314 if ( !Modifier.isStatic( field.getModifiers() ) )
1315 {
1316 state = context.getMemberAccess().setup( context, target, field, propertyName );
1317 result = field.get( target );
1318 context.getMemberAccess().restore( context, target, field, propertyName, state );
1319 }
1320 else
1321 {
1322 throw new NoSuchFieldException( propertyName );
1323 }
1324
1325 }
1326 catch ( IllegalAccessException ex )
1327 {
1328 throw new NoSuchFieldException( propertyName );
1329 }
1330 }
1331 return result;
1332 }
1333
1334 public static boolean setFieldValue( OgnlContext context, Object target, String propertyName, Object value )
1335 throws OgnlException
1336 {
1337 boolean result = false;
1338
1339 try
1340 {
1341 Class<?> targetClass = target == null ? null : target.getClass();
1342 Field field = getField( targetClass, propertyName );
1343 Object state;
1344
1345 if ( ( field != null ) && !Modifier.isStatic( field.getModifiers() ) )
1346 {
1347 state = context.getMemberAccess().setup( context, target, field, propertyName );
1348 try
1349 {
1350 if ( isTypeCompatible( value, field.getType() ) || (
1351 ( value = getConvertedType( context, target, field, propertyName, value, field.getType() ) ) != null ) )
1352 {
1353 field.set( target, value );
1354 result = true;
1355 }
1356 }
1357 finally
1358 {
1359 context.getMemberAccess().restore( context, target, field, propertyName, state );
1360 }
1361 }
1362 }
1363 catch ( IllegalAccessException ex )
1364 {
1365 throw new NoSuchPropertyException( target, propertyName, ex );
1366 }
1367 return result;
1368 }
1369
1370 public static boolean isFieldAccessible( OgnlContext context, Object target, Class<?> inClass, String propertyName )
1371 {
1372 return isFieldAccessible( context, target, getField( inClass, propertyName ), propertyName );
1373 }
1374
1375 public static boolean isFieldAccessible( OgnlContext context, Object target, Field field, String propertyName )
1376 {
1377 return context.getMemberAccess().isAccessible( context, target, field, propertyName );
1378 }
1379
1380 public static boolean hasField( OgnlContext context, Object target, Class<?> inClass, String propertyName )
1381 {
1382 Field field = getField( inClass, propertyName );
1383
1384 return ( field != null ) && isFieldAccessible( context, target, field, propertyName );
1385 }
1386
1387 public static Object getStaticField( OgnlContext context, String className, String fieldName )
1388 throws OgnlException
1389 {
1390 Exception cause;
1391 try
1392 {
1393 Class<?> clazz = classForName( context, className );
1394
1395 if ( clazz == null )
1396 {
1397 throw new OgnlException(
1398 "Unable to find class " + className + " when resolving field name of " + fieldName );
1399 }
1400
1401
1402
1403
1404
1405 if ( "class".equals( fieldName ) )
1406 {
1407 return clazz;
1408 }
1409 else if ( clazz.isEnum() )
1410 {
1411 return Enum.valueOf( (Class<? extends Enum>) clazz, fieldName );
1412 }
1413 else
1414 {
1415 Field field = clazz.getField( fieldName );
1416 if ( !Modifier.isStatic(field.getModifiers()) )
1417 {
1418 throw new OgnlException( "Field " + fieldName + " of class " + className + " is not static" );
1419 }
1420
1421 return field.get( null );
1422 }
1423 }
1424 catch ( ClassNotFoundException e )
1425 {
1426 cause = e;
1427 }
1428 catch ( NoSuchFieldException e )
1429 {
1430 cause = e;
1431 }
1432 catch ( SecurityException e )
1433 {
1434 cause = e;
1435 }
1436 catch ( IllegalAccessException e )
1437 {
1438 cause = e;
1439 }
1440
1441 throw new OgnlException( "Could not get static field " + fieldName + " from class " + className, cause );
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451 public static List<Method> getDeclaredMethods( Class<?> targetClass, String propertyName, boolean findSets )
1452 {
1453 String baseName = Character.toUpperCase( propertyName.charAt( 0 ) ) + propertyName.substring( 1 );
1454 List<Method> methods = new ArrayList<Method>();
1455 List<String> methodNames = new ArrayList<String>( 2 );
1456 if ( findSets )
1457 {
1458 methodNames.add( SET_PREFIX + baseName );
1459 }
1460 else
1461 {
1462 methodNames.add( IS_PREFIX + baseName );
1463 methodNames.add( GET_PREFIX + baseName );
1464 }
1465 for ( String methodName : methodNames )
1466 {
1467 DeclaredMethodCacheEntry key = new DeclaredMethodCacheEntry( targetClass );
1468 List<Method> methodList = cache.getMethod( key ).get( methodName );
1469 if ( methodList != null )
1470 {
1471 methods.addAll( methodList );
1472 }
1473 }
1474
1475 return methods;
1476 }
1477
1478
1479
1480
1481
1482
1483
1484
1485 public static boolean isMethodCallable( Method method )
1486 {
1487 return !( method.isSynthetic() || Modifier.isVolatile( method.getModifiers() ) );
1488
1489 }
1490
1491 public static Method getGetMethod( OgnlContext unused, Class<?> targetClass, String propertyName )
1492 throws IntrospectionException, OgnlException
1493 {
1494 Method result = null;
1495
1496 List<Method> methods = getDeclaredMethods( targetClass, propertyName, false
1497
1498 if ( methods != null )
1499 {
1500 for ( Method method : methods )
1501 {
1502 Class<?>[] mParameterTypes = findParameterTypes( targetClass, method );
1503
1504 if ( mParameterTypes.length == 0 )
1505 {
1506 result = method;
1507 break;
1508 }
1509 }
1510 }
1511
1512 return result;
1513 }
1514
1515 public static boolean isMethodAccessible( OgnlContext context, Object target, Method method, String propertyName )
1516 {
1517 return ( method != null ) && context.getMemberAccess().isAccessible( context, target, method, propertyName );
1518 }
1519
1520 public static boolean hasGetMethod( OgnlContext context, Object target, Class<?> targetClass, String propertyName )
1521 throws IntrospectionException, OgnlException
1522 {
1523 return isMethodAccessible( context, target, getGetMethod( context, targetClass, propertyName ), propertyName );
1524 }
1525
1526 public static Method getSetMethod( OgnlContext context, Class<?> targetClass, String propertyName )
1527 throws IntrospectionException, OgnlException
1528 {
1529 Method setMethod = null;
1530
1531 List<Method> methods = getDeclaredMethods( targetClass, propertyName, true
1532
1533 if ( methods != null )
1534 {
1535 for ( Method method : methods )
1536 {
1537 Class<?>[] mParameterTypes = findParameterTypes( targetClass, method );
1538
1539 if ( mParameterTypes.length == 1 )
1540 {
1541 setMethod = method;
1542 break;
1543 }
1544 }
1545 }
1546
1547 return setMethod;
1548 }
1549
1550 public static boolean hasSetMethod( OgnlContext context, Object target, Class<?> targetClass, String propertyName )
1551 throws IntrospectionException, OgnlException
1552 {
1553 return isMethodAccessible( context, target, getSetMethod( context, targetClass, propertyName ), propertyName );
1554 }
1555
1556 public static boolean hasGetProperty( OgnlContext context, Object target, Object oname )
1557 throws IntrospectionException, OgnlException
1558 {
1559 Class<?> targetClass = ( target == null ) ? null : target.getClass();
1560 String name = oname.toString();
1561
1562 return hasGetMethod( context, target, targetClass, name ) || hasField( context, target, targetClass, name );
1563 }
1564
1565 public static boolean hasSetProperty( OgnlContext context, Object target, Object oname )
1566 throws IntrospectionException, OgnlException
1567 {
1568 Class<?> targetClass = ( target == null ) ? null : target.getClass();
1569 String name = oname.toString();
1570
1571 return hasSetMethod( context, target, targetClass, name ) || hasField( context, target, targetClass, name );
1572 }
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582 public static Map<String, PropertyDescriptor> getPropertyDescriptors( Class<?> targetClass )
1583 throws IntrospectionException, OgnlException
1584 {
1585 return cache.getPropertyDescriptor( targetClass );
1586 }
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597 public static PropertyDescriptor getPropertyDescriptor( Class<?> targetClass, String propertyName )
1598 throws IntrospectionException, OgnlException
1599 {
1600 if ( targetClass == null )
1601 {
1602 return null;
1603 }
1604
1605 return getPropertyDescriptors( targetClass ).get( propertyName );
1606 }
1607
1608 public static PropertyDescriptor[] getPropertyDescriptorsArray( Class<?> targetClass )
1609 throws IntrospectionException, OgnlException
1610 {
1611 Collection<PropertyDescriptor> propertyDescriptors = getPropertyDescriptors( targetClass ).values();
1612 return propertyDescriptors.toArray( new PropertyDescriptor[propertyDescriptors.size()] );
1613 }
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624 public static PropertyDescriptor getPropertyDescriptorFromArray( Class<?> targetClass, String name )
1625 throws IntrospectionException, OgnlException
1626 {
1627 PropertyDescriptor result = null;
1628 PropertyDescriptor[] propertyDescriptors = getPropertyDescriptorsArray( targetClass );
1629
1630 for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
1631 {
1632 if ( result != null )
1633 {
1634 break;
1635 }
1636 if ( propertyDescriptor.getName().compareTo( name ) == 0 )
1637 {
1638 result = propertyDescriptor;
1639 }
1640 }
1641 return result;
1642 }
1643
1644 public static void setMethodAccessor( Class<?> clazz, MethodAccessor accessor )
1645 {
1646 cache.setMethodAccessor( clazz, accessor );
1647 }
1648
1649 public static MethodAccessor getMethodAccessor( Class<?> clazz )
1650 throws OgnlException
1651 {
1652 return cache.getMethodAccessor( clazz );
1653 }
1654
1655 public static void setPropertyAccessor( Class<?> clazz, PropertyAccessor accessor )
1656 {
1657 cache.setPropertyAccessor( clazz, accessor );
1658 }
1659
1660 public static PropertyAccessor getPropertyAccessor( Class<?> clazz )
1661 throws OgnlException
1662 {
1663 return cache.getPropertyAccessor( clazz );
1664 }
1665
1666 public static ElementsAccessor getElementsAccessor( Class<?> clazz )
1667 throws OgnlException
1668 {
1669 return cache.getElementsAccessor( clazz );
1670 }
1671
1672 public static void setElementsAccessor( Class<?> clazz, ElementsAccessor accessor )
1673 {
1674 cache.setElementsAccessor( clazz, accessor );
1675 }
1676
1677 public static NullHandler getNullHandler( Class<?> clazz )
1678 throws OgnlException
1679 {
1680 return cache.getNullHandler( clazz );
1681 }
1682
1683 public static void setNullHandler( Class<?> clazz, NullHandler handler )
1684 {
1685 cache.setNullHandler( clazz, handler );
1686 }
1687
1688 public static Object getProperty( OgnlContext context, Object source, Object name )
1689 throws OgnlException
1690 {
1691 PropertyAccessor accessor;
1692
1693 if ( source == null )
1694 {
1695 throw new OgnlException( "source is null for getProperty(null, \"" + name + "\")" );
1696 }
1697 if ( ( accessor = getPropertyAccessor( getTargetClass( source ) ) ) == null )
1698 {
1699 throw new OgnlException( "No property accessor for " + getTargetClass( source ).getName() );
1700 }
1701
1702 return accessor.getProperty( context, source, name );
1703 }
1704
1705 public static void setProperty( OgnlContext context, Object target, Object name, Object value )
1706 throws OgnlException
1707 {
1708 PropertyAccessor accessor;
1709
1710 if ( target == null )
1711 {
1712 throw new OgnlException( "target is null for setProperty(null, \"" + name + "\", " + value + ")" );
1713 }
1714 if ( ( accessor = getPropertyAccessor( getTargetClass( target ) ) ) == null )
1715 {
1716 throw new OgnlException( "No property accessor for " + getTargetClass( target ).getName() );
1717 }
1718
1719 accessor.setProperty( context, target, name, value );
1720 }
1721
1722
1723
1724
1725
1726
1727
1728
1729 public static int getIndexedPropertyType( OgnlContext context, Class<?> sourceClass, String name )
1730 throws OgnlException
1731 {
1732 int result = INDEXED_PROPERTY_NONE;
1733
1734 try
1735 {
1736 PropertyDescriptor propertyDescriptor = getPropertyDescriptor( sourceClass, name );
1737 if ( propertyDescriptor != null )
1738 {
1739 if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
1740 {
1741 result = INDEXED_PROPERTY_INT;
1742 }
1743 else
1744 {
1745 if ( propertyDescriptor instanceof ObjectIndexedPropertyDescriptor )
1746 {
1747 result = INDEXED_PROPERTY_OBJECT;
1748 }
1749 }
1750 }
1751 }
1752 catch ( Exception ex )
1753 {
1754 throw new OgnlException( "problem determining if '" + name + "' is an indexed property", ex );
1755 }
1756 return result;
1757 }
1758
1759 public static Object getIndexedProperty( OgnlContext context, Object source, String name, Object index )
1760 throws OgnlException
1761 {
1762 Object[] args = objectArrayPool.create( index );
1763
1764 try
1765 {
1766 PropertyDescriptor propertyDescriptor = getPropertyDescriptor( ( source == null ) ? null : source.getClass(), name );
1767 Method method;
1768
1769 if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
1770 {
1771 method = ( (IndexedPropertyDescriptor) propertyDescriptor ).getIndexedReadMethod();
1772 }
1773 else
1774 {
1775 if ( propertyDescriptor instanceof ObjectIndexedPropertyDescriptor )
1776 {
1777 method = ( (ObjectIndexedPropertyDescriptor) propertyDescriptor ).getIndexedReadMethod();
1778 }
1779 else
1780 {
1781 throw new OgnlException( "property '" + name + "' is not an indexed property" );
1782 }
1783 }
1784
1785 return callMethod( context, source, method.getName(), args );
1786
1787 }
1788 catch ( OgnlException ex )
1789 {
1790 throw ex;
1791 }
1792 catch ( Exception ex )
1793 {
1794 throw new OgnlException( "getting indexed property descriptor for '" + name + "'", ex );
1795 }
1796 finally
1797 {
1798 objectArrayPool.recycle( args );
1799 }
1800 }
1801
1802 public static void setIndexedProperty( OgnlContext context, Object source, String name, Object index, Object value )
1803 throws OgnlException
1804 {
1805 Object[] args = objectArrayPool.create( index, value );
1806
1807 try
1808 {
1809 PropertyDescriptor propertyDescriptor = getPropertyDescriptor( ( source == null ) ? null : source.getClass(), name );
1810 Method method;
1811
1812 if ( propertyDescriptor instanceof IndexedPropertyDescriptor )
1813 {
1814 method = ( (IndexedPropertyDescriptor) propertyDescriptor ).getIndexedWriteMethod();
1815 }
1816 else
1817 {
1818 if ( propertyDescriptor instanceof ObjectIndexedPropertyDescriptor )
1819 {
1820 method = ( (ObjectIndexedPropertyDescriptor) propertyDescriptor ).getIndexedWriteMethod();
1821 }
1822 else
1823 {
1824 throw new OgnlException( "property '" + name + "' is not an indexed property" );
1825 }
1826 }
1827
1828 callMethod( context, source, method.getName(), args );
1829
1830 }
1831 catch ( OgnlException ex )
1832 {
1833 throw ex;
1834 }
1835 catch ( Exception ex )
1836 {
1837 throw new OgnlException( "getting indexed property descriptor for '" + name + "'", ex );
1838 }
1839 finally
1840 {
1841 objectArrayPool.recycle( args );
1842 }
1843 }
1844
1845 public static EvaluationPool getEvaluationPool()
1846 {
1847 return evaluationPool;
1848 }
1849
1850 public static ObjectArrayPool getObjectArrayPool()
1851 {
1852 return objectArrayPool;
1853 }
1854
1855
1856
1857
1858
1859
1860
1861 public static void setClassCacheInspector( ClassCacheInspector inspector )
1862 {
1863 cache.setClassCacheInspector( inspector );
1864 }
1865
1866 public static Method getMethod( OgnlContext context, Class<?> target, String name, Node[] children,
1867 boolean includeStatic )
1868 throws Exception
1869 {
1870 Class<?>[] parms;
1871 if ( children != null && children.length > 0 )
1872 {
1873 parms = new Class[children.length];
1874
1875
1876 Class<?> currType = context.getCurrentType();
1877 Class<?> currAccessor = context.getCurrentAccessor();
1878 Object cast = context.get( ExpressionCompiler.PRE_CAST );
1879
1880 context.setCurrentObject( context.getRoot() );
1881 context.setCurrentType( context.getRoot() != null ? context.getRoot().getClass() : null );
1882 context.setCurrentAccessor( null );
1883 context.setPreviousType( null );
1884
1885 for ( int i = 0; i < children.length; i++ )
1886 {
1887 children[i].toGetSourceString( context, context.getRoot() );
1888 parms[i] = context.getCurrentType();
1889 }
1890
1891 context.put( ExpressionCompiler.PRE_CAST, cast );
1892
1893 context.setCurrentType( currType );
1894 context.setCurrentAccessor( currAccessor );
1895 context.setCurrentObject( target );
1896 }
1897 else
1898 {
1899 parms = new Class[0];
1900 }
1901
1902 List<Method> methods = OgnlRuntime.getMethods( target, name, includeStatic );
1903 if ( methods == null )
1904 {
1905 return null;
1906 }
1907
1908 for ( Method method : methods )
1909 {
1910 boolean varArgs = method.isVarArgs();
1911
1912 if ( parms.length != method.getParameterTypes().length && !varArgs )
1913 {
1914 continue;
1915 }
1916
1917 Class<?>[] methodParameterTypes = method.getParameterTypes();
1918 boolean matched = true;
1919 for ( int i = 0; i < methodParameterTypes.length; i++ )
1920 {
1921 Class<?> methodParameterType = methodParameterTypes[i];
1922 if ( varArgs && methodParameterType.isArray() )
1923 {
1924 continue;
1925 }
1926
1927 Class<?> parm = parms[i];
1928 if ( parm == null )
1929 {
1930 matched = false;
1931 break;
1932 }
1933
1934 if ( parm == methodParameterType || methodParameterType.isPrimitive() && Character.TYPE != methodParameterType && Byte.TYPE != methodParameterType
1935 && Number.class.isAssignableFrom(parm)
1936 && OgnlRuntime.getPrimitiveWrapperClass(parm) == methodParameterType)
1937 {
1938 continue;
1939 }
1940
1941 matched = false;
1942 break;
1943 }
1944
1945 if ( matched )
1946 {
1947 return method;
1948 }
1949 }
1950
1951 return null;
1952 }
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964 public static Method getReadMethod( Class<?> target, String name )
1965 {
1966 return getReadMethod( target, name, -1 );
1967 }
1968
1969 public static Method getReadMethod( Class<?> target, String name, int numParms )
1970 {
1971 try
1972 {
1973 name = name.replaceAll( "\"", "" ).toLowerCase();
1974
1975 BeanInfo info = Introspector.getBeanInfo( target );
1976 MethodDescriptor[] methodDescriptors = info.getMethodDescriptors();
1977
1978
1979
1980 Method method = null;
1981
1982 for ( MethodDescriptor methodDescriptor : methodDescriptors )
1983 {
1984 if ( !isMethodCallable( methodDescriptor.getMethod() ) )
1985 {
1986 continue;
1987 }
1988
1989 String methodName = methodDescriptor.getName();
1990 String lowerMethodName = methodName.toLowerCase();
1991 int methodParamLen = methodDescriptor.getMethod().getParameterTypes().length;
1992
1993 if ( ( methodName.equalsIgnoreCase( name ) || lowerMethodName.equals( "get" + name )
1994 || lowerMethodName.equals( "has" + name ) || lowerMethodName.equals( "is" + name ) )
1995 && !methodName.startsWith( "set" ) )
1996 {
1997 if ( numParms > 0 && methodParamLen == numParms )
1998 {
1999 return methodDescriptor.getMethod();
2000 }
2001 else if ( numParms < 0 )
2002 {
2003 if ( methodName.equals( name ) )
2004 {
2005 return methodDescriptor.getMethod();
2006 }
2007 else if ( method == null || ( method.getParameterTypes().length > methodParamLen ) )
2008 {
2009 method = methodDescriptor.getMethod();
2010 }
2011 }
2012 }
2013 }
2014
2015 if ( method != null )
2016 {
2017 return method;
2018 }
2019
2020 for ( MethodDescriptor methodDescriptor : methodDescriptors )
2021 {
2022 if ( !isMethodCallable( methodDescriptor.getMethod() ) )
2023 {
2024 continue;
2025 }
2026
2027 if ( methodDescriptor.getName().toLowerCase().endsWith( name ) && !methodDescriptor.getName().startsWith( "set" )
2028 && methodDescriptor.getMethod().getReturnType() != Void.TYPE )
2029 {
2030
2031 if ( numParms > 0 && methodDescriptor.getMethod().getParameterTypes().length == numParms )
2032 {
2033 return methodDescriptor.getMethod();
2034 }
2035 else if ( numParms < 0 )
2036 {
2037 if ( ( method != null
2038 && method.getParameterTypes().length > methodDescriptor.getMethod().getParameterTypes().length )
2039 || method == null )
2040 {
2041 method = methodDescriptor.getMethod();
2042 }
2043 }
2044 }
2045 }
2046
2047 if ( method != null )
2048 {
2049 return method;
2050 }
2051
2052
2053
2054 if ( !name.startsWith( "get" ) )
2055 {
2056 return OgnlRuntime.getReadMethod( target, "get" + name, numParms );
2057 }
2058
2059 }
2060 catch ( Throwable t )
2061 {
2062 throw OgnlOps.castToRuntime( t );
2063 }
2064
2065 return null;
2066 }
2067
2068 public static Method getWriteMethod( Class<?> target, String name )
2069 {
2070 return getWriteMethod( target, name, -1 );
2071 }
2072
2073 public static Method getWriteMethod( Class<?> target, String name, int numParms )
2074 {
2075 try
2076 {
2077 name = name.replaceAll( "\"", "" );
2078
2079 BeanInfo info = Introspector.getBeanInfo( target );
2080 MethodDescriptor[] methods = info.getMethodDescriptors();
2081
2082 for ( MethodDescriptor method : methods )
2083 {
2084 if ( !isMethodCallable( method.getMethod() ) )
2085 {
2086 continue;
2087 }
2088
2089 if ( ( method.getName().equalsIgnoreCase( name ) || method.getName().toLowerCase().equals(
2090 name.toLowerCase() ) || method.getName().toLowerCase().equals( "set" + name.toLowerCase() ) )
2091 && !method.getName().startsWith( "get" ) )
2092 {
2093
2094 if ( numParms > 0 && method.getMethod().getParameterTypes().length == numParms )
2095 {
2096 return method.getMethod();
2097 }
2098 else if ( numParms < 0 )
2099 {
2100 return method.getMethod();
2101 }
2102 }
2103 }
2104
2105
2106
2107 Method[] cmethods = target.getClass().getMethods();
2108 for ( Method cmethod : cmethods )
2109 {
2110 if ( !isMethodCallable( cmethod ) )
2111 {
2112 continue;
2113 }
2114
2115 if ( ( cmethod.getName().equalsIgnoreCase( name ) || cmethod.getName().toLowerCase().equals(
2116 name.toLowerCase() ) || cmethod.getName().toLowerCase().equals( "set" + name.toLowerCase() ) )
2117 && !cmethod.getName().startsWith( "get" ) )
2118 {
2119
2120 if ( numParms > 0 && cmethod.getParameterTypes().length == numParms )
2121 {
2122 return cmethod;
2123 }
2124 else if ( numParms < 0 )
2125 {
2126 return cmethod;
2127 }
2128 }
2129 }
2130
2131
2132
2133 if ( !name.startsWith( "set" ) )
2134 {
2135 return OgnlRuntime.getReadMethod( target, "set" + name, numParms );
2136 }
2137
2138 }
2139 catch ( Throwable t )
2140 {
2141 throw OgnlOps.castToRuntime( t );
2142 }
2143
2144 return null;
2145 }
2146
2147 public static PropertyDescriptor getProperty( Class<?> target, String name )
2148 {
2149 try
2150 {
2151 BeanInfo info = Introspector.getBeanInfo( target );
2152
2153 PropertyDescriptor[] propertyDescriptors = info.getPropertyDescriptors();
2154
2155 for ( PropertyDescriptor propertyDescriptor : propertyDescriptors )
2156 {
2157
2158 String propertyDescriptorName = propertyDescriptor.getName();
2159 if ( propertyDescriptorName.equalsIgnoreCase( name ) || propertyDescriptorName.toLowerCase().equals( name.toLowerCase() )
2160 || propertyDescriptorName.toLowerCase().endsWith( name.toLowerCase() ) )
2161 {
2162 return propertyDescriptor;
2163 }
2164 }
2165
2166 }
2167 catch ( Throwable t )
2168 {
2169 throw OgnlOps.castToRuntime( t );
2170 }
2171
2172 return null;
2173 }
2174
2175 public static boolean isBoolean( String expression )
2176 {
2177 return expression != null && ( "true".equals( expression ) || "false".equals( expression )
2178 || "!true".equals( expression ) || "!false".equals( expression ) || "(true)".equals( expression )
2179 || "!(true)".equals( expression ) || "(false)".equals( expression ) || "!(false)".equals( expression )
2180 || expression.startsWith( "org.apache.commons.ognl.OgnlOps" ) );
2181 }
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196 public static boolean shouldConvertNumericTypes( OgnlContext context )
2197 {
2198 Class<?> currentType = context.getCurrentType();
2199 Class<?> previousType = context.getPreviousType();
2200 return currentType == null || previousType == null
2201 || !( currentType == previousType && currentType.isPrimitive() && previousType.isPrimitive() )
2202 && !currentType.isArray() && !previousType.isArray();
2203 }
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216 public static String getChildSource( OgnlContext context, Object target, Node child )
2217 throws OgnlException
2218 {
2219 return getChildSource( context, target, child, false );
2220 }
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234 public static String getChildSource( OgnlContext context, Object target, Node child, boolean forceConversion )
2235 throws OgnlException
2236 {
2237 String pre = (String) context.get( "_currentChain" );
2238 if ( pre == null )
2239 {
2240 pre = "";
2241 }
2242
2243 try
2244 {
2245 child.getValue( context, target );
2246 }
2247 catch ( NullPointerException e )
2248 {
2249
2250 }
2251 catch ( ArithmeticException e )
2252 {
2253 context.setCurrentType( int.class );
2254 return "0";
2255 }
2256 catch ( Throwable t )
2257 {
2258 throw OgnlOps.castToRuntime( t );
2259 }
2260
2261 String source;
2262
2263 try
2264 {
2265 source = child.toGetSourceString( context, target );
2266 }
2267 catch ( Throwable t )
2268 {
2269 throw OgnlOps.castToRuntime( t );
2270 }
2271
2272
2273
2274 if ( !ASTConst.class.isInstance( child ) && ( target == null || context.getRoot() != target ) )
2275 {
2276 source = pre + source;
2277 }
2278
2279 if ( context.getRoot() != null )
2280 {
2281 source = ExpressionCompiler.getRootExpression( child, context.getRoot(), context ) + source;
2282 context.setCurrentAccessor( context.getRoot().getClass() );
2283 }
2284
2285 if ( ASTChain.class.isInstance( child ) )
2286 {
2287 String cast = (String) context.remove( ExpressionCompiler.PRE_CAST );
2288 if ( cast == null )
2289 {
2290 cast = "";
2291 }
2292
2293 source = cast + source;
2294 }
2295
2296 if ( source == null || source.trim().length() < 1 )
2297 {
2298 source = "null";
2299 }
2300
2301 return source;
2302 }
2303 }