From: <cg...@us...> - 2008-11-30 02:30:48
|
Revision: 5663 http://jython.svn.sourceforge.net/jython/?rev=5663&view=rev Author: cgroves Date: 2008-11-30 02:30:42 +0000 (Sun, 30 Nov 2008) Log Message: ----------- Hook bean events up in PyJavaType. All of test_java_integration passes again. Modified Paths: -------------- branches/newstyle-java-types/src/org/python/core/PyBeanEvent.java branches/newstyle-java-types/src/org/python/core/PyBeanEventProperty.java branches/newstyle-java-types/src/org/python/core/PyCompoundCallable.java branches/newstyle-java-types/src/org/python/core/PyException.java branches/newstyle-java-types/src/org/python/core/PyJavaType.java Modified: branches/newstyle-java-types/src/org/python/core/PyBeanEvent.java =================================================================== --- branches/newstyle-java-types/src/org/python/core/PyBeanEvent.java 2008-11-30 00:40:22 UTC (rev 5662) +++ branches/newstyle-java-types/src/org/python/core/PyBeanEvent.java 2008-11-30 02:30:42 UTC (rev 5663) @@ -1,13 +1,17 @@ // Copyright (c) Corporation for National Research Initiatives package org.python.core; + import java.lang.reflect.Method; -public class PyBeanEvent extends PyObject { +public class PyBeanEvent<T> extends PyObject { + public Method addMethod; - public Class eventClass; + + public Class<T> eventClass; + public String __name__; - public PyBeanEvent(String name, Class eventClass, Method addMethod) { + public PyBeanEvent(String name, Class<T> eventClass, Method addMethod) { __name__ = name.intern(); this.addMethod = addMethod; this.eventClass = eventClass; @@ -17,16 +21,15 @@ throw Py.TypeError("write only attribute"); } - boolean _jdontdel() { + boolean jdontdel() { throw Py.TypeError("can't delete this attribute"); } public boolean _doset(PyObject self, PyObject value) { Object jself = Py.tojava(self, addMethod.getDeclaringClass()); - Object jvalue = Py.tojava(value, eventClass); - + T jvalue = Py.tojava(value, eventClass); try { - addMethod.invoke(jself, new Object[] {jvalue}); + addMethod.invoke(jself, jvalue); } catch (Exception e) { throw Py.JavaError(e); } Modified: branches/newstyle-java-types/src/org/python/core/PyBeanEventProperty.java =================================================================== --- branches/newstyle-java-types/src/org/python/core/PyBeanEventProperty.java 2008-11-30 00:40:22 UTC (rev 5662) +++ branches/newstyle-java-types/src/org/python/core/PyBeanEventProperty.java 2008-11-30 02:30:42 UTC (rev 5663) @@ -9,16 +9,29 @@ import org.python.util.Generic; -public class PyBeanEventProperty extends PyReflectedField -{ +public class PyBeanEventProperty extends PyReflectedField { + + private static Map<String, Class<?>> adapterClasses = Generic.map(); + + private static Map<Object, Map<String, WeakReference<Object>>> adapters = + new WeakHashMap<Object, Map<String, WeakReference<Object>>>(); + public Method addMethod; + public String eventName; - public Class eventClass; + + public Class<?> eventClass; + public String __name__; - public PyBeanEventProperty(String eventName, Class eventClass, - Method addMethod, Method eventMethod) - { + private Field adapterField; + + private Class<?> adapterClass; + + public PyBeanEventProperty(String eventName, + Class<?> eventClass, + Method addMethod, + Method eventMethod) { __name__ = eventMethod.getName().intern(); this.addMethod = addMethod; this.eventName = eventName; @@ -26,47 +39,50 @@ } public PyObject _doget(PyObject self) { - if (self == null) + if (self == null) { return this; - + } initAdapter(); - Object jself = Py.tojava(self, addMethod.getDeclaringClass()); - Object field; try { field = adapterField.get(getAdapter(jself)); } catch (Exception exc) { throw Py.JavaError(exc); } - PyCompoundCallable func; if (field == null) { func = new PyCompoundCallable(); setFunction(jself, func); return func; } - if (field instanceof PyCompoundCallable) + if (field instanceof PyCompoundCallable) { return (PyCompoundCallable)field; - + } func = new PyCompoundCallable(); setFunction(jself, func); func.append((PyObject)field); return func; } - private synchronized static Class<?> getAdapterClass(Class<?> c) { - Class<?> pc = Py.findClass("org.python.proxies." + c.getName() + "$Adapter"); - if (pc == null) { - pc = MakeProxies.makeAdapter(c); + public boolean _doset(PyObject self, PyObject value) { + Object jself = Py.tojava(self, addMethod.getDeclaringClass()); + if (!(value instanceof PyCompoundCallable)) { + PyCompoundCallable func = new PyCompoundCallable(); + setFunction(jself, func); + func.append(value); + } else { + setFunction(jself, value); } - return pc; + return true; } - protected Map<Object, Map<String, WeakReference<Object>>> adapters = - new WeakHashMap<Object, Map<String, WeakReference<Object>>>(); + public String toString() { + return "<beanEventProperty " + __name__ + " for event " + eventClass.toString() + " " + + Py.idstr(this) + ">"; + } - protected Object getAdapter(Object o, String evc) { + private Object getAdapter(Object o, String evc) { Map<String, WeakReference<Object>> ads = adapters.get(o); if (ads == null) { return null; @@ -78,9 +94,9 @@ return adw.get(); } - protected void putAdapter(Object o, String evc, Object ad) { + private void putAdapter(Object o, String evc, Object ad) { Map<String, WeakReference<Object>> ads = adapters.get(o); - if(ads == null) { + if (ads == null) { ads = Generic.map(); adapters.put(o, ads); } @@ -90,11 +106,12 @@ private synchronized Object getAdapter(Object self) { String eventClassName = eventClass.getName(); Object adapter = getAdapter(self, eventClassName); - if (adapter != null) + if (adapter != null) { return adapter; + } try { adapter = adapterClass.newInstance(); - addMethod.invoke(self, new Object[] {adapter}); + addMethod.invoke(self, adapter); } catch (Exception e) { throw Py.JavaError(e); } @@ -102,14 +119,9 @@ return adapter; } - private Field adapterField; - private Class adapterClass; - private void initAdapter() { if (adapterClass == null) { adapterClass = getAdapterClass(eventClass); - } - if (adapterField == null) { try { adapterField = adapterClass.getField(__name__); } catch (NoSuchFieldException exc) { @@ -127,20 +139,16 @@ } } - public boolean _doset(PyObject self, PyObject value) { - Object jself = Py.tojava(self, addMethod.getDeclaringClass()); - if (!(value instanceof PyCompoundCallable)) { - PyCompoundCallable func = new PyCompoundCallable(); - setFunction(jself, func); - func.append(value); - } else { - setFunction(jself, value); + private synchronized static Class<?> getAdapterClass(Class<?> c) { + String name = "org.python.proxies." + c.getName() + "$Adapter"; + Class<?> pc = Py.findClass(name); + if (pc == null) { + pc = adapterClasses.get(name); + if (pc == null) { + pc = MakeProxies.makeAdapter(c); + adapterClasses.put(name, pc); + } } - return true; + return pc; } - - public String toString() { - return "<beanEventProperty "+__name__+" for event "+ - eventClass.toString()+" "+Py.idstr(this)+">"; - } } Modified: branches/newstyle-java-types/src/org/python/core/PyCompoundCallable.java =================================================================== --- branches/newstyle-java-types/src/org/python/core/PyCompoundCallable.java 2008-11-30 00:40:22 UTC (rev 5662) +++ branches/newstyle-java-types/src/org/python/core/PyCompoundCallable.java 2008-11-30 02:30:42 UTC (rev 5663) @@ -1,36 +1,34 @@ // Copyright (c) Corporation for National Research Initiatives package org.python.core; -import java.util.Vector; +import java.util.List; + +import org.python.util.Generic; + public class PyCompoundCallable extends PyObject { - private Vector callables; - private PySystemState systemState; - public PyCompoundCallable () { - callables = new Vector(); - systemState = Py.getSystemState(); - } + private List<PyObject> callables = Generic.list(); + private PySystemState systemState = Py.getSystemState(); + public void append(PyObject callable) { - callables.addElement(callable); + callables.add(callable); } public void clear() { - callables.removeAllElements(); + callables.clear(); } public PyObject __call__(PyObject[] args, String[] keywords) { // Set the system state to handle callbacks from java threads Py.setSystemState(systemState); - int n = callables.size(); - //System.out.println("callable: "+n); - for (int i=0; i<n; i++) { - ((PyObject)callables.elementAt(i)).__call__(args, keywords); + for (PyObject callable : callables) { + callable.__call__(args, keywords); } return Py.None; } public String toString() { - return "<CompoundCallable with "+callables.size()+" callables>"; + return "<CompoundCallable with " + callables.size() + " callables>"; } } Modified: branches/newstyle-java-types/src/org/python/core/PyException.java =================================================================== --- branches/newstyle-java-types/src/org/python/core/PyException.java 2008-11-30 00:40:22 UTC (rev 5662) +++ branches/newstyle-java-types/src/org/python/core/PyException.java 2008-11-30 02:30:42 UTC (rev 5663) @@ -65,12 +65,9 @@ public void printStackTrace() { Py.printException(this); } - + public Throwable fillInStackTrace() { - if (Options.includeJavaStackInExceptions) - return super.fillInStackTrace(); - else - return this; + return Options.includeJavaStackInExceptions ? super.fillInStackTrace() : this; } public synchronized void printStackTrace(PrintStream s) { Modified: branches/newstyle-java-types/src/org/python/core/PyJavaType.java =================================================================== --- branches/newstyle-java-types/src/org/python/core/PyJavaType.java 2008-11-30 00:40:22 UTC (rev 5662) +++ branches/newstyle-java-types/src/org/python/core/PyJavaType.java 2008-11-30 02:30:42 UTC (rev 5663) @@ -7,6 +7,7 @@ import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Enumeration; +import java.util.EventListener; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -18,138 +19,8 @@ private final static Class<?>[] OO = {PyObject.class, PyObject.class}; + private static Map<Class<?>, PyBuiltinMethod[]> collectionProxies; - class EnumerationIter extends PyIterator { - - private Enumeration<Object> proxy; - - public EnumerationIter(Enumeration<Object> proxy) { - this.proxy = proxy; - } - - public PyObject __iternext__() { - return proxy.hasMoreElements() ? Py.java2py(proxy.nextElement()) : null; - } - } - - private static class IteratorIter extends PyIterator { - - private Iterator<Object> proxy; - - public IteratorIter(Iterator<Object> proxy) { - this.proxy = proxy; - } - - public PyObject __iternext__() { - return proxy.hasNext() ? Py.java2py(proxy.next()) : null; - } - } - - static Map<Class<?>, PyBuiltinMethod[]> _collectionProxies; - - protected static class ListMethod extends PyBuiltinMethodNarrow { - protected ListMethod(String name, int minArgs, int maxArgs) { - super(name, minArgs, maxArgs); - } - - protected List<Object> asList(){ - return (List<Object>)self.getJavaProxy(); - } - } - protected static class MapMethod extends PyBuiltinMethodNarrow { - protected MapMethod(String name, int minArgs, int maxArgs) { - super(name, minArgs, maxArgs); - } - - protected Map<Object, Object> asMap(){ - return (Map<Object, Object>)self.getJavaProxy(); - } - } - - public static Map<Class<?>, PyBuiltinMethod[]> getCollectionProxies() { - if (_collectionProxies == null) { - _collectionProxies = Generic.map(); - - PyBuiltinMethodNarrow lenProxy = new PyBuiltinMethodNarrow("__len__", 0, 0) { - @Override - public PyObject __call__() { - return Py.newInteger(((Collection<?>)self.getJavaProxy()).size()); - } - }; - - PyBuiltinMethodNarrow mapGetProxy = new MapMethod("__getitem__", 1, 1) { - @Override - public PyObject __call__(PyObject key) { - return Py.java2py(asMap().get(Py.tojava(key, Object.class))); - } - }; - - PyBuiltinMethodNarrow mapPutProxy = new MapMethod("__setitem__", 2, 2) { - @Override - public PyObject __call__(PyObject key, PyObject value) { - return Py.java2py(asMap().put(Py.tojava(key, Object.class), - Py.tojava(value, Object.class))); - } - }; - - PyBuiltinMethodNarrow mapRemoveProxy = new MapMethod("__delitem__", 1, 1) { - @Override - public PyObject __call__(PyObject key, PyObject value) { - return Py.java2py(asMap().remove(Py.tojava(key, Object.class))); - } - }; - - PyBuiltinMethodNarrow listGetProxy = new ListMethod("__getitem__", 1, 1) { - @Override - public PyObject __call__(PyObject key) { - if (key instanceof PyInteger) { - return Py.java2py(asList().get(((PyInteger)key).getValue())); - } else { - throw Py.TypeError("only integer keys accepted"); - } - } - }; - - PyBuiltinMethodNarrow listSetProxy = new ListMethod("__setitem__", 2, 2) { - @Override - public PyObject __call__(PyObject key, PyObject value) { - if (key instanceof PyInteger) { - asList().set(((PyInteger)key).getValue(), Py.tojava(value, Object.class)); - } else { - throw Py.TypeError("only integer keys accepted"); - } - return Py.None; - } - }; - - PyBuiltinMethodNarrow listRemoveProxy = new ListMethod("__delitem__", 1, 1) { - @Override - public PyObject __call__(PyObject key, PyObject value) { - if (key instanceof PyInteger) { - return Py.java2py(asList().remove(((PyInteger)key).getValue())); - } else { - throw Py.TypeError("only integer keys accepted"); - } - } - }; - - PyBuiltinMethodNarrow iterableProxy = new PyBuiltinMethodNarrow("__iter__", 0, 0) { - public PyObject __call__() { - return new IteratorIter(((Iterable)self.getJavaProxy()).iterator()); - } - }; - _collectionProxies.put(Iterable.class, new PyBuiltinMethod[] {iterableProxy}); - _collectionProxies.put(Collection.class, new PyBuiltinMethod[] {lenProxy}); - _collectionProxies.put(Map.class, new PyBuiltinMethod[] {mapGetProxy, - mapPutProxy, - mapRemoveProxy}); - _collectionProxies.put(List.class, new PyBuiltinMethod[] {listGetProxy, - listSetProxy, - listRemoveProxy}); - } - return _collectionProxies; - } - public static PyObject wrapJavaObject(Object o) { PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass())); obj.javaProxy = o; @@ -172,6 +43,7 @@ // Add methods and determine bean properties declared on this class Map<String, PyBeanProperty> props = Generic.map(); + Map<String, PyBeanEvent> events = Generic.map(); for (Method meth : underlying_class.getMethods()) { if (!declaredOnMember(base, meth) || ignore(meth)) { continue; @@ -184,34 +56,54 @@ } else { reflfunc.addMethod(meth); } - if (!Modifier.isStatic(meth.getModifiers())) { - // check for xxxX.* - int n = meth.getParameterTypes().length; - String name = null; - boolean get = true; - if (methname.startsWith("get") && methname.length() > 3 && n == 0) { - name = methname.substring(3); - } else if (methname.startsWith("is") && methname.length() > 2 && n == 0 - && meth.getReturnType() == Boolean.TYPE) { - name = methname.substring(2); - } else if (methname.startsWith("set") && methname.length() > 3 && n == 1) { - name = methname.substring(3); - get = false; + + // Now check if this is a bean method, for which it must be an instance method + if (Modifier.isStatic(meth.getModifiers())) { + continue; + } + + // First check if this is a bean event addition method + int n = meth.getParameterTypes().length; + if ((methname.startsWith("add") || methname.startsWith("set")) + && methname.endsWith("Listener") && n == 1 && + meth.getReturnType() == Void.TYPE && + EventListener.class.isAssignableFrom(meth.getParameterTypes()[0])) { + Class<?> eventClass = meth.getParameterTypes()[0]; + String ename = eventClass.getName(); + int idot = ename.lastIndexOf('.'); + if (idot != -1) { + ename = ename.substring(idot + 1); } - if (name != null) { - name = normalize(StringUtil.decapitalize(name)); - PyBeanProperty prop = props.get(name); - if (prop == null) { - prop = new PyBeanProperty(name, null, null, null); - props.put(name, prop); - } - if (get) { - prop.getMethod = meth; - prop.myType = meth.getReturnType(); - } else { - prop.setMethod = meth; - } + ename = normalize(StringUtil.decapitalize(ename)); + events.put(ename, new PyBeanEvent(name, eventClass, meth)); + continue; + } + + // Now check if it's a bean property accessor + String name = null; + boolean get = true; + if (methname.startsWith("get") && methname.length() > 3 && n == 0) { + name = methname.substring(3); + } else if (methname.startsWith("is") && methname.length() > 2 && n == 0 + && meth.getReturnType() == Boolean.TYPE) { + name = methname.substring(2); + } else if (methname.startsWith("set") && methname.length() > 3 && n == 1) { + name = methname.substring(3); + get = false; + } + if (name != null) { + name = normalize(StringUtil.decapitalize(name)); + PyBeanProperty prop = props.get(name); + if (prop == null) { + prop = new PyBeanProperty(name, null, null, null); + props.put(name, prop); } + if (get) { + prop.getMethod = meth; + prop.myType = meth.getReturnType(); + } else { + prop.setMethod = meth; + } } } @@ -251,6 +143,23 @@ } } + for (PyBeanEvent ev : events.values()) { + if (dict.__finditem__(ev.__name__) == null) { + dict.__setitem__(ev.__name__, ev); + } + + for (Method meth : ev.eventClass.getMethods()) { + String name = meth.getName().intern(); + if (dict.__finditem__(name) != null) { + continue; + } + dict.__setitem__(name, new PyBeanEventProperty(name, + ev.eventClass, + ev.addMethod, + meth)); + } + } + // Fill in the bean properties picked up while going through the methods for (PyBeanProperty prop : props.values()) { PyObject prev = dict.__finditem__(prop.__name__); @@ -362,4 +271,134 @@ } return false; } + + private class EnumerationIter extends PyIterator { + + private Enumeration<Object> proxy; + + public EnumerationIter(Enumeration<Object> proxy) { + this.proxy = proxy; + } + + public PyObject __iternext__() { + return proxy.hasMoreElements() ? Py.java2py(proxy.nextElement()) : null; + } + } + + private static class IteratorIter extends PyIterator { + + private Iterator<Object> proxy; + + public IteratorIter(Iterator<Object> proxy) { + this.proxy = proxy; + } + + public PyObject __iternext__() { + return proxy.hasNext() ? Py.java2py(proxy.next()) : null; + } + } + + private static class ListMethod extends PyBuiltinMethodNarrow { + protected ListMethod(String name, int minArgs, int maxArgs) { + super(name, minArgs, maxArgs); + } + + protected List<Object> asList(){ + return (List<Object>)self.getJavaProxy(); + } + } + + private static class MapMethod extends PyBuiltinMethodNarrow { + protected MapMethod(String name, int minArgs, int maxArgs) { + super(name, minArgs, maxArgs); + } + + protected Map<Object, Object> asMap(){ + return (Map<Object, Object>)self.getJavaProxy(); + } + } + + private static Map<Class<?>, PyBuiltinMethod[]> getCollectionProxies() { + if (collectionProxies == null) { + collectionProxies = Generic.map(); + + PyBuiltinMethodNarrow lenProxy = new PyBuiltinMethodNarrow("__len__", 0, 0) { + @Override + public PyObject __call__() { + return Py.newInteger(((Collection<?>)self.getJavaProxy()).size()); + } + }; + + PyBuiltinMethodNarrow mapGetProxy = new MapMethod("__getitem__", 1, 1) { + @Override + public PyObject __call__(PyObject key) { + return Py.java2py(asMap().get(Py.tojava(key, Object.class))); + } + }; + + PyBuiltinMethodNarrow mapPutProxy = new MapMethod("__setitem__", 2, 2) { + @Override + public PyObject __call__(PyObject key, PyObject value) { + return Py.java2py(asMap().put(Py.tojava(key, Object.class), + Py.tojava(value, Object.class))); + } + }; + + PyBuiltinMethodNarrow mapRemoveProxy = new MapMethod("__delitem__", 1, 1) { + @Override + public PyObject __call__(PyObject key, PyObject value) { + return Py.java2py(asMap().remove(Py.tojava(key, Object.class))); + } + }; + + PyBuiltinMethodNarrow listGetProxy = new ListMethod("__getitem__", 1, 1) { + @Override + public PyObject __call__(PyObject key) { + if (key instanceof PyInteger) { + return Py.java2py(asList().get(((PyInteger)key).getValue())); + } else { + throw Py.TypeError("only integer keys accepted"); + } + } + }; + + PyBuiltinMethodNarrow listSetProxy = new ListMethod("__setitem__", 2, 2) { + @Override + public PyObject __call__(PyObject key, PyObject value) { + if (key instanceof PyInteger) { + asList().set(((PyInteger)key).getValue(), Py.tojava(value, Object.class)); + } else { + throw Py.TypeError("only integer keys accepted"); + } + return Py.None; + } + }; + + PyBuiltinMethodNarrow listRemoveProxy = new ListMethod("__delitem__", 1, 1) { + @Override + public PyObject __call__(PyObject key, PyObject value) { + if (key instanceof PyInteger) { + return Py.java2py(asList().remove(((PyInteger)key).getValue())); + } else { + throw Py.TypeError("only integer keys accepted"); + } + } + }; + + PyBuiltinMethodNarrow iterableProxy = new PyBuiltinMethodNarrow("__iter__", 0, 0) { + public PyObject __call__() { + return new IteratorIter(((Iterable)self.getJavaProxy()).iterator()); + } + }; + collectionProxies.put(Iterable.class, new PyBuiltinMethod[] {iterableProxy}); + collectionProxies.put(Collection.class, new PyBuiltinMethod[] {lenProxy}); + collectionProxies.put(Map.class, new PyBuiltinMethod[] {mapGetProxy, + mapPutProxy, + mapRemoveProxy}); + collectionProxies.put(List.class, new PyBuiltinMethod[] {listGetProxy, + listSetProxy, + listRemoveProxy}); + } + return collectionProxies; + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |