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 java.util.*;
23
24
25
26
27
28
29
30 public class ListPropertyAccessor
31 extends ObjectPropertyAccessor
32 implements PropertyAccessor
33 {
34
35 @Override
36 public Object getProperty( Map<String, Object> context, Object target, Object name )
37 throws OgnlException
38 {
39 List<?> list = (List<?>) target;
40
41 if ( name instanceof String )
42 {
43 Object result;
44
45 if ( "size".equals( name ) )
46 {
47 result = list.size();
48 }
49 else
50 {
51 if ( "iterator".equals( name ) )
52 {
53 result = list.iterator();
54 }
55 else
56 {
57 if ( "isEmpty".equals( name ) || "empty".equals( name ) )
58 {
59 result = list.isEmpty() ? Boolean.TRUE : Boolean.FALSE;
60 }
61 else
62 {
63 result = super.getProperty( context, target, name );
64 }
65 }
66 }
67
68 return result;
69 }
70
71 if ( name instanceof Number )
72 {
73 return list.get( ( (Number) name ).intValue() );
74 }
75
76 if ( name instanceof DynamicSubscript )
77 {
78 int len = list.size();
79 switch ( ( (DynamicSubscript) name ).getFlag() )
80 {
81 case DynamicSubscript.FIRST:
82 return len > 0 ? list.get( 0 ) : null;
83 case DynamicSubscript.MID:
84 return len > 0 ? list.get( len / 2 ) : null;
85 case DynamicSubscript.LAST:
86 return len > 0 ? list.get( len - 1 ) : null;
87 case DynamicSubscript.ALL:
88 return new ArrayList<Object>( list );
89 default:
90 break;
91 }
92 }
93
94 throw new NoSuchPropertyException( target, name );
95 }
96
97 @Override
98 public void setProperty( Map<String, Object> context, Object target, Object name, Object value )
99 throws OgnlException
100 {
101 if ( name instanceof String && !( (String) name ).contains( "$" ) )
102 {
103 super.setProperty( context, target, name, value );
104 return;
105 }
106
107 @SuppressWarnings( "unchecked" )
108 List<Object> list = (List<Object>) target;
109
110 if ( name instanceof Number )
111 {
112 list.set( ( (Number) name ).intValue(), value );
113 return;
114 }
115
116 if ( name instanceof DynamicSubscript )
117 {
118 int len = list.size();
119 switch ( ( (DynamicSubscript) name ).getFlag() )
120 {
121 case DynamicSubscript.FIRST:
122 if ( len > 0 )
123 {
124 list.set( 0, value );
125 }
126 return;
127 case DynamicSubscript.MID:
128 if ( len > 0 )
129 {
130 list.set( len / 2, value );
131 }
132 return;
133 case DynamicSubscript.LAST:
134 if ( len > 0 )
135 {
136 list.set( len - 1, value );
137 }
138 return;
139 case DynamicSubscript.ALL:
140 if ( !( value instanceof Collection ) )
141 {
142 throw new OgnlException( "Value must be a collection" );
143 }
144 list.clear();
145 list.addAll( (Collection<?>) value );
146 return;
147 default:
148 return;
149 }
150 }
151
152 throw new NoSuchPropertyException( target, name );
153 }
154
155 @Override
156 public Class<?> getPropertyClass( OgnlContext context, Object target, Object index )
157 {
158 if ( index instanceof String )
159 {
160 String key = ( (String) index ).replaceAll( "\"", "" );
161 if ( "size".equals( key ) )
162 {
163 return int.class;
164 }
165 if ( "iterator".equals( key ) )
166 {
167 return Iterator.class;
168 }
169 if ( "isEmpty".equals( key ) || "empty".equals( key ) )
170 {
171 return boolean.class;
172 }
173 return super.getPropertyClass( context, target, index );
174 }
175
176 if ( index instanceof Number )
177 {
178 return Object.class;
179 }
180
181 return null;
182 }
183
184 @Override
185 public String getSourceAccessor( OgnlContext context, Object target, Object index )
186 {
187 String indexStr = index.toString().replaceAll( "\"", "" );
188
189 if ( String.class.isInstance( index ) )
190 {
191 if ( "size".equals( indexStr ) )
192 {
193 context.setCurrentAccessor( List.class );
194 context.setCurrentType( int.class );
195 return ".size()";
196 }
197 if ( "iterator".equals( indexStr ) )
198 {
199 context.setCurrentAccessor( List.class );
200 context.setCurrentType( Iterator.class );
201 return ".iterator()";
202 }
203 if ( "isEmpty".equals( indexStr ) || "empty".equals( indexStr ) )
204 {
205 context.setCurrentAccessor( List.class );
206 context.setCurrentType( boolean.class );
207 return ".isEmpty()";
208 }
209 }
210
211
212
213 return getSourceBeanMethod( context, target, index, indexStr, false );
214 }
215
216 @Override
217 public String getSourceSetter( OgnlContext context, Object target, Object index )
218 {
219 String indexStr = index.toString().replaceAll( "\"", "" );
220
221
222
223
224
225
226
227
228
229 return getSourceBeanMethod( context, target, index, indexStr, true );
230 }
231
232 private String getSourceBeanMethod( OgnlContext context, Object target, Object index, String indexStr,
233 boolean isSetter )
234 {
235 Object currentObject = context.getCurrentObject();
236 Class<?> currentType = context.getCurrentType();
237 if ( currentObject != null && !Number.class.isInstance( currentObject ) )
238 {
239 try
240 {
241 if ( isSetter )
242 {
243 if ( OgnlRuntime.getWriteMethod( target.getClass(), indexStr ) != null
244 || !currentType.isPrimitive() )
245 {
246 return super.getSourceSetter( context, target, index );
247 }
248 }
249 else
250 {
251 if ( OgnlRuntime.getReadMethod( target.getClass(), indexStr ) != null )
252 {
253 return super.getSourceAccessor( context, target, index );
254 }
255 }
256 }
257 catch ( Throwable t )
258 {
259 throw OgnlOps.castToRuntime( t );
260 }
261 }
262
263
264
265
266
267 context.setCurrentAccessor( List.class );
268
269
270
271 if ( !currentType.isPrimitive() && Number.class.isAssignableFrom( currentType ) )
272 {
273 indexStr += "." + OgnlRuntime.getNumericValueGetter( currentType );
274 }
275 else if ( currentObject != null && Number.class.isAssignableFrom( currentObject.getClass() )
276 && !currentType.isPrimitive() )
277 {
278
279
280 String toString = String.class.isInstance( index ) && currentType != Object.class ? "" : ".toString()";
281
282 indexStr = "org.apache.commons.ognl.OgnlOps#getIntValue(" + indexStr + toString + ")";
283 }
284
285 context.setCurrentType( Object.class );
286
287 return isSetter ? ".set(" + indexStr + ", $3)" : ".get(" + indexStr + ")";
288 }
289
290 }