// Copyright (c) Corporation for National Research Initiatives package org.python.core; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; import java.lang.InstantiationException; public class PyReflectedConstructor extends PyReflectedFunction { public PyReflectedConstructor(String name) { super(name); __name__ = name; argslist = new ReflectedArgs[1]; nargs = 0; } public PyReflectedConstructor(Constructor c) { this(c.getDeclaringClass().getName()); addConstructor(c); } private ReflectedArgs makeArgs(Constructor m) { return new ReflectedArgs(m, m.getParameterTypes(), m.getDeclaringClass(), true); } public void addConstructor(Constructor m) { int mods = m.getModifiers(); // Only add public methods unless we're overriding if (!Modifier.isPublic(mods) && !JavaAccessibility.accessIsMutable()) return; addArgs(makeArgs(m)); } // xxx temporary solution, type ctr will go through __new__ ... PyObject make(PyObject[] args, String[] keywords) { ReflectedArgs[] argsl = argslist; ReflectedCallData callData = new ReflectedCallData(); Object method = null; boolean consumes_keywords = false; int n = nargs; int nkeywords = keywords.length; PyObject[] allArgs = null; // Check for a matching constructor to call if (n > 0) { // PyArgsKeywordsCall signature, if present, is the first if (argsl[0].matches(null, args, keywords, callData)) { method = argsl[0].data; consumes_keywords = argsl[0].flags == ReflectedArgs.PyArgsKeywordsCall; } else { allArgs = args; int i = 1; if (nkeywords > 0) { args = new PyObject[allArgs.length - nkeywords]; System.arraycopy(allArgs, 0, args, 0, args.length); i = 0; } for (; i < n; i++) { ReflectedArgs rargs = argsl[i]; if (rargs.matches(null, args, Py.NoKeywords, callData)) { method = rargs.data; break; } } } } // Throw an error if no valid set of arguments if (method == null) { throwError(callData.errArg, args.length, true /*xxx?*/, false); } // Do the actual constructor call PyObject obj = null; Constructor ctor = (Constructor) method; try { obj = (PyObject) ctor.newInstance(callData.getArgsArray()); } catch (Throwable t) { throw Py.JavaError(t); } if (!consumes_keywords) { int offset = args.length; for (int i = 0; i < nkeywords; i++) { obj.__setattr__(keywords[i], allArgs[i + offset]); } } return obj; } public PyObject __call__(PyObject self, PyObject[] args, String[] keywords) { ReflectedArgs[] argsl = argslist; if (self == null || !(self instanceof PyInstance)) { throw Py.TypeError("invalid self argument to constructor"); } PyInstance iself = (PyInstance) self; Class javaClass = iself.instclass.proxyClass; //Class[] javaClasses = iself.__class__.proxyClasses; //int myIndex = -1; boolean proxyConstructor = false; Class declaringClass = argsl[0].declaringClass; // If this is the constructor for a proxy class or not... if (PyProxy.class.isAssignableFrom(declaringClass)) { // if (self instanceof PyJavaInstance) { // throw Py.TypeError( // "invalid self argument to proxy constructor"); // } } else { if (!(iself instanceof PyJavaInstance)) { // Get proxy constructor and call it if (declaringClass.isAssignableFrom(javaClass)) { proxyConstructor = true; } else { throw Py.TypeError("invalid self argument"); } PyJavaClass jc = PyJavaClass.lookup(javaClass); // xxx jc.initConstructors(); return jc.__init__.__call__(iself, args, keywords); } } if (declaringClass.isAssignableFrom(javaClass)) { proxyConstructor = true; } else { throw Py.TypeError("self invalid - must implement: " + declaringClass.getName()); } if (iself.javaProxy != null) { Class sup = iself.instclass.proxyClass; if (PyProxy.class.isAssignableFrom(sup)) sup = sup.getSuperclass(); throw Py.TypeError("instance already instantiated for " + sup.getName()); } ReflectedCallData callData = new ReflectedCallData(); Object method = null; // Remove keyword args int nkeywords = keywords.length; PyObject[] allArgs = args; if (nkeywords > 0) { args = new PyObject[allArgs.length - nkeywords]; System.arraycopy(allArgs, 0, args, 0, args.length); } // Check for a matching constructor to call int n = nargs; for (int i = 0; i < n; i++) { ReflectedArgs rargs = argsl[i]; if (rargs.matches(null, args, Py.NoKeywords, callData)) { method = rargs.data; break; } } // Throw an error if no valid set of arguments if (method == null) { throwError(callData.errArg, args.length, self != null, false); } // Do the actual constructor call Object jself = null; ThreadState ts = Py.getThreadState(); try { ts.pushInitializingProxy(iself); Constructor ctor = (Constructor) method; try { jself = ctor.newInstance(callData.getArgsArray()); } catch (InvocationTargetException e) { if (e.getTargetException() instanceof InstantiationException) { Class sup = iself.instclass.proxyClass.getSuperclass(); String msg = "Constructor failed for Java superclass"; if (sup != null) msg += " " + sup.getName(); throw Py.TypeError(msg); } else throw Py.JavaError(e); } catch (Throwable t) { throw Py.JavaError(t); } } finally { ts.popInitializingProxy(); } iself.javaProxy = jself; // Do setattr's for keyword args int offset = args.length; for (int i = 0; i < nkeywords; i++) { iself.__setattr__(keywords[i], allArgs[i + offset]); } return Py.None; } public PyObject __call__(PyObject[] args, String[] keywords) { if (args.length < 1) { throw Py.TypeError("constructor requires self argument"); } PyObject[] newArgs = new PyObject[args.length - 1]; System.arraycopy(args, 1, newArgs, 0, newArgs.length); return __call__(args[0], newArgs, keywords); } public String toString() { //printArgs(); return "<java constructor " + __name__ + " " + Py.idstr(this) + ">"; } }