KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > program > JavaClassDef


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.program;
31
32 import com.caucho.quercus.Quercus;
33 import com.caucho.quercus.QuercusException;
34 import com.caucho.quercus.annotation.Construct;
35 import com.caucho.quercus.env.*;
36 import com.caucho.quercus.expr.Expr;
37 import com.caucho.quercus.expr.LiteralExpr;
38 import com.caucho.quercus.function.JavaMarshal;
39 import com.caucho.quercus.function.Marshal;
40 import com.caucho.quercus.function.MarshalFactory;
41 import com.caucho.quercus.module.ModuleContext;
42 import com.caucho.util.L10N;
43 import com.caucho.vfs.WriteStream;
44
45 import java.io.IOException JavaDoc;
46 import java.lang.reflect.Constructor JavaDoc;
47 import java.lang.reflect.Field JavaDoc;
48 import java.lang.reflect.Method JavaDoc;
49 import java.lang.reflect.Modifier JavaDoc;
50 import java.net.URL JavaDoc;
51 import java.util.ArrayList JavaDoc;
52 import java.util.Calendar JavaDoc;
53 import java.util.Collection JavaDoc;
54 import java.util.Date JavaDoc;
55 import java.util.HashMap JavaDoc;
56 import java.util.IdentityHashMap JavaDoc;
57 import java.util.Iterator JavaDoc;
58 import java.util.List JavaDoc;
59 import java.util.Map JavaDoc;
60 import java.util.logging.Level JavaDoc;
61 import java.util.logging.Logger JavaDoc;
62
63 /**
64  * Represents an introspected Java class.
65  */

66 public class JavaClassDef extends ClassDef {
67   private final static Logger JavaDoc log
68     = Logger.getLogger(JavaClassDef.class.getName());
69   private final static L10N L = new L10N(JavaClassDef.class);
70
71   private final ModuleContext _moduleContext;
72
73   private final String JavaDoc _name;
74   private final Class JavaDoc _type;
75   private final boolean _isArray;
76   
77   private JavaClassDef _componentDef;
78
79   protected volatile boolean _isInit;
80
81   private final HashMap JavaDoc<String JavaDoc, Value> _constMap
82     = new HashMap JavaDoc<String JavaDoc, Value>();
83
84   private final HashMap JavaDoc<String JavaDoc, AbstractJavaMethod> _functionMap
85     = new HashMap JavaDoc<String JavaDoc, AbstractJavaMethod>();
86
87   private final HashMap JavaDoc<String JavaDoc, JavaMethod> _getMap
88     = new HashMap JavaDoc<String JavaDoc, JavaMethod>();
89
90   private final HashMap JavaDoc<String JavaDoc, JavaMethod> _setMap
91     = new HashMap JavaDoc<String JavaDoc, JavaMethod>();
92
93   // _fieldMap stores all public non-static fields
94
// used by getField and setField
95
private final HashMap JavaDoc<String JavaDoc, FieldMarshalPair> _fieldMap
96     = new HashMap JavaDoc<String JavaDoc, FieldMarshalPair> ();
97
98   private JavaMethod __get = null;
99
100   private JavaMethod __getField = null;
101
102   private JavaMethod __set = null;
103
104   private JavaMethod __setField = null;
105
106   private JavaMethod __call = null;
107
108   private Method JavaDoc _printRImpl = null;
109   private Method JavaDoc _varDumpImpl = null;
110
111   private JavaInvoker _cons;
112
113   private Method JavaDoc _iterator;
114
115   private Marshal _marshal;
116
117   protected JavaClassDef(ModuleContext moduleContext, String JavaDoc name, Class JavaDoc type)
118   {
119     super(name, null, new String JavaDoc[0]);
120
121     _moduleContext = moduleContext;
122
123     _name = name;
124
125     _type = type;
126
127     _isArray = type.isArray();
128   }
129
130   public static JavaClassDef create(ModuleContext moduleContext,
131                     String JavaDoc name, Class JavaDoc type)
132   {
133     if (Double JavaDoc.class.isAssignableFrom(type) ||
134     Float JavaDoc.class.isAssignableFrom(type))
135       return new DoubleClassDef(moduleContext);
136     else if (Number JavaDoc.class.isAssignableFrom(type))
137       return new LongClassDef(moduleContext);
138     else if (String JavaDoc.class.isAssignableFrom(type) ||
139          Character JavaDoc.class.isAssignableFrom(type))
140       return new StringClassDef(moduleContext);
141     else if (Boolean JavaDoc.class.isAssignableFrom(type))
142       return new BooleanClassDef(moduleContext);
143     else if (Calendar JavaDoc.class.isAssignableFrom(type))
144       return new CalendarClassDef(moduleContext);
145     else if (Date JavaDoc.class.isAssignableFrom(type))
146       return new DateClassDef(moduleContext);
147     else if (URL JavaDoc.class.isAssignableFrom(type))
148       return new URLClassDef(moduleContext);
149     else if (Map JavaDoc.class.isAssignableFrom(type))
150       return new JavaMapClassDef(moduleContext, name, type);
151     else if (List JavaDoc.class.isAssignableFrom(type))
152       return new JavaListClassDef(moduleContext, name, type);
153     else if (Collection JavaDoc.class.isAssignableFrom(type))
154       return new JavaCollectionClassDef(moduleContext, name, type);
155     else
156       return new JavaClassDef(moduleContext, name, type);
157   }
158
159   /**
160    * Returns the class name.
161    */

162   public String JavaDoc getName()
163   {
164     return _name;
165   }
166
167   public Class JavaDoc getType()
168   {
169     return _type;
170   }
171
172   public boolean isA(String JavaDoc name)
173   {
174     Class JavaDoc type = _type;
175
176     while (type != null) {
177       if (type.getSimpleName().equalsIgnoreCase(name))
178         return true;
179
180       if (isAInterface(name, type))
181         return true;
182
183       type = type.getSuperclass();
184     }
185
186     return false;
187   }
188
189   private boolean isAInterface(String JavaDoc name, Class JavaDoc type)
190   {
191     Class JavaDoc[] interfaces = type.getInterfaces();
192
193     if (interfaces != null) {
194       for (Class JavaDoc intfc : interfaces) {
195         if (intfc.getSimpleName().equalsIgnoreCase(name))
196           return true;
197
198         if (isAInterface(name, intfc))
199           return true;
200       }
201     }
202
203     return false;
204   }
205
206   public boolean isArray()
207   {
208     return _isArray;
209   }
210
211   public JavaClassDef getComponentDef()
212   {
213     if (_componentDef == null) {
214       Class JavaDoc compType = getType().getComponentType();
215       _componentDef = _moduleContext.getJavaClassDefinition(compType.getName());
216     }
217     
218     return _componentDef;
219   }
220
221   public Value wrap(Env env, Object JavaDoc obj)
222   {
223     if (! _isInit)
224       init();
225     
226     return new JavaValue(env, obj, this);
227   }
228
229   /**
230    * For array dereferencing.
231    *
232    * Also designed to call __get()
233    * IE: SimpleXMLElement
234    *
235    * @param name
236    * @return Value
237    */

238   public Value get(Env env, Object JavaDoc obj, Value name)
239   {
240     if (__get != null) {
241       try {
242        //__get needs to handle a Value $foo[5] vs. $foo['bar']
243
return __get.call(env, obj, name);
244       } catch (Throwable JavaDoc e) {
245         log.log(Level.FINE, L.l(e.getMessage()), e);
246         return NullValue.NULL;
247       }
248     }
249
250     return NullValue.NULL;
251   }
252
253   /**
254    * @param name
255    * @return Value attained through invoking getter
256    */

257   public Value getField(Env env, Object JavaDoc obj, String JavaDoc name)
258   {
259     Object JavaDoc result;
260
261     JavaMethod get = _getMap.get(name);
262
263     if (get != null) {
264       try {
265         return get.call(env, obj);
266       } catch (Throwable JavaDoc e) {
267         log.log(Level.FINE, L.l(e.getMessage()), e);
268         return NullValue.NULL;
269       }
270     } else {
271       FieldMarshalPair fieldPair = _fieldMap.get(name);
272       if (fieldPair != null) {
273         try {
274           result = fieldPair._field.get(obj);
275           return fieldPair._marshal.unmarshal(env, result);
276         } catch (Throwable JavaDoc e) {
277           log.log(Level.FINE, L.l(e.getMessage()), e);
278           return NullValue.NULL;
279         }
280       } else if (__getField != null) {
281         try {
282           return __getField.call(env, obj, new StringValueImpl(name));
283         } catch (Throwable JavaDoc e) {
284           log.log(Level.FINE, L.l(e.getMessage()), e);
285           return NullValue.NULL;
286         }
287       }
288     }
289
290     return NullValue.NULL;
291   }
292
293   /**
294    * specifically designed for __set()
295    *
296    * @param env
297    * @param obj
298    * @param name
299    * @param value
300    * @return value
301    */

302   public Value put(Env env,
303                    Object JavaDoc obj,
304                    Value name,
305                    Value value)
306   {
307     if (__set != null) {
308       try {
309         return __set.call(env, obj, name, value);
310       } catch (Throwable JavaDoc e) {
311         log.log(Level.FINE, L.l(e.getMessage()), e);
312         return NullValue.NULL;
313
314       }
315     }
316
317     return NullValue.NULL;
318   }
319
320   public Value putField(Env env,
321                         Object JavaDoc obj,
322                         String JavaDoc name,
323                         Value value)
324   {
325     JavaMethod setter = _setMap.get(name);
326
327     if (setter != null) {
328       try {
329         return setter.call(env, obj, value);
330       } catch (Throwable JavaDoc e) {
331         log.log(Level.FINE, L.l(e.getMessage()), e);
332         return NullValue.NULL;
333       }
334     } else {
335       FieldMarshalPair fieldPair = _fieldMap.get(name);
336       if (fieldPair != null) {
337         try {
338           Class JavaDoc type = fieldPair._field.getType();
339           Object JavaDoc marshaledValue = fieldPair._marshal.marshal(env, value, type);
340           fieldPair._field.set(obj, marshaledValue);
341
342           return value;
343
344         } catch (Throwable JavaDoc e) {
345           log.log(Level.FINE, L.l(e.getMessage()), e);
346           return NullValue.NULL;
347         }
348       } else if (__setField != null) {
349         try {
350           return __setField.call(env, obj, new StringValueImpl(name), value);
351         } catch (Throwable JavaDoc e) {
352           log.log(Level.FINE, L.l(e.getMessage()), e);
353           return NullValue.NULL;
354
355         }
356       }
357     }
358
359     return NullValue.NULL;
360
361   }
362
363   /**
364    * Returns the marshal instance.
365    */

366   public Marshal getMarshal()
367   {
368     return _marshal;
369   }
370
371   /**
372    * Creates a new instance.
373    */

374   public Value newInstance(Env env, QuercusClass qClass)
375   {
376     // return newInstance();
377
return null;
378   }
379
380   public Value newInstance()
381   {
382     return null;
383     /*
384     try {
385       //Object obj = _type.newInstance();
386       return new JavaValue(null, _type.newInstance(), this);
387     } catch (Exception e) {
388       throw new QuercusRuntimeException(e);
389     }
390     */

391   }
392
393   /**
394    * Eval new
395    */

396   public Value callNew(Env env, Expr []args)
397   {
398     return _cons.call(env, (Object JavaDoc) null, args);
399   }
400
401   /**
402    * Eval new
403    */

404   public Value callNew(Env env, Value []args)
405   {
406     if (_cons != null)
407       return _cons.call(env, (Object JavaDoc) null, args);
408     else
409       return NullValue.NULL;
410   }
411
412   /**
413    * Returns the matching method.
414    */

415   public AbstractFunction findFunction(String JavaDoc name)
416   {
417     return _functionMap.get(name);
418   }
419
420   /**
421    * Returns the __call.
422    */

423   public AbstractFunction getCallMethod()
424   {
425     return __call;
426   }
427
428   /**
429    * Eval a method
430    */

431   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name, Expr []args)
432   {
433     AbstractJavaMethod method = _functionMap.get(name);
434
435     if (method != null) {
436     }
437     else if (method == null) {
438       env.warning(env.getLocation().getMessagePrefix() + L.l("{0}::{1} is an unknown method.",
439                                           _name, name));
440
441       return NullValue.NULL;
442     }
443
444     return method.call(env, obj, args);
445   }
446
447   /**
448    * Eval a method
449    */

450   public Value callMethod(Env env, Value value, String JavaDoc name, Expr []args)
451   {
452     return callMethod(env, value.toJavaObject(), name, args);
453   }
454
455   /**
456    * Eval a method
457    */

458   public Value callMethod(Env env, Value value, String JavaDoc name, Value []args)
459   {
460     return callMethod(env, value.toJavaObject(), name, args);
461   }
462
463   /**
464    * Eval a method
465    */

466   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name, Value []args)
467   {
468     AbstractJavaMethod method = _functionMap.get(name);
469
470     if (method != null)
471       return method.call(env, obj, args);
472     else if (__call != null) {
473       Value []extArgs = new Value[args.length + 1];
474
475       extArgs[0] = new StringValueImpl(name);
476
477       System.arraycopy(args, 0, extArgs, 1, args.length);
478       
479       return __call.call(env, obj, extArgs);
480     }
481     else {
482       env.error(L.l("'{0}::{1}' is an unknown method",
483             _name, name));
484
485       return NullValue.NULL;
486     }
487   }
488
489   /**
490    * Eval a method
491    */

492   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name)
493   {
494     AbstractJavaMethod method = _functionMap.get(name);
495
496     if (method != null)
497       return method.call(env, obj);
498     else if (__call != null)
499       return __call.call(env, obj, new StringValueImpl(name));
500     else {
501       env.error(L.l("'{0}::{1}' is an unknown method",
502             _name, name));
503
504       return NullValue.NULL;
505     }
506   }
507
508   /**
509    * Eval a method
510    */

511   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name, Value a1)
512   {
513     AbstractJavaMethod method = _functionMap.get(name);
514
515     if (method != null)
516       return method.call(env, obj, a1);
517     else if (__call != null)
518       return __call.call(env, obj, new StringValueImpl(name), a1);
519     else {
520       env.error(L.l("'{0}::{1}' is an unknown method",
521             _name, name));
522
523       return NullValue.NULL;
524     }
525   }
526
527   /**
528    * Eval a method
529    */

530   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name,
531                           Value a1, Value a2)
532   {
533     AbstractJavaMethod method = _functionMap.get(name);
534
535     if (method != null)
536       return method.call(env, obj, a1, a2);
537     else if (__call != null)
538       return __call.call(env, obj, new StringValueImpl(name), a1, a2);
539     else {
540       env.error(L.l("'{0}::{1}' is an unknown method",
541             _name, name));
542
543       return NullValue.NULL;
544     }
545   }
546
547   /**
548    * Eval a method
549    */

550   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name,
551                           Value a1, Value a2, Value a3)
552   {
553     return getMethod(env, name).call(env, obj, a1, a2, a3);
554   }
555
556   /**
557    * Eval a method
558    */

559   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name,
560                           Value a1, Value a2, Value a3, Value a4)
561   {
562     return getMethod(env, name).call(env, obj, a1, a2, a3, a4);
563   }
564
565   /**
566    * Eval a method
567    */

568   public Value callMethod(Env env, Object JavaDoc obj, String JavaDoc name,
569                           Value a1, Value a2, Value a3, Value a4, Value a5)
570   {
571     return getMethod(env, name).call(env, obj, a1, a2, a3, a4, a5);
572   }
573
574   /**
575    * Returns the values for an iterator.
576    */

577   public Value []getValueArray(Env env, Object JavaDoc obj)
578   {
579     try {
580       if (_iterator == null)
581         return new Value[0];
582
583       Iterator JavaDoc iter = (Iterator JavaDoc) _iterator.invoke(obj);
584
585       ArrayList JavaDoc<Value> values = new ArrayList JavaDoc<Value>();
586
587       while (iter.hasNext()) {
588         Object JavaDoc objValue = iter.next();
589
590         if (objValue instanceof Value)
591           values.add((Value) objValue);
592         else
593           values.add(env.wrapJava(objValue));
594       }
595
596       Value []valueArray = new Value[values.size()];
597
598       values.toArray(valueArray);
599
600       return valueArray;
601     } catch (Throwable JavaDoc e) {
602       throw new RuntimeException JavaDoc(e);
603     }
604   }
605
606   private AbstractJavaMethod getMethod(Env env, String JavaDoc name)
607   {
608     AbstractJavaMethod method = _functionMap.get(name);
609
610     if (method != null)
611       return method;
612     else if (method == null) {
613       env.error(L.l("`{0}' is an unknown method of {1}.", name, _name));
614     }
615
616     return method;
617   }
618
619   /**
620    * Initialize the quercus class.
621    */

622   public void initClass(QuercusClass cl)
623   {
624     init();
625     
626     if (_cons != null)
627       cl.setConstructor(_cons);
628
629     if (__get != null)
630       cl.setGet(__get);
631     
632     for (Map.Entry JavaDoc<String JavaDoc,AbstractJavaMethod> entry : _functionMap.entrySet()) {
633       cl.addMethod(entry.getKey(), entry.getValue());
634     }
635
636     if (__call != null)
637       cl.setCall(__call);
638
639     for (Map.Entry JavaDoc<String JavaDoc,Value> entry : _constMap.entrySet()) {
640       cl.addConstant(entry.getKey(), new LiteralExpr(entry.getValue()));
641     }
642   }
643
644   /**
645    * Finds the matching constant
646    */

647   public Value findConstant(Env env, String JavaDoc name)
648   {
649     return _constMap.get(name);
650   }
651
652   /**
653    * Creates a new instance.
654    */

655   public void initInstance(Env env, Value value)
656   {
657   }
658
659   /**
660    * Returns the constructor
661    */

662   public AbstractFunction findConstructor()
663   {
664     return null;
665   }
666
667   public void init()
668   {
669     introspect();
670   }
671   
672   /**
673    * Introspects the Java class.
674    */

675   public synchronized void introspect()
676   {
677     if (_isInit)
678       return;
679
680     try {
681       introspectConstants(_type);
682       introspectMethods(_moduleContext, _type);
683       introspectFields(_moduleContext, _type);
684
685       _marshal = new JavaMarshal(this, false);
686
687       Method JavaDoc consMethod = getConsMethod(_type);
688
689       if (consMethod != null)
690     _cons = new JavaMethod(_moduleContext, consMethod);
691       else {
692     Constructor JavaDoc []cons = _type.getConstructors();
693
694     if (cons.length > 0) {
695       int i;
696       for (i = 0; i < cons.length; i++) {
697         if (cons[i].isAnnotationPresent(Construct.class))
698           break;
699       }
700
701       if (i < cons.length)
702         _cons = new JavaConstructor(_moduleContext, cons[i]);
703       else
704         _cons = new JavaConstructor(_moduleContext, cons[0]);
705
706     } else
707       _cons = null;
708       }
709
710       try {
711     Method JavaDoc method = _type.getMethod("iterator", new Class JavaDoc[0]);
712
713     if (method != null &&
714         Iterator JavaDoc.class.isAssignableFrom(method.getReturnType()))
715       _iterator = method;
716       } catch (Throwable JavaDoc e) {
717       }
718     } finally {
719       _isInit = true;
720     }
721   }
722
723   private Method JavaDoc getConsMethod(Class JavaDoc type)
724   {
725     Method JavaDoc []methods = type.getMethods();
726
727     for (int i = 0; i < methods.length; i++) {
728       Method JavaDoc method = methods[i];
729       
730       if (! method.getName().equals("__construct"))
731     continue;
732       if (! Modifier.isStatic(method.getModifiers()))
733     continue;
734       if (! Modifier.isPublic(method.getModifiers()))
735     continue;
736
737       return method;
738     }
739
740     return null;
741   }
742
743   protected void setCons(Method JavaDoc method)
744   {
745     _cons = new JavaMethod(_moduleContext, method);
746   }
747
748   /**
749    * Introspects the Java class.
750    */

751   private void introspectFields(ModuleContext moduleContext, Class JavaDoc type)
752   {
753     if (type == null || type.equals(Object JavaDoc.class))
754       return;
755
756     if (! Modifier.isPublic(type.getModifiers()))
757       return;
758
759     // Introspect getXXX and setXXX
760
// also register whether __get, __getField, __set, __setField exists
761
Method JavaDoc[] methods = type.getMethods();
762
763     for (Method JavaDoc method : methods) {
764       if (Modifier.isStatic(method.getModifiers()))
765         continue;
766
767       String JavaDoc methodName = method.getName();
768       int length = methodName.length();
769
770       if (length > 3) {
771         if (methodName.startsWith("get")) {
772           _getMap.put(javaToQuercusConvert(methodName.substring(3, length)),
773               new JavaMethod(moduleContext, method));
774
775         }
776         else if (methodName.startsWith("is")) {
777           _getMap.put(javaToQuercusConvert(methodName.substring(2, length)),
778               new JavaMethod(moduleContext, method));
779         }
780         else if (methodName.startsWith("set")) {
781           JavaMethod javaMethod = new JavaMethod(moduleContext, method);
782           _setMap.put(javaToQuercusConvert(methodName.substring(3, length)),
783               new JavaMethod(moduleContext, method));
784
785         } else if ("__get".equals(methodName)) {
786           __get = new JavaMethod(moduleContext, method);
787         } else if ("__getField".equals(methodName)) {
788           __getField = new JavaMethod(moduleContext, method);
789         } else if ("__set".equals(methodName)) {
790           __set = new JavaMethod(moduleContext, method);
791         } else if ("__setField".equals(methodName)) {
792           __setField = new JavaMethod(moduleContext, method);
793         }
794       }
795     }
796
797     // Introspect public non-static fields
798
Field JavaDoc[] fields = type.getFields();
799
800     for (Field JavaDoc field : fields) {
801       if (Modifier.isStatic(field.getModifiers()))
802         continue;
803
804       MarshalFactory factory = moduleContext.getMarshalFactory();
805       Marshal marshal = factory.create(field.getType(), false);
806       _fieldMap.put(field.getName(), new FieldMarshalPair(field, marshal));
807     }
808
809
810    // introspectFields(quercus, type.getSuperclass());
811
}
812
813   /**
814    * helper for introspectFields
815    *
816    * @param s (IE: Foo, URL)
817    * @return (foo, URL)
818    */

819   private String JavaDoc javaToQuercusConvert(String JavaDoc s)
820   {
821     if (s.length() == 1) {
822       return new String JavaDoc(new char[] {Character.toLowerCase(s.charAt(0))});
823     }
824
825     if (Character.isUpperCase(s.charAt(1)))
826       return s;
827     else {
828       StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
829       sb.append(Character.toLowerCase(s.charAt(0)));
830
831       int length = s.length();
832       for (int i = 1; i < length; i++) {
833         sb.append(s.charAt(i));
834       }
835
836       return sb.toString();
837     }
838   }
839
840   /**
841    * Introspects the Java class.
842    */

843   private void introspectConstants(Class JavaDoc type)
844   {
845     if (type == null || type.equals(Object JavaDoc.class))
846       return;
847
848     if (! Modifier.isPublic(type.getModifiers()))
849       return;
850
851     Class JavaDoc []ifcs = type.getInterfaces();
852
853     for (Class JavaDoc ifc : ifcs) {
854       introspectConstants(ifc);
855     }
856
857     Field JavaDoc []fields = type.getDeclaredFields();
858
859     for (Field JavaDoc field : fields) {
860       if (_constMap.get(field.getName()) != null)
861         continue;
862       else if (! Modifier.isPublic(field.getModifiers()))
863         continue;
864       else if (! Modifier.isStatic(field.getModifiers()))
865         continue;
866       else if (! Modifier.isFinal(field.getModifiers()))
867         continue;
868
869       try {
870         Value value = Quercus.objectToValue(field.get(null));
871
872         if (value != null)
873           _constMap.put(field.getName().intern(), value);
874       } catch (Throwable JavaDoc e) {
875         log.log(Level.FINER, e.toString(), e);
876       }
877     }
878
879     introspectConstants(type.getSuperclass());
880   }
881
882   /**
883    * Introspects the Java class.
884    */

885   private void introspectMethods(ModuleContext moduleContext, Class JavaDoc type)
886   {
887     if (type == null || type.equals(Object JavaDoc.class))
888       return;
889
890     Method JavaDoc []methods = type.getMethods();
891
892     for (Method JavaDoc method : methods) {
893       if (_functionMap.get(method.getName()) != null)
894         continue;
895       else if (! Modifier.isPublic(method.getModifiers()))
896         continue;
897
898       if ("printRImpl".equals(method.getName())) {
899         _printRImpl = method;
900       } else if ("varDumpImpl".equals(method.getName())) {
901         _varDumpImpl = method;
902       } else if ("__call".equals(method.getName())) {
903     __call = new JavaMethod(moduleContext, method);
904       } else {
905     ArrayList JavaDoc<Method JavaDoc> methodList = getMethods(methods, method.getName());
906
907     if (methodList.size() == 1)
908       _functionMap.put(method.getName(),
909                new JavaMethod(moduleContext, method));
910     else
911       _functionMap.put(method.getName(),
912                new JavaOverloadMethod(moduleContext, methodList));
913       }
914     }
915
916     introspectMethods(moduleContext, type.getSuperclass());
917
918     Class JavaDoc []ifcs = type.getInterfaces();
919
920     for (Class JavaDoc ifc : ifcs) {
921       introspectMethods(moduleContext, ifc);
922     }
923   }
924
925   private ArrayList JavaDoc<Method JavaDoc> getMethods(Method JavaDoc []methods, String JavaDoc name)
926   {
927     ArrayList JavaDoc<Method JavaDoc> methodList = new ArrayList JavaDoc<Method JavaDoc>();
928
929     for (int i = 0; i < methods.length; i++) {
930       if (! Modifier.isPublic(methods[i].getModifiers()))
931     continue;
932       else if (! methods[i].getName().equals(name))
933     continue;
934
935       methodList.add(methods[i]);
936     }
937
938     return methodList;
939   }
940
941   /**
942    *
943    * @param env
944    * @param obj
945    * @param out
946    * @param depth
947    * @param valueSet
948    * @return false if printRImpl not implemented
949    * @throws IOException
950    */

951   protected boolean printRImpl(Env env,
952                                Object JavaDoc obj,
953                                WriteStream out,
954                                int depth,
955                                IdentityHashMap JavaDoc<Value, String JavaDoc> valueSet)
956     throws IOException JavaDoc
957   {
958
959     try {
960       if (_printRImpl == null) {
961     return false;
962     
963       }
964       
965       _printRImpl.invoke(obj, env, out, depth, valueSet);
966       return true;
967     } catch (Exception JavaDoc e) {
968       throw new QuercusException(e);
969     }
970   }
971
972   public boolean varDumpImpl(Env env,
973                              Object JavaDoc obj,
974                              WriteStream out,
975                              int depth,
976                              IdentityHashMap JavaDoc<Value, String JavaDoc> valueSet)
977     throws IOException JavaDoc
978   {
979     try {
980       if (_varDumpImpl == null) {
981     return false;
982     
983       }
984       
985       _varDumpImpl.invoke(obj, env, out, depth, valueSet);
986       return true;
987     } catch (Exception JavaDoc e) {
988       throw new QuercusException(e);
989     }
990   }
991
992   private class MethodMarshalPair {
993     public Method JavaDoc _method;
994     public Marshal _marshal;
995
996     public MethodMarshalPair(Method JavaDoc method,
997                               Marshal marshal)
998     {
999       _method = method;
1000      _marshal = marshal;
1001    }
1002  }
1003
1004  private class FieldMarshalPair {
1005    public Field JavaDoc _field;
1006    public Marshal _marshal;
1007
1008    public FieldMarshalPair(Field JavaDoc field,
1009                             Marshal marshal)
1010    {
1011      _field = field;
1012      _marshal = marshal;
1013    }
1014  }
1015  
1016  private static class LongClassDef extends JavaClassDef {
1017    LongClassDef(ModuleContext module)
1018    {
1019      super(module, "Long", Long JavaDoc.class);
1020    }
1021
1022    public Value wrap(Env env, Object JavaDoc obj)
1023    {
1024      return LongValue.create(((Number JavaDoc) obj).longValue());
1025    }
1026  }
1027  
1028  private static class DoubleClassDef extends JavaClassDef {
1029    DoubleClassDef(ModuleContext module)
1030    {
1031      super(module, "Double", Double JavaDoc.class);
1032    }
1033
1034    public Value wrap(Env env, Object JavaDoc obj)
1035    {
1036      return new DoubleValue(((Number JavaDoc) obj).doubleValue());
1037    }
1038  }
1039  
1040  private static class StringClassDef extends JavaClassDef {
1041    StringClassDef(ModuleContext module)
1042    {
1043      super(module, "String", String JavaDoc.class);
1044    }
1045
1046    public Value wrap(Env env, Object JavaDoc obj)
1047    {
1048      return new StringValueImpl((String JavaDoc) obj);
1049    }
1050  }
1051  
1052  private static class BooleanClassDef extends JavaClassDef {
1053    BooleanClassDef(ModuleContext module)
1054    {
1055      super(module, "Boolean", Boolean JavaDoc.class);
1056    }
1057
1058    public Value wrap(Env env, Object JavaDoc obj)
1059    {
1060      if (Boolean.TRUE.equals(obj))
1061    return BooleanValue.TRUE;
1062      else
1063    return BooleanValue.FALSE;
1064    }
1065  }
1066  
1067  private static class CalendarClassDef extends JavaClassDef {
1068    CalendarClassDef(ModuleContext module)
1069    {
1070      super(module, "Calendar", Calendar JavaDoc.class);
1071    }
1072    
1073    public Value wrap(Env env, Object JavaDoc obj)
1074    {
1075      return new JavaCalendarValue(env, (Calendar JavaDoc)obj, this);
1076    }
1077  }
1078  
1079  private static class DateClassDef extends JavaClassDef {
1080    DateClassDef(ModuleContext module)
1081    {
1082      super(module, "Date", Date JavaDoc.class);
1083    }
1084    
1085    public Value wrap(Env env, Object JavaDoc obj)
1086    {
1087      return new JavaDateValue(env, (Date JavaDoc)obj, this);
1088    }
1089  }
1090  
1091  private static class URLClassDef extends JavaClassDef {
1092    URLClassDef(ModuleContext module)
1093    {
1094      super(module, "URL", URL JavaDoc.class);
1095    }
1096    
1097    public Value wrap(Env env, Object JavaDoc obj)
1098    {
1099      return new JavaURLValue(env, (URL JavaDoc)obj, this);
1100    }
1101  }
1102}
1103
1104
Popular Tags