001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: import java.lang.reflect.Constructor;
005: import java.lang.reflect.Modifier;
006: import java.lang.reflect.InvocationTargetException;
007: import java.lang.InstantiationException;
008:
009: public class PyReflectedConstructor extends PyReflectedFunction {
010:
011: public PyReflectedConstructor(String name) {
012: super (name);
013: __name__ = name;
014: argslist = new ReflectedArgs[1];
015: nargs = 0;
016: }
017:
018: public PyReflectedConstructor(Constructor c) {
019: this (c.getDeclaringClass().getName());
020: addConstructor(c);
021: }
022:
023: private ReflectedArgs makeArgs(Constructor m) {
024: return new ReflectedArgs(m, m.getParameterTypes(), m
025: .getDeclaringClass(), true);
026: }
027:
028: public void addConstructor(Constructor m) {
029: int mods = m.getModifiers();
030: // Only add public methods unless we're overriding
031: if (!Modifier.isPublic(mods)
032: && !JavaAccessibility.accessIsMutable())
033: return;
034: addArgs(makeArgs(m));
035: }
036:
037: // xxx temporary solution, type ctr will go through __new__ ...
038: PyObject make(PyObject[] args, String[] keywords) {
039: ReflectedArgs[] argsl = argslist;
040:
041: ReflectedCallData callData = new ReflectedCallData();
042: Object method = null;
043: boolean consumes_keywords = false;
044: int n = nargs;
045: int nkeywords = keywords.length;
046: PyObject[] allArgs = null;
047:
048: // Check for a matching constructor to call
049: if (n > 0) { // PyArgsKeywordsCall signature, if present, is the first
050: if (argsl[0].matches(null, args, keywords, callData)) {
051: method = argsl[0].data;
052: consumes_keywords = argsl[0].flags == ReflectedArgs.PyArgsKeywordsCall;
053: } else {
054: allArgs = args;
055: int i = 1;
056: if (nkeywords > 0) {
057: args = new PyObject[allArgs.length - nkeywords];
058: System.arraycopy(allArgs, 0, args, 0, args.length);
059: i = 0;
060: }
061: for (; i < n; i++) {
062: ReflectedArgs rargs = argsl[i];
063: if (rargs.matches(null, args, Py.NoKeywords,
064: callData)) {
065: method = rargs.data;
066: break;
067: }
068: }
069: }
070: }
071:
072: // Throw an error if no valid set of arguments
073: if (method == null) {
074: throwError(callData.errArg, args.length, true /*xxx?*/,
075: false);
076: }
077:
078: // Do the actual constructor call
079: PyObject obj = null;
080: Constructor ctor = (Constructor) method;
081: try {
082: obj = (PyObject) ctor.newInstance(callData.getArgsArray());
083: } catch (Throwable t) {
084: throw Py.JavaError(t);
085: }
086:
087: if (!consumes_keywords) {
088: int offset = args.length;
089: for (int i = 0; i < nkeywords; i++) {
090: obj.__setattr__(keywords[i], allArgs[i + offset]);
091: }
092: }
093:
094: return obj;
095: }
096:
097: public PyObject __call__(PyObject self, PyObject[] args,
098: String[] keywords) {
099: ReflectedArgs[] argsl = argslist;
100:
101: if (self == null || !(self instanceof PyInstance)) {
102: throw Py.TypeError("invalid self argument to constructor");
103: }
104:
105: PyInstance iself = (PyInstance) self;
106: Class javaClass = iself.instclass.proxyClass;
107: //Class[] javaClasses = iself.__class__.proxyClasses;
108: //int myIndex = -1;
109: boolean proxyConstructor = false;
110: Class declaringClass = argsl[0].declaringClass;
111:
112: // If this is the constructor for a proxy class or not...
113: if (PyProxy.class.isAssignableFrom(declaringClass)) {
114: // if (self instanceof PyJavaInstance) {
115: // throw Py.TypeError(
116: // "invalid self argument to proxy constructor");
117: // }
118: } else {
119: if (!(iself instanceof PyJavaInstance)) {
120: // Get proxy constructor and call it
121: if (declaringClass.isAssignableFrom(javaClass)) {
122: proxyConstructor = true;
123: } else {
124: throw Py.TypeError("invalid self argument");
125: }
126:
127: PyJavaClass jc = PyJavaClass.lookup(javaClass); // xxx
128: jc.initConstructors();
129: return jc.__init__.__call__(iself, args, keywords);
130: }
131: }
132:
133: if (declaringClass.isAssignableFrom(javaClass)) {
134: proxyConstructor = true;
135: } else {
136: throw Py.TypeError("self invalid - must implement: "
137: + declaringClass.getName());
138: }
139:
140: if (iself.javaProxy != null) {
141: Class sup = iself.instclass.proxyClass;
142: if (PyProxy.class.isAssignableFrom(sup))
143: sup = sup.getSuperclass();
144: throw Py.TypeError("instance already instantiated for "
145: + sup.getName());
146: }
147:
148: ReflectedCallData callData = new ReflectedCallData();
149: Object method = null;
150:
151: // Remove keyword args
152: int nkeywords = keywords.length;
153: PyObject[] allArgs = args;
154: if (nkeywords > 0) {
155: args = new PyObject[allArgs.length - nkeywords];
156: System.arraycopy(allArgs, 0, args, 0, args.length);
157: }
158:
159: // Check for a matching constructor to call
160: int n = nargs;
161: for (int i = 0; i < n; i++) {
162: ReflectedArgs rargs = argsl[i];
163: if (rargs.matches(null, args, Py.NoKeywords, callData)) {
164: method = rargs.data;
165: break;
166: }
167: }
168:
169: // Throw an error if no valid set of arguments
170: if (method == null) {
171: throwError(callData.errArg, args.length, self != null,
172: false);
173: }
174:
175: // Do the actual constructor call
176: Object jself = null;
177: ThreadState ts = Py.getThreadState();
178: try {
179: ts.pushInitializingProxy(iself);
180: Constructor ctor = (Constructor) method;
181: try {
182: jself = ctor.newInstance(callData.getArgsArray());
183: } catch (InvocationTargetException e) {
184: if (e.getTargetException() instanceof InstantiationException) {
185: Class sup = iself.instclass.proxyClass
186: .getSuperclass();
187: String msg = "Constructor failed for Java superclass";
188: if (sup != null)
189: msg += " " + sup.getName();
190: throw Py.TypeError(msg);
191: } else
192: throw Py.JavaError(e);
193: } catch (Throwable t) {
194: throw Py.JavaError(t);
195: }
196: } finally {
197: ts.popInitializingProxy();
198: }
199:
200: iself.javaProxy = jself;
201:
202: // Do setattr's for keyword args
203: int offset = args.length;
204: for (int i = 0; i < nkeywords; i++) {
205: iself.__setattr__(keywords[i], allArgs[i + offset]);
206: }
207: return Py.None;
208: }
209:
210: public PyObject __call__(PyObject[] args, String[] keywords) {
211: if (args.length < 1) {
212: throw Py.TypeError("constructor requires self argument");
213: }
214: PyObject[] newArgs = new PyObject[args.length - 1];
215: System.arraycopy(args, 1, newArgs, 0, newArgs.length);
216:
217: return __call__(args[0], newArgs, keywords);
218: }
219:
220: public String toString() {
221: //printArgs();
222: return "<java constructor " + __name__ + " " + Py.idstr(this )
223: + ">";
224: }
225: }
|