1 package org.apache.velocity.util.introspection;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.lang.reflect.Method;
23 import java.util.Collection;
24 import java.util.Enumeration;
25 import java.util.Iterator;
26 import java.util.Map;
27
28 import org.apache.velocity.runtime.RuntimeLogger;
29 import org.apache.velocity.runtime.log.Log;
30 import org.apache.velocity.runtime.log.RuntimeLoggerLog;
31 import org.apache.velocity.runtime.parser.node.AbstractExecutor;
32 import org.apache.velocity.runtime.parser.node.BooleanPropertyExecutor;
33 import org.apache.velocity.runtime.parser.node.GetExecutor;
34 import org.apache.velocity.runtime.parser.node.MapGetExecutor;
35 import org.apache.velocity.runtime.parser.node.MapSetExecutor;
36 import org.apache.velocity.runtime.parser.node.PropertyExecutor;
37 import org.apache.velocity.runtime.parser.node.PutExecutor;
38 import org.apache.velocity.runtime.parser.node.SetExecutor;
39 import org.apache.velocity.runtime.parser.node.SetPropertyExecutor;
40 import org.apache.velocity.util.ArrayIterator;
41 import org.apache.velocity.util.EnumerationIterator;
42
43
44
45
46
47
48
49
50
51 public class UberspectImpl implements Uberspect, UberspectLoggable
52 {
53
54
55
56 protected Log log;
57
58
59
60
61 protected Introspector introspector;
62
63
64
65
66
67
68 public void init()
69 {
70 introspector = new Introspector(log);
71 }
72
73
74
75
76
77
78
79 public void setLog(Log log)
80 {
81 this.log = log;
82 }
83
84
85
86
87
88 public void setRuntimeLogger(RuntimeLogger runtimeLogger)
89 {
90
91
92 setLog(new RuntimeLoggerLog(runtimeLogger));
93 }
94
95
96
97
98
99
100
101
102
103
104 public Iterator getIterator(Object obj, Info i)
105 throws Exception
106 {
107 if (obj.getClass().isArray())
108 {
109 return new ArrayIterator(obj);
110 }
111 else if (obj instanceof Collection)
112 {
113 return ((Collection) obj).iterator();
114 }
115 else if (obj instanceof Map)
116 {
117 return ((Map) obj).values().iterator();
118 }
119 else if (obj instanceof Iterator)
120 {
121 if (log.isDebugEnabled())
122 {
123 log.debug("The iterative object in the #foreach() loop at " +
124 i + " is of type java.util.Iterator. Because " +
125 "it is not resettable, if used in more than once it " +
126 "may lead to unexpected results.");
127 }
128 return ((Iterator) obj);
129 }
130 else if (obj instanceof Enumeration)
131 {
132 if (log.isDebugEnabled())
133 {
134 log.debug("The iterative object in the #foreach() loop at " +
135 i + " is of type java.util.Enumeration. Because " +
136 "it is not resettable, if used in more than once it " +
137 "may lead to unexpected results.");
138 }
139 return new EnumerationIterator((Enumeration) obj);
140 }
141
142
143 log.info("Could not determine type of iterator in #foreach loop at " + i);
144
145 return null;
146 }
147
148
149
150
151
152
153
154
155
156
157 public VelMethod getMethod(Object obj, String methodName, Object[] args, Info i)
158 throws Exception
159 {
160 if (obj == null)
161 {
162 return null;
163 }
164
165 Method m = introspector.getMethod(obj.getClass(), methodName, args);
166 if (m != null)
167 {
168 return new VelMethodImpl(m);
169 }
170 else if (obj.getClass().isArray())
171 {
172
173 if (VelArrayMethod.supports(methodName, args))
174 {
175 return new VelArrayMethod(obj.getClass(), methodName, args);
176 }
177 }
178 return null;
179 }
180
181
182
183
184
185
186
187
188
189 public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i)
190 throws Exception
191 {
192 if (obj == null)
193 {
194 return null;
195 }
196
197 Class claz = obj.getClass();
198
199
200
201
202
203 AbstractExecutor executor = new PropertyExecutor(log, introspector, claz, identifier);
204
205
206
207
208 if (!executor.isAlive())
209 {
210 executor = new MapGetExecutor(log, claz, identifier);
211 }
212
213
214
215
216
217 if (!executor.isAlive())
218 {
219 executor = new GetExecutor(log, introspector, claz, identifier);
220 }
221
222
223
224
225
226 if (!executor.isAlive())
227 {
228 executor = new BooleanPropertyExecutor(log, introspector, claz,
229 identifier);
230 }
231
232 return (executor.isAlive()) ? new VelGetterImpl(executor) : null;
233 }
234
235
236
237
238
239
240
241
242
243
244 public VelPropertySet getPropertySet(Object obj, String identifier,
245 Object arg, Info i)
246 throws Exception
247 {
248 if (obj == null)
249 {
250 return null;
251 }
252
253 Class claz = obj.getClass();
254
255
256
257
258
259 SetExecutor executor = new SetPropertyExecutor(log, introspector, claz, identifier, arg);
260
261
262
263
264 if (!executor.isAlive()) {
265 executor = new MapSetExecutor(log, claz, identifier);
266 }
267
268
269
270
271
272 if (!executor.isAlive())
273 {
274 executor = new PutExecutor(log, introspector, claz, arg, identifier);
275 }
276
277 return (executor.isAlive()) ? new VelSetterImpl(executor) : null;
278 }
279
280
281
282
283 public static class VelMethodImpl implements VelMethod
284 {
285 final Method method;
286
287
288
289
290 public VelMethodImpl(Method m)
291 {
292 method = m;
293 }
294
295 private VelMethodImpl()
296 {
297 method = null;
298 }
299
300
301
302
303 public Object invoke(Object o, Object[] params)
304 throws Exception
305 {
306 return method.invoke(o, params);
307 }
308
309
310
311
312 public boolean isCacheable()
313 {
314 return true;
315 }
316
317
318
319
320 public String getMethodName()
321 {
322 return method.getName();
323 }
324
325
326
327
328 public Class getReturnType()
329 {
330 return method.getReturnType();
331 }
332 }
333
334
335
336
337
338 public static class VelGetterImpl implements VelPropertyGet
339 {
340 final AbstractExecutor getExecutor;
341
342
343
344
345 public VelGetterImpl(AbstractExecutor exec)
346 {
347 getExecutor = exec;
348 }
349
350 private VelGetterImpl()
351 {
352 getExecutor = null;
353 }
354
355
356
357
358 public Object invoke(Object o)
359 throws Exception
360 {
361 return getExecutor.execute(o);
362 }
363
364
365
366
367 public boolean isCacheable()
368 {
369 return true;
370 }
371
372
373
374
375 public String getMethodName()
376 {
377 return getExecutor.isAlive() ? getExecutor.getMethod().getName() : null;
378 }
379 }
380
381
382
383
384 public static class VelSetterImpl implements VelPropertySet
385 {
386 private final SetExecutor setExecutor;
387
388
389
390
391 public VelSetterImpl(final SetExecutor setExecutor)
392 {
393 this.setExecutor = setExecutor;
394 }
395
396 private VelSetterImpl()
397 {
398 setExecutor = null;
399 }
400
401
402
403
404
405
406
407
408
409 public Object invoke(final Object o, final Object value)
410 throws Exception
411 {
412 return setExecutor.execute(o, value);
413 }
414
415
416
417
418 public boolean isCacheable()
419 {
420 return true;
421 }
422
423
424
425
426 public String getMethodName()
427 {
428 return setExecutor.isAlive() ? setExecutor.getMethod().getName() : null;
429 }
430 }
431 }