11/*
2- * Copyright 2002-2009 the original author or authors.
2+ * Copyright 2002-2010 the original author or authors.
33 *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
1818
1919import java .lang .reflect .Array ;
2020import java .util .List ;
21+ import java .util .ArrayList ;
2122
2223import org .springframework .core .convert .TypeDescriptor ;
2324import org .springframework .expression .AccessException ;
4849 */
4950public class ConstructorReference extends SpelNodeImpl {
5051
52+ private boolean isArrayConstructor = false ;
53+
54+ private SpelNodeImpl [] dimensions ;
55+
5156 // TODO is this caching safe - passing the expression around will mean this executor is also being passed around
5257 /**
5358 * The cached executor that may be reused on subsequent evaluations.
5459 */
5560 private volatile ConstructorExecutor cachedExecutor ;
5661
57- private boolean isArrayConstructor = false ;
58- private SpelNodeImpl [] dimensions ;
5962
6063 /**
6164 * Create a constructor reference. The first argument is the type, the rest are the parameters to the constructor
@@ -76,40 +79,42 @@ public ConstructorReference(int pos, SpelNodeImpl[] dimensions, SpelNodeImpl...
7679 this .dimensions = dimensions ;
7780 }
7881
82+
7983 /**
8084 * Implements getValue() - delegating to the code for building an array or a simple type.
8185 */
8286 @ Override
8387 public TypedValue getValueInternal (ExpressionState state ) throws EvaluationException {
84- if (isArrayConstructor ) {
88+ if (this . isArrayConstructor ) {
8589 return createArray (state );
86- } else {
90+ }
91+ else {
8792 return createNewInstance (state );
8893 }
8994 }
9095
9196 /**
9297 * Create a new ordinary object and return it.
93- *
9498 * @param state the expression state within which this expression is being evaluated
9599 * @return the new object
96100 * @throws EvaluationException if there is a problem creating the object
97101 */
98102 private TypedValue createNewInstance (ExpressionState state ) throws EvaluationException {
99103 Object [] arguments = new Object [getChildCount () - 1 ];
100- Class <?>[] argumentTypes = new Class [ getChildCount () - 1 ] ;
104+ List < TypeDescriptor > argumentTypes = new ArrayList < TypeDescriptor >( getChildCount () - 1 ) ;
101105 for (int i = 0 ; i < arguments .length ; i ++) {
102- TypedValue childValue = children [i + 1 ].getValueInternal (state );
106+ TypedValue childValue = this . children [i + 1 ].getValueInternal (state );
103107 Object value = childValue .getValue ();
104108 arguments [i ] = value ;
105- argumentTypes [ i ] = ( value == null ? null : value . getClass ( ));
109+ argumentTypes . add ( TypeDescriptor . forObject ( value ));
106110 }
107111
108112 ConstructorExecutor executorToUse = this .cachedExecutor ;
109113 if (executorToUse != null ) {
110114 try {
111115 return executorToUse .execute (state .getEvaluationContext (), arguments );
112- } catch (AccessException ae ) {
116+ }
117+ catch (AccessException ae ) {
113118 // Two reasons this can occur:
114119 // 1. the method invoked actually threw a real exception
115120 // 2. the method invoked was not passed the arguments it expected and has become 'stale'
@@ -129,7 +134,7 @@ private TypedValue createNewInstance(ExpressionState state) throws EvaluationExc
129134 if (rootCause instanceof RuntimeException ) {
130135 throw (RuntimeException ) rootCause ;
131136 } else {
132- String typename = (String ) children [0 ].getValueInternal (state ).getValue ();
137+ String typename = (String ) this . children [0 ].getValueInternal (state ).getValue ();
133138 throw new SpelEvaluationException (getStartPosition (), rootCause ,
134139 SpelMessage .CONSTRUCTOR_INVOCATION_PROBLEM , typename , FormatHelper
135140 .formatMethodForMessage ("" , argumentTypes ));
@@ -142,13 +147,13 @@ private TypedValue createNewInstance(ExpressionState state) throws EvaluationExc
142147 }
143148
144149 // either there was no accessor or it no longer exists
145- String typename = (String ) children [0 ].getValueInternal (state ).getValue ();
150+ String typename = (String ) this . children [0 ].getValueInternal (state ).getValue ();
146151 executorToUse = findExecutorForConstructor (typename , argumentTypes , state );
147152 try {
148153 this .cachedExecutor = executorToUse ;
149- TypedValue result = executorToUse .execute (state .getEvaluationContext (), arguments );
150- return result ;
151- } catch (AccessException ae ) {
154+ return executorToUse .execute (state .getEvaluationContext (), arguments );
155+ }
156+ catch (AccessException ae ) {
152157 throw new SpelEvaluationException (getStartPosition (), ae , SpelMessage .CONSTRUCTOR_INVOCATION_PROBLEM ,
153158 typename , FormatHelper .formatMethodForMessage ("" , argumentTypes ));
154159
@@ -158,14 +163,13 @@ private TypedValue createNewInstance(ExpressionState state) throws EvaluationExc
158163 /**
159164 * Go through the list of registered constructor resolvers and see if any can find a constructor that takes the
160165 * specified set of arguments.
161- *
162166 * @param typename the type trying to be constructed
163167 * @param argumentTypes the types of the arguments supplied that the constructor must take
164168 * @param state the current state of the expression
165169 * @return a reusable ConstructorExecutor that can be invoked to run the constructor or null
166170 * @throws SpelEvaluationException if there is a problem locating the constructor
167171 */
168- private ConstructorExecutor findExecutorForConstructor (String typename , Class <?>[] argumentTypes ,
172+ private ConstructorExecutor findExecutorForConstructor (String typename , List < TypeDescriptor > argumentTypes ,
169173 ExpressionState state ) throws SpelEvaluationException {
170174
171175 EvaluationContext eContext = state .getEvaluationContext ();
@@ -178,10 +182,11 @@ private ConstructorExecutor findExecutorForConstructor(String typename, Class<?>
178182 if (cEx != null ) {
179183 return cEx ;
180184 }
181- } catch (AccessException ex ) {
185+ }
186+ catch (AccessException ex ) {
182187 throw new SpelEvaluationException (getStartPosition (), ex ,
183- SpelMessage .CONSTRUCTOR_INVOCATION_PROBLEM , typename , FormatHelper . formatMethodForMessage (
184- "" , argumentTypes ));
188+ SpelMessage .CONSTRUCTOR_INVOCATION_PROBLEM , typename ,
189+ FormatHelper . formatMethodForMessage ( "" , argumentTypes ));
185190 }
186191 }
187192 }
@@ -208,13 +213,11 @@ public String toStringAST() {
208213
209214 /**
210215 * Create an array and return it.
211- *
212216 * @param state the expression state within which this expression is being evaluated
213217 * @return the new array
214218 * @throws EvaluationException if there is a problem creating the array
215219 */
216220 private TypedValue createArray (ExpressionState state ) throws EvaluationException {
217-
218221 // First child gives us the array type which will either be a primitive or reference type
219222 Object intendedArrayType = getChild (0 ).getValue (state );
220223 if (!(intendedArrayType instanceof String )) {
@@ -223,44 +226,44 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException
223226 .formatClassNameForMessage (intendedArrayType .getClass ()));
224227 }
225228 String type = (String ) intendedArrayType ;
226- Class <?> componentType = null ;
229+ Class <?> componentType ;
227230 TypeCode arrayTypeCode = TypeCode .forName (type );
228231 if (arrayTypeCode == TypeCode .OBJECT ) {
229232 componentType = state .findType (type );
230- } else {
233+ }
234+ else {
231235 componentType = arrayTypeCode .getType ();
232236 }
233-
234237 TypeDescriptor td = TypeDescriptor .valueOf (componentType );
235-
236- Object newArray = null ;
237-
238+ Object newArray ;
238239 if (!hasInitializer ()) {
239240 // Confirm all dimensions were specified (for example [3][][5] is missing the 2nd dimension)
240- for (int i = 0 ; i < dimensions . length ; i ++ ) {
241- if (dimensions [ i ] == null ) {
241+ for (SpelNodeImpl dimension : this . dimensions ) {
242+ if (dimension == null ) {
242243 throw new SpelEvaluationException (getStartPosition (), SpelMessage .MISSING_ARRAY_DIMENSION );
243244 }
244245 }
245246 TypeConverter typeConverter = state .getEvaluationContext ().getTypeConverter ();
246247
247248 // Shortcut for 1 dimensional
248- if (dimensions .length == 1 ) {
249- TypedValue o = dimensions [0 ].getTypedValue (state );
249+ if (this . dimensions .length == 1 ) {
250+ TypedValue o = this . dimensions [0 ].getTypedValue (state );
250251 int arraySize = ExpressionUtils .toInt (typeConverter , o );
251252 newArray = Array .newInstance (componentType , arraySize );
252- } else {
253+ }
254+ else {
253255 // Multi-dimensional - hold onto your hat!
254- int [] dims = new int [dimensions .length ];
255- for (int d = 0 ; d < dimensions .length ; d ++) {
256- TypedValue o = dimensions [d ].getTypedValue (state );
256+ int [] dims = new int [this . dimensions .length ];
257+ for (int d = 0 ; d < this . dimensions .length ; d ++) {
258+ TypedValue o = this . dimensions [d ].getTypedValue (state );
257259 dims [d ] = ExpressionUtils .toInt (typeConverter , o );
258260 }
259261 newArray = Array .newInstance (componentType , dims );
260262 }
261- } else {
263+ }
264+ else {
262265 // There is an initializer
263- if (dimensions .length > 1 ) {
266+ if (this . dimensions .length > 1 ) {
264267 // There is an initializer but this is a multi-dimensional array (e.g. new int[][]{{1,2},{3,4}}) - this
265268 // is not currently supported
266269 throw new SpelEvaluationException (getStartPosition (),
@@ -269,8 +272,8 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException
269272 TypeConverter typeConverter = state .getEvaluationContext ().getTypeConverter ();
270273 InlineList initializer = (InlineList ) getChild (1 );
271274 // If a dimension was specified, check it matches the initializer length
272- if (dimensions [0 ] != null ) {
273- TypedValue dValue = dimensions [0 ].getTypedValue (state );
275+ if (this . dimensions [0 ] != null ) {
276+ TypedValue dValue = this . dimensions [0 ].getTypedValue (state );
274277 int i = ExpressionUtils .toInt (typeConverter , dValue );
275278 if (i != initializer .getChildCount ()) {
276279 throw new SpelEvaluationException (getStartPosition (), SpelMessage .INITIALIZER_LENGTH_INCORRECT );
@@ -281,27 +284,35 @@ private TypedValue createArray(ExpressionState state) throws EvaluationException
281284 newArray = Array .newInstance (componentType , arraySize );
282285 if (arrayTypeCode == TypeCode .OBJECT ) {
283286 populateReferenceTypeArray (state , newArray , typeConverter , initializer , componentType );
284- } else if (arrayTypeCode == TypeCode .INT ) {
287+ }
288+ else if (arrayTypeCode == TypeCode .INT ) {
285289 populateIntArray (state , newArray , typeConverter , initializer );
286- } else if (arrayTypeCode == TypeCode .BOOLEAN ) {
290+ }
291+ else if (arrayTypeCode == TypeCode .BOOLEAN ) {
287292 populateBooleanArray (state , newArray , typeConverter , initializer );
288- } else if (arrayTypeCode == TypeCode .CHAR ) {
293+ }
294+ else if (arrayTypeCode == TypeCode .CHAR ) {
289295 populateCharArray (state , newArray , typeConverter , initializer );
290- } else if (arrayTypeCode == TypeCode .LONG ) {
296+ }
297+ else if (arrayTypeCode == TypeCode .LONG ) {
291298 populateLongArray (state , newArray , typeConverter , initializer );
292- } else if (arrayTypeCode == TypeCode .SHORT ) {
299+ }
300+ else if (arrayTypeCode == TypeCode .SHORT ) {
293301 populateShortArray (state , newArray , typeConverter , initializer );
294- } else if (arrayTypeCode == TypeCode .DOUBLE ) {
302+ }
303+ else if (arrayTypeCode == TypeCode .DOUBLE ) {
295304 populateDoubleArray (state , newArray , typeConverter , initializer );
296- } else if (arrayTypeCode == TypeCode .FLOAT ) {
305+ }
306+ else if (arrayTypeCode == TypeCode .FLOAT ) {
297307 populateFloatArray (state , newArray , typeConverter , initializer );
298- } else if (arrayTypeCode == TypeCode .BYTE ) {
308+ }
309+ else if (arrayTypeCode == TypeCode .BYTE ) {
299310 populateByteArray (state , newArray , typeConverter , initializer );
300- } else {
311+ }
312+ else {
301313 throw new IllegalStateException (arrayTypeCode .name ());
302314 }
303315 }
304-
305316 return new TypedValue (newArray , td );
306317 }
307318
0 commit comments