Coverage Report - org.apache.commons.ognl.ASTCtor
 
Classes in this File Line Coverage Branch Coverage Complexity
ASTCtor
90%
109/120
76%
67/88
6.3
 
 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  
 
 24  
 import java.lang.reflect.Array;
 25  
 import java.lang.reflect.Constructor;
 26  
 import java.util.List;
 27  
 
 28  
 /**
 29  
  * $Id: ASTCtor.java 1194869 2011-10-29 11:10:16Z mcucchiara $
 30  
  * @author Luke Blanshard (blanshlu@netscape.net)
 31  
  * @author Drew Davidson (drew@ognl.org)
 32  
  */
 33  
 public class ASTCtor
 34  
     extends SimpleNode
 35  
 {
 36  
 
 37  
     private String className;
 38  
 
 39  
     private boolean isArray;
 40  
 
 41  
     public ASTCtor( int id )
 42  
     {
 43  96
         super( id );
 44  96
     }
 45  
 
 46  
     public ASTCtor( OgnlParser p, int id )
 47  
     {
 48  0
         super( p, id );
 49  0
     }
 50  
 
 51  
     /** Called from parser action. */
 52  
     void setClassName( String className )
 53  
     {
 54  96
         this.className = className;
 55  96
     }
 56  
 
 57  
     /**
 58  
      * Get the class name for this constructor.
 59  
      *
 60  
      * @return the class name.
 61  
      * @since 4.0
 62  
      */
 63  
     String getClassName()
 64  
     {
 65  0
         return className;
 66  
     }
 67  
 
 68  
 
 69  
     void setArray( boolean value )
 70  
     {
 71  53
         isArray = value;
 72  53
     }
 73  
 
 74  
     public boolean isArray()
 75  
     {
 76  20
         return isArray;
 77  
     }
 78  
 
 79  
     protected Object getValueBody( OgnlContext context, Object source )
 80  
         throws OgnlException
 81  
     {
 82  111
         Object result, root = context.getRoot();
 83  111
         int count = jjtGetNumChildren();
 84  111
         Object[] args = OgnlRuntime.getObjectArrayPool().create( count );
 85  
 
 86  
         try
 87  
         {
 88  254
             for ( int i = 0; i < count; ++i )
 89  
             {
 90  143
                 args[i] = children[i].getValue( context, root );
 91  
             }
 92  111
             if ( isArray )
 93  
             {
 94  33
                 if ( args.length == 1 )
 95  
                 {
 96  
                     try
 97  
                     {
 98  33
                         Class componentClass = OgnlRuntime.classForName( context, className );
 99  33
                         List sourceList = null;
 100  
                         int size;
 101  
 
 102  33
                         if ( args[0] instanceof List )
 103  
                         {
 104  20
                             sourceList = (List) args[0];
 105  20
                             size = sourceList.size();
 106  
                         }
 107  
                         else
 108  
                         {
 109  13
                             size = (int) OgnlOps.longValue( args[0] );
 110  
                         }
 111  33
                         result = Array.newInstance( componentClass, size );
 112  33
                         if ( sourceList != null )
 113  
                         {
 114  20
                             TypeConverter converter = context.getTypeConverter();
 115  
 
 116  62
                             for ( int i = 0, icount = sourceList.size(); i < icount; i++ )
 117  
                             {
 118  42
                                 Object o = sourceList.get( i );
 119  
 
 120  42
                                 if ( ( o == null ) || componentClass.isInstance( o ) )
 121  
                                 {
 122  17
                                     Array.set( result, i, o );
 123  
                                 }
 124  
                                 else
 125  
                                 {
 126  25
                                     Array.set( result, i,
 127  
                                                converter.convertValue( context, null, null, null, o, componentClass ) );
 128  
                                 }
 129  
                             }
 130  
                         }
 131  
                     }
 132  0
                     catch ( ClassNotFoundException ex )
 133  
                     {
 134  0
                         throw new OgnlException( "array component class '" + className + "' not found", ex );
 135  33
                     }
 136  
                 }
 137  
                 else
 138  
                 {
 139  0
                     throw new OgnlException( "only expect array size or fixed initializer list" );
 140  
                 }
 141  
             }
 142  
             else
 143  
             {
 144  78
                 result = OgnlRuntime.callConstructor( context, className, args );
 145  
             }
 146  
 
 147  111
             return result;
 148  
         }
 149  
         finally
 150  
         {
 151  111
             OgnlRuntime.getObjectArrayPool().recycle( args );
 152  
         }
 153  
     }
 154  
 
 155  
 
 156  
     public String toGetSourceString( OgnlContext context, Object target )
 157  
     {
 158  53
         String result = "new " + className;
 159  
 
 160  53
         Class clazz = null;
 161  53
         Object ctorValue = null;
 162  
         try
 163  
         {
 164  
 
 165  53
             clazz = OgnlRuntime.classForName( context, className );
 166  
 
 167  53
             ctorValue = this.getValueBody( context, target );
 168  53
             context.setCurrentObject( ctorValue );
 169  
 
 170  53
             if ( clazz != null && ctorValue != null )
 171  
             {
 172  
 
 173  53
                 context.setCurrentType( ctorValue.getClass() );
 174  53
                 context.setCurrentAccessor( ctorValue.getClass() );
 175  
             }
 176  
 
 177  53
             if ( isArray )
 178  
             {
 179  26
                 context.put( "_ctorClass", clazz );
 180  
             }
 181  
         }
 182  0
         catch ( Throwable t )
 183  
         {
 184  0
             throw OgnlOps.castToRuntime( t );
 185  53
         }
 186  
 
 187  
         try
 188  
         {
 189  
 
 190  53
             if ( isArray )
 191  
             {
 192  26
                 if ( children[0] instanceof ASTConst )
 193  
                 {
 194  
 
 195  7
                     result = result + "[" + children[0].toGetSourceString( context, target ) + "]";
 196  
                 }
 197  19
                 else if ( ASTProperty.class.isInstance( children[0] ) )
 198  
                 {
 199  
 
 200  1
                     result =
 201  
                         result + "[" + ExpressionCompiler.getRootExpression( children[0], target, context )
 202  
                             + children[0].toGetSourceString( context, target ) + "]";
 203  
                 }
 204  18
                 else if ( ASTChain.class.isInstance( children[0] ) )
 205  
                 {
 206  
 
 207  1
                     result = result + "[" + children[0].toGetSourceString( context, target ) + "]";
 208  
                 }
 209  
                 else
 210  
                 {
 211  
 
 212  17
                     result = result + "[] " + children[0].toGetSourceString( context, target );
 213  
                 }
 214  
 
 215  
             }
 216  
             else
 217  
             {
 218  27
                 result = result + "(";
 219  
 
 220  27
                 if ( ( children != null ) && ( children.length > 0 ) )
 221  
                 {
 222  
 
 223  21
                     Object[] values = new Object[children.length];
 224  21
                     String[] expressions = new String[children.length];
 225  21
                     Class[] types = new Class[children.length];
 226  
 
 227  
                     // first populate arrays with child values
 228  
 
 229  58
                     for ( int i = 0; i < children.length; i++ )
 230  
                     {
 231  
 
 232  37
                         Object objValue = children[i].getValue( context, context.getRoot() );
 233  37
                         String value = children[i].toGetSourceString( context, target );
 234  
 
 235  37
                         if ( !ASTRootVarRef.class.isInstance( children[i] ) )
 236  
                         {
 237  36
                             value = ExpressionCompiler.getRootExpression( children[i], target, context ) + value;
 238  
                         }
 239  
 
 240  37
                         String cast = "";
 241  37
                         if ( ExpressionCompiler.shouldCast( children[i] ) )
 242  
                         {
 243  
 
 244  13
                             cast = (String) context.remove( ExpressionCompiler.PRE_CAST );
 245  
                         }
 246  37
                         if ( cast == null )
 247  
                         {
 248  12
                             cast = "";
 249  
                         }
 250  
                         
 251  37
                         if ( !ASTConst.class.isInstance( children[i] ) )
 252  
                         {
 253  13
                             value = cast + value;
 254  
                         }
 255  
                         
 256  37
                         values[i] = objValue;
 257  37
                         expressions[i] = value;
 258  37
                         types[i] = context.getCurrentType();
 259  
                     }
 260  
 
 261  
                     // now try and find a matching constructor
 262  
 
 263  21
                     Constructor[] cons = clazz.getConstructors();
 264  21
                     Constructor ctor = null;
 265  21
                     Class[] ctorParamTypes = null;
 266  
 
 267  75
                     for ( int i = 0; i < cons.length; i++ )
 268  
                     {
 269  54
                         Class[] ctorTypes = cons[i].getParameterTypes();
 270  
 
 271  54
                         if ( OgnlRuntime.areArgsCompatible( values, ctorTypes )
 272  
                             && ( ctor == null || OgnlRuntime.isMoreSpecific( ctorTypes, ctorParamTypes ) ) )
 273  
                         {
 274  21
                             ctor = cons[i];
 275  21
                             ctorParamTypes = ctorTypes;
 276  
                         }
 277  
                     }
 278  
 
 279  21
                     if ( ctor == null )
 280  
                     {
 281  0
                         ctor =
 282  
                             OgnlRuntime.getConvertedConstructorAndArgs( context, clazz,
 283  
                                                                         OgnlRuntime.getConstructors( clazz ), values,
 284  
                                                                         new Object[values.length] );
 285  
                     }
 286  
                     
 287  21
                     if ( ctor == null ) 
 288  
                     {
 289  0
                         throw new NoSuchMethodException(
 290  
                             "Unable to find constructor appropriate for arguments in class: " + clazz );
 291  
                     }
 292  21
                     ctorParamTypes = ctor.getParameterTypes();
 293  
 
 294  
                     // now loop over child values again and build up the actual source string
 295  
 
 296  58
                     for ( int i = 0; i < children.length; i++ )
 297  
                     {
 298  37
                         if ( i > 0 )
 299  
                         {
 300  16
                             result = result + ", ";
 301  
                         }
 302  
 
 303  37
                         String value = expressions[i];
 304  
 
 305  37
                         if ( types[i].isPrimitive() )
 306  
                         {
 307  
 
 308  6
                             String literal = OgnlRuntime.getNumericLiteral( types[i] );
 309  6
                             if ( literal != null )
 310  
                             {
 311  6
                                 value += literal;
 312  
                             }
 313  
                         }
 314  
 
 315  37
                         if ( ctorParamTypes[i] != types[i] )
 316  
                         {
 317  
 
 318  4
                             if ( values[i] != null && !types[i].isPrimitive() && !values[i].getClass().isArray()
 319  
                                 && !ASTConst.class.isInstance( children[i] ) )
 320  
                             {
 321  
 
 322  2
                                 value =
 323  
                                     "(" + OgnlRuntime.getCompiler( context ).getInterfaceClass( values[i].getClass() ).getName()
 324  
                                         + ")" + value;
 325  
                             }
 326  2
                             else if ( !ASTConst.class.isInstance( children[i] )
 327  
                                 || ( ASTConst.class.isInstance( children[i] ) && !types[i].isPrimitive() ) )
 328  
                             {
 329  
 
 330  2
                                 if ( !types[i].isArray() && types[i].isPrimitive() && !ctorParamTypes[i].isPrimitive() )
 331  
                                 {
 332  1
                                     value =
 333  
                                         "new "
 334  
                                             + ExpressionCompiler.getCastString( 
 335  
                                                 OgnlRuntime.getPrimitiveWrapperClass( types[i] ) )
 336  
                                             + "(" + value + ")";
 337  
                                 }
 338  
                                 else
 339  
                                 {
 340  1
                                     value = " ($w) " + value;
 341  
                                 }
 342  
                             }
 343  
                         }
 344  
 
 345  37
                         result += value;
 346  
                     }
 347  
 
 348  
                 }
 349  27
                 result = result + ")";
 350  
             }
 351  
 
 352  52
             context.setCurrentType( ctorValue != null ? ctorValue.getClass() : clazz );
 353  52
             context.setCurrentAccessor( clazz );
 354  52
             context.setCurrentObject( ctorValue );
 355  
 
 356  
         }
 357  1
         catch ( Throwable t )
 358  
         {
 359  1
             throw OgnlOps.castToRuntime( t );
 360  52
         }
 361  
 
 362  52
         context.remove( "_ctorClass" );
 363  
 
 364  52
         return result;
 365  
     }
 366  
 
 367  
     public String toSetSourceString( OgnlContext context, Object target )
 368  
     {
 369  32
         return "";
 370  
     }
 371  
 
 372  
     public <R, P> R accept( NodeVisitor<? extends R, ? super P> visitor, P data )
 373  
         throws OgnlException
 374  
     {
 375  0
         return visitor.visit( this, data );
 376  
     }
 377  
 }