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