KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > python > core > PyJavaClass


1 // Copyright (c) Corporation for National Research Initiatives
2
package org.python.core;
3
4 import java.lang.reflect.Constructor JavaDoc;
5 import java.lang.reflect.Field JavaDoc;
6 import java.lang.reflect.Method JavaDoc;
7 import java.lang.reflect.Modifier JavaDoc;
8
9 /**
10  * A wrapper around a java class.
11  */

12
13 public class PyJavaClass extends PyClass
14 {
15     public PyReflectedConstructor __init__;
16
17     public PackageManager __mgr__;
18
19     private static InternalTables tbl;
20
21     public synchronized final static InternalTables getInternalTables() {
22         if(tbl == null)
23           tbl = InternalTables.createInternalTables();
24         return tbl;
25     }
26
27     public final boolean isLazy() {
28         return proxyClass == null;
29     }
30
31     public static final PyJavaClass lookup(String JavaDoc name,PackageManager mgr) {
32         if (tbl.queryCanonical(name)) {
33             Class JavaDoc c = mgr.findClass(null,name,"forced java class");
34             check_lazy_allowed(c); // xxx
35
return lookup(c);
36         }
37         PyJavaClass ret = new PyJavaClass(name, mgr);
38         tbl.putLazyCanonical(name, ret);
39         return ret;
40     }
41
42     public synchronized static final PyJavaClass lookup(Class JavaDoc c) {
43         if (tbl == null) {
44             tbl = InternalTables.createInternalTables();
45             PyJavaClass jc = new PyJavaClass(true);
46             jc.init(PyJavaClass.class);
47             tbl.putCanonical(PyJavaClass.class,jc);
48         }
49         PyJavaClass ret = tbl.getCanonical(c);
50         if (ret != null)
51             return ret;
52         PyJavaClass lazy = tbl.getLazyCanonical(c.getName());
53         if (lazy != null) {
54             initLazy(lazy);
55             if (lazy.proxyClass == c) return lazy;
56         }
57
58         Class JavaDoc parent = c.getDeclaringClass();
59         if (parent == null)
60             ret = new PyJavaClass(c);
61         else
62             ret = new PyJavaInnerClass(c, lookup(parent));
63         tbl.putCanonical(c,ret);
64
65         return ret;
66     }
67
68     private PyJavaClass(boolean fakeArg) {
69         super(true);
70     }
71
72     protected PyJavaClass(Class JavaDoc c) {
73         init(c);
74     }
75
76     protected PyJavaClass(String JavaDoc name,PackageManager mgr) {
77         __name__ = name;
78         this.__mgr__ = mgr;
79     }
80
81     protected void findModule(PyObject dict) {}
82
83     protected Class JavaDoc getProxyClass() {
84         initialize();
85         return proxyClass;
86     }
87
88     // for the moment trying to lazily load a PyObject subclass
89
// is not allowed, (because of the PyJavaClass vs PyType class mismatch)
90
// pending PyJavaClass becoming likely a subclass of PyType
91
private static final void check_lazy_allowed(Class JavaDoc c) {
92         if (PyObject.class.isAssignableFrom(c)) { // xxx
93
throw Py.TypeError("cannot lazy load PyObject subclass");
94         }
95     }
96
97     private static final void initLazy(PyJavaClass jc) {
98         Class JavaDoc c = jc.__mgr__.findClass(null,jc.__name__,"lazy java class");
99         check_lazy_allowed(c); // xxx
100
jc.init(c);
101         tbl.putCanonical(jc.proxyClass,jc);
102         jc.__mgr__ = null;
103     }
104
105     private boolean initialized=false;
106
107     // Prevent recursive calls to initialize()
108
private boolean initializing=false;
109
110     private synchronized void initialize() {
111         if (initialized || initializing)
112             return;
113         initializing = true;
114         synchronized(PyJavaClass.class) {
115             if (proxyClass == null) {
116                 initLazy(this);
117             }
118         }
119         init__bases__(proxyClass);
120         init__dict__();
121
122         if (ClassDictInit.class.isAssignableFrom(proxyClass)
123                             && proxyClass != ClassDictInit.class) {
124             try {
125                 Method JavaDoc m = proxyClass.getMethod("classDictInit",
126                      new Class JavaDoc[] { PyObject.class });
127                 m.invoke(null, new Object JavaDoc[] { __dict__ });
128             }
129             catch (Exception JavaDoc exc) {
130                 // System.err.println("Got exception: " + exc + " " +
131
// proxyClass);
132
throw Py.JavaError(exc);
133             }
134         }
135
136         if (InitModule.class.isAssignableFrom(proxyClass)) {
137             try {
138                 InitModule m = (InitModule)proxyClass.newInstance();
139                 m.initModule(__dict__);
140             }
141             catch (Exception JavaDoc exc) {
142 // System.err.println("Got exception: " + exc);
143
throw Py.JavaError(exc);
144             }
145         }
146
147         initialized = true;
148         initializing = false;
149     }
150
151     private synchronized void init__dict__() {
152         if (__dict__ != null)
153             return;
154         PyStringMap d = new PyStringMap();
155 // d.__setitem__("__module__", Py.None);
156
__dict__ = d;
157         try {
158             Method JavaDoc[] methods = getAccessibleMethods(proxyClass);
159             setBeanInfoCustom(proxyClass, methods);
160             setFields(proxyClass);
161             setMethods(proxyClass, methods);
162         } catch (SecurityException JavaDoc se) {}
163     }
164
165     private synchronized void init__class__(Class JavaDoc c) {
166         /* xxx disable opt, will need similar opt for types
167         if (!PyObject.class.isAssignableFrom(c))
168             return;
169         try {
170             Field field = c.getField("__class__");
171             if (Modifier.isStatic(field.getModifiers()) &&
172                 field.getType().isAssignableFrom(PyJavaClass.class) &&
173                 field.getDeclaringClass() == c)
174             {
175                 field.set(null, this);
176             }
177         }
178         catch (NoSuchFieldException exc) {}
179         catch (IllegalAccessException exc1) {} */

180     }
181
182     private synchronized void init__bases__(Class JavaDoc c) {
183         if (__bases__ != null) return;
184
185         Class JavaDoc interfaces[] = getAccessibleInterfaces(c);
186         int nInterfaces = interfaces.length;
187         int nBases = 0;
188         int i;
189         for (i=0; i<nInterfaces; i++) {
190             Class JavaDoc inter = interfaces[i];
191             if (inter == InitModule.class || inter == PyProxy.class ||
192                 inter == ClassDictInit.class)
193                 continue;
194             nBases++;
195         }
196
197         Class JavaDoc superclass = c.getSuperclass();
198         int index=0;
199         PyObject[] bases;
200         PyJavaClass tmp;
201         if (superclass == null || superclass == PyObject.class) {
202             bases = new PyObject[nBases];
203         } else {
204             bases = new PyObject[nBases+1];
205             tmp = PyJavaClass.lookup(superclass);
206             bases[0] = tmp;
207             tmp.initialize();
208             index++;
209         }
210
211         for (i=0; i<nInterfaces; i++) {
212             Class JavaDoc inter = interfaces[i];
213             if (inter == InitModule.class || inter == PyProxy.class ||
214                 inter == ClassDictInit.class)
215                 continue;
216             tmp = PyJavaClass.lookup(inter);
217             tmp.initialize();
218             bases[index++] = tmp;
219         }
220
221         __bases__ = new PyTuple(bases);
222     }
223
224     private void init(Class JavaDoc c) {
225         init__class__(c);
226         proxyClass = c;
227         __name__ = c.getName();
228     }
229
230     /**
231      * Return the list of all accessible interfaces for a class. This will
232      * only the public interfaces. Since we can't set accessibility on
233      * interfaces, the Options.respectJavaAccessibility is not honored.
234      */

235     private static Class JavaDoc[] getAccessibleInterfaces(Class JavaDoc c) {
236         // can't modify accessibility of interfaces in Java2
237
// thus get only public interfaces
238
Class JavaDoc[] in = c.getInterfaces();
239         java.util.Vector JavaDoc v=new java.util.Vector JavaDoc();
240         for (int i = 0; i < in.length; i++) {
241             if (!Modifier.isPublic(in[i].getModifiers()))
242                 continue;
243             v.addElement(in[i]);
244         }
245         if (v.size() == in.length)
246             return in;
247         Class JavaDoc[] ret = new Class JavaDoc[v.size()];
248         v.copyInto(ret);
249         return ret;
250     }
251
252      /**
253       * Return the list of all accessible fields for a class. This will
254       * only the public fields unless Options.respectJavaAccessibility is
255       * false, in which case all fields are returned.
256       */

257     private static Field JavaDoc[] getAccessibleFields(Class JavaDoc c) {
258         if (!JavaAccessibility.accessIsMutable())
259             // returns just the public fields
260
return c.getFields();
261         // from here on out we know we must be using at least Java 1.2.
262
// Note that an ArrayList would be better here because we don't
263
// need access to be synchronized, but that would prevent this file
264
// from being compiled on Java 1.1 (as opposed to being compilable,
265
// but not having the feature available).
266
java.util.Vector JavaDoc fields = new java.util.Vector JavaDoc();
267         while (c != null) {
268             // get all declared fields for this class, mutate their
269
// accessibility and pop it into the array for later
270
Field JavaDoc[] declared = c.getDeclaredFields();
271             for (int i=0; i < declared.length; i++) {
272                 // TBD: this is a permanent change. Should we provide a
273
// way to restore the original accessibility flag?
274
JavaAccessibility.setAccessible(declared[i], true);
275                 fields.addElement(declared[i]);
276             }
277             // walk down superclass chain. no need to deal specially with
278
// interfaces...
279
c = c.getSuperclass();
280         }
281 // return (Field[])fields.toArray(new Field[fields.size()]);
282
Field JavaDoc[] ret = new Field JavaDoc[fields.size()];
283         fields.copyInto(ret);
284         return ret;
285     }
286
287     private void setFields(Class JavaDoc c) {
288         Field JavaDoc[] fields = getAccessibleFields(c);
289         for (int i=0; i<fields.length; i++) {
290             Field JavaDoc field = fields[i];
291             if (field.getDeclaringClass() != c)
292                 continue;
293
294             String JavaDoc name = getName(field.getName());
295             boolean isstatic = Modifier.isStatic(field.getModifiers());
296
297             if (isstatic) {
298                 if (name.startsWith("__doc__") && name.length() > 7)
299                     continue;
300                 PyObject prop = lookup(name, false);
301                 if (prop != null && prop instanceof PyBeanProperty) {
302                     PyBeanProperty beanProp = ((PyBeanProperty)prop).copy();
303                     beanProp.field = field;
304                     __dict__.__setitem__(name, beanProp);
305                     continue;
306                 }
307             }
308             __dict__.__setitem__(name, new PyReflectedField(field));
309         }
310     }
311
312     /* Produce a good Python name for a Java method. If the Java method
313        ends in '$', strip it (this handles reserved Java keywords) Don't
314        make any changes to keywords since this is now handled by parser
315     */

316
317     private String JavaDoc getName(String JavaDoc name) {
318         if (name.endsWith("$")) name = name.substring(0, name.length()-1);
319         return name.intern();
320     }
321
322     private void addMethod(Method JavaDoc meth) {
323         String JavaDoc name = getName(meth.getName());
324         if (name == "_getPyInstance" || name == "_setPyInstance" ||
325             name == "_getPySystemState" || name == "_setPySystemState")
326         {
327             return;
328         }
329
330         // Special case to handle a few troublesome methods in java.awt.*.
331
// These methods are all deprecated and interfere too badly with
332
// bean properties to be tolerated. This is totally a hack, but a
333
// lot of code that uses java.awt will break without it.
334
String JavaDoc classname = proxyClass.getName();
335         if (classname.startsWith("java.awt.") &&
336             classname.indexOf('.', 9) == -1)
337         {
338             if (name == "layout" || name == "insets" ||
339                 name == "size" || name == "minimumSize" ||
340                 name == "preferredSize" || name == "maximumSize" ||
341                 name == "bounds" || name == "enable")
342             {
343                 return;
344             }
345         }
346
347         // See if any of my superclasses are using 'name' for something
348
// else. Or if I'm already using it myself
349
PyObject o = lookup(name, false);
350
351         // If it's being used as a function, then things get more
352
// interesting...
353
PyReflectedFunction func;
354         if (o != null && o instanceof PyReflectedFunction) {
355             func = (PyReflectedFunction)o;
356
357             PyObject o1 = __dict__.__finditem__(name);
358
359             /* If this function already exists, add this method to the
360                signature. If this alters the signature of the function in
361                some significant way, then return a duplicate and stick it in
362                the __dict__ */

363             if (o1 != o) {
364                 if (func.handles(meth))
365                     return;
366                 func = func.copy();
367             }
368             func.addMethod(meth);
369         } else {
370             func = new PyReflectedFunction(meth);
371             try {
372                 Field JavaDoc docField = proxyClass.getField("__doc__" + name);
373                 int mods = docField.getModifiers();
374                 if (docField.getType() == PyString.class &&
375                        Modifier.isPublic(mods) &&
376                        Modifier.isStatic(mods));
377                     func.__doc__ = (PyString) docField.get(null);
378             } catch (NoSuchFieldException JavaDoc ex) {
379             } catch (SecurityException JavaDoc ex) {
380             } catch (IllegalAccessException JavaDoc ex) {}
381         }
382         __dict__.__setitem__(name, func);
383     }
384
385
386      /**
387       * Return the list of all accessible methods for a class. This will
388       * only the public methods unless Options.respectJavaAccessibility is
389       * false, in which case all methods are returned.
390       */

391     private static Method JavaDoc[] getAccessibleMethods(Class JavaDoc c) {
392         if (!JavaAccessibility.accessIsMutable())
393             // returns just the public methods
394
return c.getMethods();
395         Method JavaDoc[] declared = c.getDeclaredMethods();
396         for (int i=0; i < declared.length; i++) {
397             // TBD: this is a permanent change. Should we provide a way to
398
// restore the original accessibility flag?
399
JavaAccessibility.setAccessible(declared[i], true);
400         }
401         return declared;
402     }
403
404     private boolean ignoreMethod(Method JavaDoc method) {
405         Class JavaDoc[] exceptions = method.getExceptionTypes();
406         for (int j = 0; j < exceptions.length; j++) {
407             if (exceptions[j] == PyIgnoreMethodTag.class) {
408                 return true;
409             }
410         }
411         return false;
412     }
413
414     /* Add all methods declared by this class */
415     private void setMethods(Class JavaDoc c, Method JavaDoc[] methods) {
416         for (int i=0; i<methods.length; i++) {
417             Method JavaDoc method = methods[i];
418             Class JavaDoc dc = method.getDeclaringClass();
419             if (dc != c)
420                 continue;
421             int mods = dc.getModifiers();
422             if(!(Modifier.isPublic(mods) || Modifier.isPrivate(mods) || Modifier.isProtected(mods))) {
423                 // skip package protected classes such as AbstractStringBuilder or UNIXProcess
424
continue;
425             }
426             if (ignoreMethod(method))
427                 continue;
428             addMethod(method);
429         }
430     }
431
432     /* Adds a bean property to this class */
433     void addProperty(String JavaDoc name, Class JavaDoc propClass,
434                      Method JavaDoc getMethod, Method JavaDoc setMethod)
435     {
436         // This will skip indexed property types
437
if (propClass == null)
438             return;
439
440         boolean set = true;
441         name = getName(name);
442
443         PyBeanProperty prop = new PyBeanProperty(name, propClass, getMethod,
444                                                  setMethod);
445
446         // Check to see if this name is already being used...
447
PyObject o = lookup(name, false);
448
449         if (o != null) {
450             if (!(o instanceof PyReflectedField))
451                 return;
452
453             if (o instanceof PyBeanProperty) {
454                 PyBeanProperty oldProp = (PyBeanProperty)o;
455                 if (prop.myType == oldProp.myType) {
456                     // If this adds nothing over old property, do nothing
457
if ((prop.getMethod == null || oldProp.getMethod != null)
458                         &&
459                         (prop.setMethod == null || oldProp.setMethod != null))
460                     {
461                         set = false;
462                     }
463
464                     // Add old get/set methods to current prop
465
// Handles issues with private classes
466
if (oldProp.getMethod != null) {
467                         prop.getMethod = oldProp.getMethod;
468                     }
469                     if (oldProp.setMethod != null) {
470                         prop.setMethod = oldProp.setMethod;
471                     }
472                 }
473             }
474             // This is now handled in setFields which gets called after
475
// setBeanProperties
476
// else {
477
// // Keep static fields around...
478
// PyReflectedField field = (PyReflectedField)o;
479
// if (Modifier.isStatic(field.field.getModifiers())) {
480
// prop.field = field.field;
481
// } else {
482
// // If the field is not static (and thus subsumable)
483
// // don't overwrite
484
// return;
485
// }
486
// }
487
}
488         if (set)
489             __dict__.__setitem__(name, prop);
490     }
491
492     /* Adds a bean event to this class */
493     void addEvent(String JavaDoc name, Class JavaDoc eventClass, Method JavaDoc addMethod,
494                   Method JavaDoc[] meths)
495     {
496         String JavaDoc eventName = eventClass.getName();
497
498         for (int i=0; i<meths.length; i++) {
499             PyBeanEventProperty prop;
500             prop = new PyBeanEventProperty(name, eventClass, addMethod,
501                                            meths[i]);
502             __dict__.__setitem__(prop.__name__, prop);
503         }
504         PyBeanEvent event = new PyBeanEvent(name, eventClass, addMethod);
505         __dict__.__setitem__(event.__name__, event);
506     }
507
508
509     /* A reimplementation of java.beans.Introspector.decapitalize.
510        This is needed due to bugs in Netscape Navigator
511     */

512     private static String JavaDoc decapitalize(String JavaDoc s) {
513         //return java.beans.Introspector.decapitalize(s);
514
if (s.length() == 0)
515             return s;
516         char c0 = s.charAt(0);
517         if (Character.isUpperCase(c0)) {
518             if (s.length() > 1 && Character.isUpperCase(s.charAt(1)))
519                 return s;
520             char[] cs = s.toCharArray();
521             cs[0] = Character.toLowerCase(c0);
522             return new String JavaDoc(cs);
523         } else {
524             return s;
525         }
526     }
527
528     // This method is a workaround for Netscape's stupid security bug!
529
private void setBeanInfoCustom(Class JavaDoc c, Method JavaDoc[] meths) {
530         //try {
531
int i;
532         int n = meths.length;
533         for (i=0; i<n; i++) {
534             Method JavaDoc method = meths[i];
535
536             if (ignoreMethod(method))
537                 continue;
538             if (method.getDeclaringClass() != c ||
539                 Modifier.isStatic(method.getModifiers()))
540             {
541                 continue;
542             }
543
544             String JavaDoc name = method.getName();
545             Method JavaDoc getter = null;
546             Method JavaDoc setter = null;
547             Class JavaDoc[] args = method.getParameterTypes();
548             Class JavaDoc ret = method.getReturnType();
549             Class JavaDoc myType=null;
550
551             String JavaDoc pname="";
552
553             if (name.startsWith("get")) {
554                 if (args.length != 0)
555                     continue;
556                 getter = method;
557                 pname = decapitalize(name.substring(3));
558                 myType = ret;
559                 //System.out.println("get: "+name+", "+myType);
560
} else {
561                 if (name.startsWith("is")) {
562                     if (args.length != 0 || ret != Boolean.TYPE)
563                         continue;
564                     getter = method;
565                     pname = decapitalize(name.substring(2));
566                     myType = ret;
567                 } else {
568                     if (name.startsWith("set")) {
569                         if (args.length != 1)
570                             continue;
571                         setter = method;
572                         pname = decapitalize(name.substring(3));
573                         myType = args[0];
574                         //System.out.println("set: "+name+", "+myType);
575
} else {
576                         continue;
577                     }
578                 }
579             }
580
581             PyObject o = __dict__.__finditem__(new PyString(pname));
582             PyBeanProperty prop;
583             if (o == null || !(o instanceof PyBeanProperty) ) {
584                 addProperty(pname, myType, getter, setter);
585             } else {
586                 prop = (PyBeanProperty)o;
587                 if (prop.myType != myType) {
588                     if (getter != null) {
589                         addProperty(pname, myType, getter, setter);
590                     }
591                 } else {
592                     //System.out.println("p: "+prop.myType+", "+myType);
593
if (getter != null) prop.getMethod = getter;
594                     if (setter != null && (ret == Void.TYPE || prop.setMethod==null))
595                         prop.setMethod = setter;
596
597                 }
598             }
599         }
600
601         for (i=0; i<n; i++) {
602             Method JavaDoc method = meths[i];
603
604             if (method.getDeclaringClass() != c ||
605                 Modifier.isStatic(method.getModifiers()))
606             {
607                 continue;
608             }
609
610             String JavaDoc mname = method.getName();
611
612             if (!(mname.startsWith("add") || mname.startsWith("set")) ||
613                 !mname.endsWith("Listener"))
614             {
615                 continue;
616             }
617
618             Class JavaDoc[] args = method.getParameterTypes();
619             Class JavaDoc ret = method.getReturnType();
620             String JavaDoc pname="";
621
622             if (args.length != 1 || ret != Void.TYPE)
623                 continue;
624
625             Class JavaDoc eClass = args[0];
626
627             // This test and call of getClassLoader() function as a
628
// workaround for a bug in MRJ2.2.4. The bug occured when
629
// this program was compiled with jythonc:
630
// import java
631
// print dir(java.awt.Button)
632
// The 'actionPerformed' attributed would be missing.
633
if (eClass.getInterfaces().length > 0)
634                  eClass.getInterfaces()[0].getClassLoader();
635             // And of Mac workaround
636

637             if (!(java.util.EventListener JavaDoc.class.isAssignableFrom(eClass)))
638                 continue;
639
640             String JavaDoc name = eClass.getName();
641             int idot = name.lastIndexOf('.');
642             if (idot != -1)
643                 name = decapitalize(name.substring(idot+1));
644
645             addEvent(name, eClass, method, eClass.getMethods());
646         }
647         /*} catch (Throwable t) {
648           System.err.println("Custom Bean error: "+t);
649           t.printStackTrace();
650           }*/

651     }
652
653      /**
654       * Return the list of all accessible constructors for a class. This
655       * will only the public constructors unless
656       * Options.respectJavaAccessibility is false, in which case all
657       * constructors are returned. Note that constructors are not
658       * inherited like methods or fields.
659       */

660     private static Constructor JavaDoc[] getAccessibleConstructors(Class JavaDoc c) {
661         if (!JavaAccessibility.accessIsMutable())
662             // returns just the public fields
663
return c.getConstructors();
664         // return all constructors
665

666
667         Constructor JavaDoc[] declared = c.getDeclaredConstructors();
668         for (int i=0; i < declared.length; i++) {
669             // TBD: this is a permanent change. Should we provide a way to
670
// restore the original accessibility flag?
671
JavaAccessibility.setAccessible(declared[i], true);
672         }
673         return declared;
674     }
675
676     private boolean ignoreConstructor(Constructor JavaDoc method) {
677         Class JavaDoc[] exceptions = method.getExceptionTypes();
678         for (int j = 0; j < exceptions.length; j++) {
679             if (exceptions[j] == PyIgnoreMethodTag.class) {
680                 return true;
681             }
682         }
683         return false;
684     }
685
686     private void setConstructors(Class JavaDoc c) {
687         if (Modifier.isInterface(c.getModifiers())) {
688             __init__ = null;
689         } else {
690             Constructor JavaDoc[] constructors = getAccessibleConstructors(c);
691             for (int i = 0; i < constructors.length; i++) {
692                 if (ignoreConstructor(constructors[i])) {
693                     continue;
694                 }
695                 if (__init__ == null) {
696                     __init__ = new PyReflectedConstructor(constructors[i]);
697                 } else {
698                     __init__.addConstructor(constructors[i]);
699                 }
700             }
701             if (__init__ != null) {
702                 __dict__.__setitem__("__init__", __init__);
703             }
704         }
705     }
706     private boolean constructorsInitialized=false;
707     synchronized void initConstructors() {
708         if (constructorsInitialized)
709             return;
710         initialize();
711         setConstructors(proxyClass);
712         constructorsInitialized = true;
713     }
714
715     /*
716       If the new name conflicts with a Python keyword, add an '_'
717     */

718     private static java.util.Hashtable JavaDoc keywords=null;
719     private static String JavaDoc unmangleKeyword(String JavaDoc name) {
720         if (keywords == null) {
721             keywords = new java.util.Hashtable JavaDoc();
722             String JavaDoc[] words = new String JavaDoc[]
723             {"or", "and", "not", "is", "in", "lambda", "if", "else", "elif",
724              "while", "for", "try", "except", "def", "class", "finally",
725              "print",
726              "pass", "break", "continue", "return", "import", "from", "del",
727              "raise", "global", "exec", "assert"};
728             for (int i=0; i<words.length; i++) {
729                 keywords.put(words[i]+"_", words[i].intern());
730             }
731         }
732         return (String JavaDoc)keywords.get(name);
733     }
734
735     PyObject[] lookupGivingClass(String JavaDoc name, boolean stop_at_java) {
736         if (stop_at_java)
737             return new PyObject[] {null, null};
738         if (!initialized)
739             initialize();
740         if (name == "__init__") {
741             initConstructors();
742             return new PyObject[] {__init__, null};
743         }
744
745         // For backwards compatibilty, support keyword_ as a substitute for
746
// keyword. An improved parser makes this no longer necessary.
747
if (Options.deprecatedKeywordMangling && name.endsWith("_")) {
748             String JavaDoc newName = unmangleKeyword(name);
749             if (newName != null)
750                 name = newName;
751         }
752         return super.lookupGivingClass(name, stop_at_java);
753     }
754
755     public PyObject __dir__() {
756         initialize();
757         if (__dict__ instanceof PyStringMap) {
758             return ((PyStringMap)__dict__).keys();
759         } else {
760             return __dict__.invoke("keys");
761         }
762     }
763
764     private PyStringMap missingAttributes = null;
765     public PyObject __findattr__(String JavaDoc name) {
766         if (name == "__dict__") {
767             if (__dict__ == null)
768                 initialize();
769             return __dict__;
770         }
771         if (name == "__name__")
772             return new PyString(__name__);
773         if (name == "__bases__") {
774             if (__bases__ == null)
775                 initialize();
776             return __bases__;
777         }
778         if (name == "__init__") {
779             initConstructors();
780             if (__init__ == null)
781                 return super.lookupGivingClass(name, false)[0];
782             return __init__;
783         }
784
785         PyObject result = lookup(name, false);
786         if (result != null)
787             return result.__get__(null, null); // xxx messy
788

789         // A cache of missing attributes to short-circuit later tests
790
if (missingAttributes != null &&
791             missingAttributes.__finditem__(name) != null)
792         {
793             return null;
794         }
795
796         // These two tests can be expensive, see above for short-circuiting
797
result = findClassAttr(name);
798         if (result != null)
799             return result;
800
801         result = findInnerClass(name);
802         if (result != null)
803             return result;
804
805         // Add this attribute to missing attributes cache
806
if (missingAttributes == null) {
807             missingAttributes = new PyStringMap();
808         }
809         missingAttributes.__setitem__(name, this);
810         return null;
811     }
812
813     private PyJavaInstance classInstance;
814     private PyObject findClassAttr(String JavaDoc name) {
815         if (classInstance == null) {
816             classInstance = new PyJavaInstance(proxyClass);
817         }
818         PyObject result = classInstance.__findattr__(name);
819         return result;
820         //if (result == null) return null;
821
//__dict__.__setitem__(name, result);
822
//return result;
823
}
824
825     private PyObject findInnerClass(String JavaDoc name) {
826         Class JavaDoc p = getProxyClass();
827         Class JavaDoc innerClass = Py.relFindClass(p, p.getName()+"$"+name);
828         if (innerClass == null) return null;
829
830         PyObject jinner = Py.java2py(innerClass); // xxx lookup(innerClass);
831
__dict__.__setitem__(name, jinner);
832         return jinner;
833     }
834
835     public void __setattr__(String JavaDoc name, PyObject value) {
836         PyObject field = lookup(name, false);
837         if (field != null) {
838             if (field.jtryset(null, value))
839                 return;
840         }
841         __dict__.__setitem__(name, value);
842     }
843
844     public void __delattr__(String JavaDoc name) {
845         PyObject field = lookup(name, false);
846         if (field == null) {
847             throw Py.NameError("attribute not found: "+name);
848         }
849
850         if (!field.jdontdel()) {
851             __dict__.__delitem__(name);
852         }
853     }
854
855     public PyObject __call__(PyObject[] args, String JavaDoc[] keywords) {
856         if (!constructorsInitialized)
857             initConstructors();
858
859         // xxx instantiation of PyObject subclass, still needed?
860
if (PyObject.class.isAssignableFrom(proxyClass)) {
861             if (Modifier.isAbstract(proxyClass.getModifiers())) {
862                             throw Py.TypeError("can't instantiate abstract class ("+
863                                                __name__+")");
864             }
865             if (__init__ == null) {
866                 throw Py.TypeError("no public constructors for "+
867                                    __name__);
868             }
869             return __init__.make(args,keywords);
870         }
871
872         PyInstance inst = new PyJavaInstance(this);
873         inst.__init__(args, keywords);
874
875         /*if (proxyClass != null &&
876                     PyObject.class.isAssignableFrom(proxyClass)) {
877             // It would be better if we didn't have to create a PyInstance
878             // in the first place.
879             ((PyObject)inst.javaProxy).__class__ = this;
880             return (PyObject)inst.javaProxy;
881         }*/

882
883         return inst;
884     }
885
886     public Object JavaDoc __tojava__(Class JavaDoc c) {
887         initialize();
888         return super.__tojava__(c);
889     }
890
891     public String JavaDoc toString() {
892         return "<jclass "+__name__+" "+Py.idstr(this)+">";
893     }
894 }
895
Popular Tags