KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jexl > util > introspection > UberspectImpl


1 /*
2  * Copyright 2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.commons.jexl.util.introspection;
18
19 import org.apache.commons.jexl.util.ArrayIterator;
20 import org.apache.commons.jexl.util.EnumerationIterator;
21 import org.apache.commons.jexl.util.AbstractExecutor;
22 import org.apache.commons.jexl.util.GetExecutor;
23 import org.apache.commons.jexl.util.BooleanPropertyExecutor;
24 import org.apache.commons.jexl.util.PropertyExecutor;
25 import org.apache.commons.logging.Log;
26
27 import java.lang.reflect.Method JavaDoc;
28 import java.lang.reflect.InvocationTargetException JavaDoc;
29 import java.lang.reflect.Field JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Collection JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.Enumeration JavaDoc;
34 import java.util.ArrayList JavaDoc;
35
36 /**
37  * Implementation of Uberspect to provide the default introspective
38  * functionality of Velocity.
39  *
40  * @since 1.0
41  * @author <a HREF="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
42  * @version $Id: UberspectImpl.java 398509 2006-05-01 03:34:35Z dion $
43  */

44 public class UberspectImpl implements Uberspect, UberspectLoggable {
45     /** index of the first character of the property. */
46     private static final int PROPERTY_START_INDEX = 3;
47
48     /**
49      * Our runtime logger.
50      */

51     private Log rlog;
52
53     /**
54      * the default Velocity introspector.
55      */

56     private static Introspector introspector;
57
58     /**
59      * init - does nothing - we need to have setRuntimeLogger called before
60      * getting our introspector, as the default vel introspector depends upon
61      * it.
62      * @throws Exception on any error.
63      */

64     public void init() throws Exception JavaDoc {
65     }
66
67     /**
68      * Sets the runtime logger - this must be called before anything else
69      * besides init() as to get the logger. Makes the pull model appealing...
70      * @param runtimeLogger service to use for logging.
71      */

72     public void setRuntimeLogger(Log runtimeLogger) {
73         rlog = runtimeLogger;
74         introspector = new Introspector(rlog);
75     }
76
77     /**
78      * {@inheritDoc}
79      */

80     public Iterator getIterator(Object JavaDoc obj, Info i) throws Exception JavaDoc {
81         if (obj.getClass().isArray()) {
82             return new ArrayIterator(obj);
83         } else if (obj instanceof Collection JavaDoc) {
84             return ((Collection JavaDoc) obj).iterator();
85         } else if (obj instanceof Map JavaDoc) {
86             return ((Map JavaDoc) obj).values().iterator();
87         } else if (obj instanceof Iterator) {
88             rlog.warn("Warning! The iterative " + " is an Iterator in the #foreach() loop at [" + i.getLine() + ","
89                 + i.getColumn() + "]" + " in template " + i.getTemplateName() + ". Because it's not resetable,"
90                 + " if used in more than once, this may lead to" + " unexpected results.");
91
92             return ((Iterator) obj);
93         } else if (obj instanceof Enumeration JavaDoc) {
94             rlog.warn("Warning! The iterative " + " is an Enumeration in the #foreach() loop at [" + i.getLine() + ","
95                 + i.getColumn() + "]" + " in template " + i.getTemplateName() + ". Because it's not resetable,"
96                 + " if used in more than once, this may lead to" + " unexpected results.");
97
98             return new EnumerationIterator((Enumeration JavaDoc) obj);
99         }
100
101         /* we have no clue what this is */
102         rlog.warn("Could not determine type of iterator in " + "#foreach loop " + " at [" + i.getLine() + ","
103             + i.getColumn() + "]" + " in template " + i.getTemplateName());
104
105         return null;
106     }
107
108     /**
109      * {@inheritDoc}
110      */

111     public VelMethod getMethod(Object JavaDoc obj, String JavaDoc methodName, Object JavaDoc[] args, Info i) throws Exception JavaDoc {
112         if (obj == null) {
113             return null;
114         }
115
116         Method JavaDoc m = introspector.getMethod(obj.getClass(), methodName, args);
117         if (m == null && obj instanceof Class JavaDoc) {
118             m = introspector.getMethod((Class JavaDoc) obj, methodName, args);
119         }
120
121         return (m == null) ? null : new VelMethodImpl(m);
122     }
123
124     /**
125      * {@inheritDoc}
126      */

127     public VelPropertyGet getPropertyGet(Object JavaDoc obj, final String JavaDoc identifier, Info i) throws Exception JavaDoc {
128         AbstractExecutor executor;
129
130         Class JavaDoc claz = obj.getClass();
131
132         /*
133          * first try for a getFoo() type of property (also getfoo() )
134          */

135
136         executor = new PropertyExecutor(rlog, introspector, claz, identifier);
137
138         /*
139          * look for boolean isFoo()
140          */

141
142         if (!executor.isAlive()) {
143             executor = new BooleanPropertyExecutor(rlog, introspector, claz, identifier);
144         }
145
146         /*
147          * if that didn't work, look for get("foo")
148          */

149
150         if (!executor.isAlive()) {
151             executor = new GetExecutor(rlog, introspector, claz, identifier);
152         }
153
154         // finally field
155
if (!executor.isAlive()) {
156             try {
157                 final Field JavaDoc field = obj.getClass().getField(identifier);
158                 return new VelPropertyGet() {
159                     public Object JavaDoc invoke(Object JavaDoc o) throws Exception JavaDoc {
160                         return field.get(o);
161                     }
162
163                     public boolean isCacheable() {
164                         return false;
165                     }
166
167                     public String JavaDoc getMethodName() {
168                         return identifier;
169                     }
170                 };
171             } catch (NoSuchFieldException JavaDoc e) {
172                 // fall through
173
}
174         }
175
176
177         return (executor == null) ? null : new VelGetterImpl(executor);
178     }
179
180     /**
181      * {@inheritDoc}
182      */

183     public VelPropertySet getPropertySet(Object JavaDoc obj, String JavaDoc identifier, Object JavaDoc arg, Info i) throws Exception JavaDoc {
184         Class JavaDoc claz = obj.getClass();
185
186         VelMethod vm = null;
187         try {
188             /*
189              * first, we introspect for the set<identifier> setter method
190              */

191
192             Object JavaDoc[] params = {arg};
193
194             try {
195                 vm = getMethod(obj, "set" + identifier, params, i);
196
197                 if (vm == null) {
198                     throw new NoSuchMethodException JavaDoc();
199                 }
200             } catch (NoSuchMethodException JavaDoc nsme2) {
201                 StringBuffer JavaDoc sb = new StringBuffer JavaDoc("set");
202                 sb.append(identifier);
203
204                 if (Character.isLowerCase(sb.charAt(PROPERTY_START_INDEX))) {
205                     sb.setCharAt(PROPERTY_START_INDEX, Character.toUpperCase(sb.charAt(PROPERTY_START_INDEX)));
206                 } else {
207                     sb.setCharAt(PROPERTY_START_INDEX, Character.toLowerCase(sb.charAt(PROPERTY_START_INDEX)));
208                 }
209
210                 vm = getMethod(obj, sb.toString(), params, i);
211
212                 if (vm == null) {
213                     throw new NoSuchMethodException JavaDoc();
214                 }
215             }
216         } catch (NoSuchMethodException JavaDoc nsme) {
217             /*
218              * right now, we only support the Map interface
219              */

220
221             if (Map JavaDoc.class.isAssignableFrom(claz)) {
222                 Object JavaDoc[] params = {new Object JavaDoc(), new Object JavaDoc()};
223
224                 vm = getMethod(obj, "put", params, i);
225
226                 if (vm != null) {
227                     return new VelSetterImpl(vm, identifier);
228                 }
229             }
230         }
231
232         return (vm == null) ? null : new VelSetterImpl(vm);
233     }
234
235     /**
236      * An implementation of {@link VelMethod}.
237      */

238     public class VelMethodImpl implements VelMethod {
239         /** the method. */
240         protected Method JavaDoc method = null;
241         /**
242          * Create a new instance.
243          *
244          * @param m the method.
245          */

246         public VelMethodImpl(Method JavaDoc m) {
247             method = m;
248         }
249
250         /**
251          * {@inheritDoc}
252          */

253         public Object JavaDoc invoke(Object JavaDoc o, Object JavaDoc[] params) throws Exception JavaDoc {
254             try {
255                 return method.invoke(o, params);
256             } catch (InvocationTargetException JavaDoc e) {
257                 final Throwable JavaDoc t = e.getTargetException();
258
259                 if (t instanceof Exception JavaDoc) {
260                     throw (Exception JavaDoc) t;
261                 } else if (t instanceof Error JavaDoc) {
262                     throw (Error JavaDoc) t;
263                 } else {
264                     throw e;
265                 }
266             }
267         }
268
269         /**
270          * {@inheritDoc}
271          */

272         public boolean isCacheable() {
273             return true;
274         }
275
276         /**
277          * {@inheritDoc}
278          */

279         public String JavaDoc getMethodName() {
280             return method.getName();
281         }
282
283         /**
284          * {@inheritDoc}
285          */

286         public Class JavaDoc getReturnType() {
287             return method.getReturnType();
288         }
289     }
290
291     /**
292      * {@inheritDoc}
293      */

294     public class VelGetterImpl implements VelPropertyGet {
295         /** executor for performing the get. */
296         protected AbstractExecutor ae = null;
297
298         /**
299          * Create the getter using an {@link AbstractExecutor} to
300          * do the work.
301          * @param exec the executor.
302          */

303         public VelGetterImpl(AbstractExecutor exec) {
304             ae = exec;
305         }
306
307         /**
308          * {@inheritDoc}
309          */

310         public Object JavaDoc invoke(Object JavaDoc o) throws Exception JavaDoc {
311             return ae.execute(o);
312         }
313
314         /**
315          * {@inheritDoc}
316          */

317         public boolean isCacheable() {
318             return true;
319         }
320
321         /**
322          * {@inheritDoc}
323          */

324         public String JavaDoc getMethodName() {
325             return ae.getMethod().getName();
326         }
327     }
328
329     /**
330      * {@inheritDoc}
331      */

332     public class VelSetterImpl implements VelPropertySet {
333         /** the method to call. */
334         protected VelMethod vm = null;
335         /** the key for indexed and other properties. */
336         protected String JavaDoc putKey = null;
337
338         /**
339          * Create an instance.
340          * @param velmethod the method to call on set.
341          */

342         public VelSetterImpl(VelMethod velmethod) {
343             this.vm = velmethod;
344         }
345
346         /**
347          * Create an instance.
348          * @param velmethod the method to call on set.
349          * @param key the index or other value passed to a
350          * setProperty(xxx, value) method.
351          */

352         public VelSetterImpl(VelMethod velmethod, String JavaDoc key) {
353             this.vm = velmethod;
354             putKey = key;
355         }
356
357         /** {@inheritDoc} */
358         public Object JavaDoc invoke(Object JavaDoc o, Object JavaDoc value) throws Exception JavaDoc {
359             ArrayList JavaDoc al = new ArrayList JavaDoc();
360
361             if (putKey == null) {
362                 al.add(value);
363             } else {
364                 al.add(putKey);
365                 al.add(value);
366             }
367
368             return vm.invoke(o, al.toArray());
369         }
370
371         /** {@inheritDoc} */
372         public boolean isCacheable() {
373             return true;
374         }
375
376         /** {@inheritDoc} */
377         public String JavaDoc getMethodName() {
378             return vm.getMethodName();
379         }
380
381     }
382 }
383
Popular Tags