Coverage Report - org.apache.commons.ognl.ObjectPropertyAccessor
 
Classes in this File Line Coverage Branch Coverage Complexity
ObjectPropertyAccessor
59%
61/103
59%
31/52
6.818
 
 1  
 package org.apache.commons.ognl;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one
 5  
  * or more contributor license agreements.  See the NOTICE file
 6  
  * distributed with this work for additional information
 7  
  * regarding copyright ownership.  The ASF licenses this file
 8  
  * to you under the Apache License, Version 2.0 (the
 9  
  * "License"); you may not use this file except in compliance
 10  
  * with the License.  You may obtain a copy of the License at
 11  
  *
 12  
  *   http://www.apache.org/licenses/LICENSE-2.0
 13  
  *
 14  
  * Unless required by applicable law or agreed to in writing,
 15  
  * software distributed under the License is distributed on an
 16  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 17  
  * KIND, either express or implied.  See the License for the
 18  
  * specific language governing permissions and limitations
 19  
  * under the License.
 20  
  */
 21  
 
 22  
 import org.apache.commons.ognl.enhance.ExpressionCompiler;
 23  
 import org.apache.commons.ognl.enhance.OgnlExpressionCompiler;
 24  
 import org.apache.commons.ognl.enhance.UnsupportedCompilationException;
 25  
 
 26  
 import java.beans.IntrospectionException;
 27  
 import java.lang.reflect.Field;
 28  
 import java.lang.reflect.Method;
 29  
 import java.util.Map;
 30  
 
 31  
 /**
 32  
  * Implementation of PropertyAccessor that uses reflection on the target object's class to find a field or a pair of
 33  
  * set/get methods with the given property name.
 34  
  * 
 35  
  * @author Luke Blanshard (blanshlu@netscape.net)
 36  
  * @author Drew Davidson (drew@ognl.org)
 37  
  */
 38  31
 public class ObjectPropertyAccessor
 39  
     implements PropertyAccessor
 40  
 {
 41  
 
 42  
     /**
 43  
      * Returns OgnlRuntime.NotFound if the property does not exist.
 44  
      */
 45  
     public Object getPossibleProperty( Map<String, Object> context, Object target, String name )
 46  
         throws OgnlException
 47  
     {
 48  
         Object result;
 49  1273
         OgnlContext ognlContext = (OgnlContext) context;
 50  
 
 51  
         try
 52  
         {
 53  1273
             result = OgnlRuntime.getMethodValue( ognlContext, target, name, true );
 54  1273
             if ( result == OgnlRuntime.NotFound )
 55  
             {
 56  114
                 result = OgnlRuntime.getFieldValue( ognlContext, target, name, true );
 57  
             }
 58  
         }
 59  0
         catch ( IntrospectionException ex )
 60  
         {
 61  0
             throw new OgnlException( name, ex );
 62  
         }
 63  0
         catch ( OgnlException ex )
 64  
         {
 65  0
             throw ex;
 66  
         }
 67  0
         catch ( Exception ex )
 68  
         {
 69  0
             throw new OgnlException( name, ex );
 70  1273
         }
 71  
 
 72  1273
         return result;
 73  
     }
 74  
 
 75  
     /**
 76  
      * Returns OgnlRuntime.NotFound if the property does not exist.
 77  
      */
 78  
     public Object setPossibleProperty( Map<String, Object> context, Object target, String name, Object value )
 79  
         throws OgnlException
 80  
     {
 81  16
         Object result = null;
 82  16
         OgnlContext ognlContext = (OgnlContext) context;
 83  
 
 84  
         try
 85  
         {
 86  16
             if ( !OgnlRuntime.setMethodValue( ognlContext, target, name, value, true ) )
 87  
             {
 88  5
                 result = OgnlRuntime.setFieldValue( ognlContext, target, name, value ) ? null : OgnlRuntime.NotFound;
 89  
             }
 90  
 
 91  15
             if ( result == OgnlRuntime.NotFound )
 92  
             {
 93  0
                 Method m = OgnlRuntime.getWriteMethod( target.getClass(), name );
 94  0
                 if ( m != null )
 95  
                 {
 96  0
                     result = m.invoke( target, new Object[] { value } );
 97  
                 }
 98  
             }
 99  
         }
 100  0
         catch ( IntrospectionException ex )
 101  
         {
 102  0
             throw new OgnlException( name, ex );
 103  
         }
 104  1
         catch ( OgnlException ex )
 105  
         {
 106  1
             throw ex;
 107  
         }
 108  0
         catch ( Exception ex )
 109  
         {
 110  0
             throw new OgnlException( name, ex );
 111  15
         }
 112  
 
 113  15
         return result;
 114  
     }
 115  
 
 116  
     public boolean hasGetProperty( OgnlContext context, Object target, Object oname )
 117  
         throws OgnlException
 118  
     {
 119  
         try
 120  
         {
 121  0
             return OgnlRuntime.hasGetProperty( context, target, oname );
 122  
         }
 123  0
         catch ( IntrospectionException ex )
 124  
         {
 125  0
             throw new OgnlException( "checking if " + target + " has gettable property " + oname, ex );
 126  
         }
 127  
     }
 128  
 
 129  
     public boolean hasGetProperty( Map<String, Object> context, Object target, Object oname )
 130  
         throws OgnlException
 131  
     {
 132  0
         return hasGetProperty( (OgnlContext) context, target, oname );
 133  
     }
 134  
 
 135  
     public boolean hasSetProperty( OgnlContext context, Object target, Object oname )
 136  
         throws OgnlException
 137  
     {
 138  
         try
 139  
         {
 140  0
             return OgnlRuntime.hasSetProperty( context, target, oname );
 141  
         }
 142  0
         catch ( IntrospectionException ex )
 143  
         {
 144  0
             throw new OgnlException( "checking if " + target + " has settable property " + oname, ex );
 145  
         }
 146  
     }
 147  
 
 148  
     public boolean hasSetProperty( Map<String, Object> context, Object target, Object oname )
 149  
         throws OgnlException
 150  
     {
 151  0
         return hasSetProperty( (OgnlContext) context, target, oname );
 152  
     }
 153  
 
 154  
     public Object getProperty( Map<String, Object> context, Object target, Object oname )
 155  
         throws OgnlException
 156  
     {
 157  1273
         String name = oname.toString();
 158  
 
 159  1273
         Object result = getPossibleProperty( context, target, name );
 160  
 
 161  1273
         if ( result == OgnlRuntime.NotFound )
 162  
         {
 163  101
             throw new NoSuchPropertyException( target, name );
 164  
         }
 165  
 
 166  1172
         return result;
 167  
     }
 168  
 
 169  
     public void setProperty( Map<String, Object> context, Object target, Object oname, Object value )
 170  
         throws OgnlException
 171  
     {
 172  16
         String name = oname.toString();
 173  
 
 174  16
         Object result = setPossibleProperty( context, target, name, value );
 175  
 
 176  15
         if ( result == OgnlRuntime.NotFound )
 177  
         {
 178  0
             throw new NoSuchPropertyException( target, name );
 179  
         }
 180  15
     }
 181  
 
 182  
     public Class<?> getPropertyClass( OgnlContext context, Object target, Object index )
 183  
     {
 184  
         try
 185  
         {
 186  0
             Method m = OgnlRuntime.getReadMethod( target.getClass(), index.toString() );
 187  
 
 188  0
             if ( m == null )
 189  
             {
 190  
 
 191  0
                 if ( String.class.isAssignableFrom( index.getClass() ) && !target.getClass().isArray() )
 192  
                 {
 193  0
                     String key = ( (String) index ).replaceAll( "\"", "" );
 194  
                     try
 195  
                     {
 196  0
                         Field f = target.getClass().getField( key );
 197  0
                         if ( f != null )
 198  
                         {
 199  
 
 200  0
                             return f.getType();
 201  
                         }
 202  
                     }
 203  0
                     catch ( NoSuchFieldException e )
 204  
                     {
 205  0
                         return null;
 206  0
                     }
 207  
                 }
 208  
 
 209  0
                 return null;
 210  
             }
 211  
 
 212  0
             return m.getReturnType();
 213  
 
 214  
         }
 215  0
         catch ( Throwable t )
 216  
         {
 217  0
             throw OgnlOps.castToRuntime( t );
 218  
         }
 219  
     }
 220  
 
 221  
     public String getSourceAccessor( OgnlContext context, Object target, Object index )
 222  
     {
 223  
         try
 224  
         {
 225  
 
 226  112
             String methodName = index.toString().replaceAll( "\"", "" );
 227  112
             Method m = OgnlRuntime.getReadMethod( target.getClass(), methodName );
 228  
 
 229  
             // try last ditch effort of checking if they were trying to do reflection via a return method value
 230  
 
 231  112
             if ( m == null && context.getCurrentObject() != null )
 232  
             {
 233  7
                 m =
 234  
                     OgnlRuntime.getReadMethod( target.getClass(),
 235  
                                                context.getCurrentObject().toString().replaceAll( "\"", "" ) );
 236  
             }
 237  
             // System.out.println("tried to get read method from target: " + target.getClass() + " with methodName:" +
 238  
             // methodName + " result: " + m);
 239  
             // try to get field if no method could be found
 240  
 
 241  112
             if ( m == null )
 242  
             {
 243  
                 try
 244  
                 {
 245  6
                     if ( String.class.isAssignableFrom( index.getClass() ) && !target.getClass().isArray() )
 246  
                     {
 247  6
                         Field f = target.getClass().getField( methodName );
 248  
 
 249  6
                         if ( f != null )
 250  
                         {
 251  6
                             context.setCurrentType( f.getType() );
 252  6
                             context.setCurrentAccessor( f.getDeclaringClass() );
 253  
 
 254  6
                             return "." + f.getName();
 255  
                         }
 256  
                     }
 257  
                 }
 258  0
                 catch ( NoSuchFieldException e )
 259  
                 {
 260  
                     // ignore
 261  0
                 }
 262  
 
 263  0
                 return "";
 264  
             }
 265  
 
 266  106
             context.setCurrentType( m.getReturnType() );
 267  106
             final OgnlExpressionCompiler compiler = OgnlRuntime.getCompiler( context );
 268  106
             context.setCurrentAccessor( compiler.getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );
 269  
 
 270  106
             return "." + m.getName() + "()";
 271  
 
 272  
         }
 273  0
         catch ( Throwable t )
 274  
         {
 275  0
             throw OgnlOps.castToRuntime( t );
 276  
         }
 277  
     }
 278  
 
 279  
     public String getSourceSetter( OgnlContext context, Object target, Object index )
 280  
     {
 281  
         try
 282  
         {
 283  
 
 284  82
             String methodName = index.toString().replaceAll( "\"", "" );
 285  82
             Method m = OgnlRuntime.getWriteMethod( target.getClass(), methodName );
 286  
 
 287  82
             if ( m == null && context.getCurrentObject() != null && context.getCurrentObject().toString() != null )
 288  
             {
 289  28
                 m =
 290  
                     OgnlRuntime.getWriteMethod( target.getClass(),
 291  
                                                 context.getCurrentObject().toString().replaceAll( "\"", "" ) );
 292  
             }
 293  
 
 294  82
             if ( m == null || m.getParameterTypes() == null || m.getParameterTypes().length <= 0 )
 295  
             {
 296  36
                 throw new UnsupportedCompilationException( "Unable to determine setting expression on "
 297  
                     + context.getCurrentObject() + " with index of " + index );
 298  
             }
 299  
 
 300  46
             Class<?> parm = m.getParameterTypes()[0];
 301  
             String conversion;
 302  
 
 303  46
             if ( m.getParameterTypes().length > 1 )
 304  
             {
 305  0
                 throw new UnsupportedCompilationException(
 306  
                     "Object property accessors can only support single parameter setters." );
 307  
             }
 308  
 
 309  46
             final OgnlExpressionCompiler compiler = OgnlRuntime.getCompiler( context );
 310  46
             if ( parm.isPrimitive() )
 311  
             {
 312  23
                 Class<?> wrapClass = OgnlRuntime.getPrimitiveWrapperClass( parm );
 313  23
                 conversion = compiler.createLocalReference( context, "((" + wrapClass.getName()
 314  
                     + ")org.apache.commons.ognl.OgnlOps#convertValue($3," + wrapClass.getName() + ".class, true))."
 315  
                     + OgnlRuntime.getNumericValueGetter( wrapClass ), parm );
 316  
 
 317  23
             }
 318  23
             else if ( parm.isArray() )
 319  
             {
 320  3
                 conversion = compiler.createLocalReference( context, "(" + ExpressionCompiler.getCastString( parm )
 321  
                     + ")org.apache.commons.ognl.OgnlOps#toArray($3," + parm.getComponentType().getName() + ".class)",
 322  
                                                             parm );
 323  
 
 324  
             }
 325  
             else
 326  
             {
 327  20
                 conversion = compiler.createLocalReference( context, "(" + parm.getName()
 328  
                     + ")org.apache.commons.ognl.OgnlOps#convertValue($3," + parm.getName() + ".class)", parm );
 329  
             }
 330  
 
 331  46
             context.setCurrentType( m.getReturnType() );
 332  46
             context.setCurrentAccessor(
 333  
                 compiler.getSuperOrInterfaceClass( m, m.getDeclaringClass() ) );
 334  
 
 335  46
             return "." + m.getName() + "(" + conversion + ")";
 336  
 
 337  
         }
 338  36
         catch ( Throwable t )
 339  
         {
 340  36
             throw OgnlOps.castToRuntime( t );
 341  
         }
 342  
     }
 343  
 }