001: /*
002: * $Id: Reflection.java,v 1.10 2002/09/16 08:05:03 jkl Exp $
003: *
004: * Copyright (c) 2002 Njet Communications Ltd. All Rights Reserved.
005: *
006: * Use is subject to license terms, as defined in
007: * Anvil Sofware License, Version 1.1. See LICENSE
008: * file, or http://njet.org/license-1.1.txt
009: */
010: package anvil.core.reflect;
011:
012: import java.lang.reflect.Array;
013: import java.lang.reflect.Field;
014: import java.lang.reflect.Method;
015: import java.lang.reflect.Modifier;
016: import java.lang.reflect.Constructor;
017: import java.util.Enumeration;
018: import anvil.core.Any;
019: import anvil.core.AnyClass;
020: import anvil.core.AnyAbstractClass;
021: import anvil.core.ObjectPool;
022: import anvil.core.Register;
023: import anvil.java.util.Hashlist;
024: import anvil.java.util.BindingEnumeration;
025: import anvil.script.Context;
026: import anvil.script.Type;
027: import anvil.script.ClassDispatcher;
028: import anvil.script.ClassType;
029: import anvil.script.InterfaceType;
030: import anvil.script.InterfaceRef;
031: import anvil.script.ClassRef;
032: import anvil.script.ConstantVariableType;
033: import anvil.script.StaticVariableType;
034: import anvil.script.VariableType;
035: import anvil.script.Scope;
036: import anvil.script.ScriptException;
037: import anvil.script.ReflectedJava;
038: import anvil.script.CompilableFunction;
039: import anvil.script.compiler.ResolvedClassRef;
040: import anvil.script.compiler.ResolvedInterfaceRef;
041: import anvil.doc.Doc;
042:
043: public class Reflection extends AnyAbstractClass implements ClassType,
044: InterfaceType, ParameterTypes, ReflectedJava {
045:
046: private PackageReflection _parent;
047: private ClassRef _super ref = null;
048: private Reflection _super = null;
049: private String _name;
050: private Class _class;
051: private int _arraytype = -1;
052: private InterfaceRef[] _interfaces;
053: private InterfaceRef[] _bases;
054: private ConstructorTree _ctor = null;
055: private Hashlist _declarations = new Hashlist();
056: private Hashlist _methods = new Hashlist();
057:
058: public Reflection() {
059: }
060:
061: public Reflection(Class cls) {
062: initialize(cls);
063: }
064:
065: public void initialize(Class cls)
066: {
067: _name = cls.getName();
068: _class = cls;
069: _parent = ObjectPool.createReflection(cls.getPackage());
070: _parent.addClass(this );
071: if (cls.isArray()) {
072: Class elemtype = cls.getComponentType();
073: if (elemtype == Boolean.TYPE) {
074: _arraytype = BOOLEAN;
075: } else if (elemtype == Byte.TYPE) {
076: _arraytype = BYTE;
077: } else if (elemtype == Short.TYPE) {
078: _arraytype = SHORT;
079: } else if (elemtype == Integer.TYPE) {
080: _arraytype = INT;
081: } else if (elemtype == Long.TYPE) {
082: _arraytype = LONG;
083: } else if (elemtype == Float.TYPE) {
084: _arraytype = FLOAT;
085: } else if (elemtype == Double.TYPE) {
086: _arraytype = DOUBLE;
087: } else if (Any.class.isAssignableFrom(elemtype)) {
088: _arraytype = ANVIL_CORE_ANY;
089: } else {
090: _arraytype = JAVA_LANG_OBJECT;
091: }
092: }
093:
094: Class super cls = cls.getSuperclass();
095: if (super cls != null) {
096: _super = ObjectPool.createReflection(super cls);
097: _super ref = new ResolvedClassRef(_super );
098: }
099:
100: if (Modifier.isPublic(cls.getModifiers())) {
101:
102: Method[] methods = cls.getDeclaredMethods();
103: int n = methods.length;
104: for(int i=0; i<n; i++) {
105: insertMethod(methods[i]);
106: }
107:
108: Constructor[] ctors = cls.getDeclaredConstructors();
109: n = ctors.length;
110: for(int i=0; i<n; i++) {
111: insertConstructor(ctors[i]);
112: }
113:
114: Field[] fields = cls.getDeclaredFields();
115: for(int i=0; i<fields.length; i++) {
116: Field field = fields[i];
117: int modifier = field.getModifiers();
118: if (Modifier.isPublic(modifier)) {
119: String name = field.getName();
120: if (Modifier.isStatic(modifier)) {
121: if (Modifier.isFinal(modifier)) {
122: addDeclaration(field.getName(),
123: new ReflectedConstantVariable(this , name, field, null));
124: } else {
125: addDeclaration(field.getName(), new AdaptiveClassVariable(name, field, this ));
126: }
127: } else {
128: addDeclaration(field.getName(), new AdaptiveMemberVariable(name, field, this ));
129: }
130: }
131: }
132:
133: Class[] classes = cls.getDeclaredClasses();
134: n = classes.length;
135: for(int i=0; i<n; i++) {
136: Class innercls = classes[i];
137: if (Modifier.isPublic(innercls.getModifiers())) {
138: Reflection ref = ObjectPool.createReflection(innercls);
139: String name = innercls.getName().substring(_name.length()+1);
140: addDeclaration(name, ref);
141: }
142: }
143:
144: Class[] interfaces = cls.getInterfaces();
145: n = interfaces.length;
146: _interfaces = new ResolvedInterfaceRef[n];
147: for(int i=0; i<n; i++) {
148: Class iface = interfaces[i];
149: if (Modifier.isPublic(iface.getModifiers())) {
150: _interfaces[i] = new ResolvedInterfaceRef(ObjectPool.createReflection(iface));
151: }
152: }
153:
154: }
155:
156: Reflection ref = _super ;
157: while(ref != null) {
158: Enumeration enum = ref.getDeclarations();
159: while(enum.hasMoreElements()) {
160: Type type = (Type)enum.nextElement();
161: String name = type.getName();
162: addDeclaration(name, type);
163: if (type.getType() == METHOD) {
164: addMethod(name, type);
165: }
166: }
167: ref = ref._super ;
168: }
169:
170: }
171:
172: private void addDeclaration(String name, Type type) {
173: if (!_declarations.containsKey(name)) {
174: _declarations.put(name, type);
175: }
176: }
177:
178: private void addMethod(String name, Type type) {
179: if (!_methods.containsKey(name)) {
180: _methods.put(name, type);
181: _methods.put(new Integer(Register.register(name)), type);
182: }
183: }
184:
185: private void insertMethod(Method method) {
186: if (Modifier.isPublic(method.getModifiers())) {
187: String name = method.getName();
188: MethodTree tree = (MethodTree) _methods.get(name);
189: if (tree == null) {
190: tree = new MethodTree(this , name);
191: addDeclaration(name, tree);
192: addMethod(name, tree);
193: }
194: tree.insert(method, method.getParameterTypes());
195: }
196: }
197:
198: private void insertConstructor(Constructor ctor) {
199: if (Modifier.isPublic(ctor.getModifiers())) {
200: if (_ctor == null) {
201: _ctor = new ConstructorTree(this , _name);
202: }
203: _ctor.insert(ctor, ctor.getParameterTypes());
204: }
205: }
206:
207: public String getSignature() {
208: return _class.getName().replace('.', '/');
209: }
210:
211: public Class getJavaClass() {
212: return _class;
213: }
214:
215: public anvil.script.ClassType classOf() {
216: return this ;
217: }
218:
219: public boolean isInstanceOf(Type ofType) {
220: if (ofType instanceof Reflection) {
221: Reflection reflection = (Reflection) ofType;
222: return reflection._class.isAssignableFrom(_class);
223: }
224: return false;
225: }
226:
227: public String toString() {
228: return "class " + _class.getName();
229: }
230:
231: public Object toObject() {
232: return _class;
233: }
234:
235: public String getName() {
236: return _name;
237: }
238:
239: public String getQualifiedName() {
240: return _name;
241: }
242:
243: public int getType() {
244: return _class.isInterface() ? INTERFACE : CLASS;
245: }
246:
247: public Scope getParent() {
248: return _parent;
249: }
250:
251: public ClassType[] getEnclosingClasses() {
252: return new ClassType[0];
253: }
254:
255: public String getPathinfo() {
256: return "";
257: }
258:
259: public BindingEnumeration getMembers(AnyClass instance) {
260: return BindingEnumeration.EMPTY;
261: }
262:
263: public Doc getDocument() {
264: return Doc.EMPTY_DOC;
265: }
266:
267: public Enumeration getDeclarations() {
268: return _declarations.elements();
269: }
270:
271: public Type lookupDeclaration(String name) {
272: return (Type) _declarations.get(name);
273: }
274:
275: public ClassRef getBase() {
276: return _super ref;
277: }
278:
279: public ClassType getBaseClass() {
280: return _super ;
281: }
282:
283: public Type lookupInheritedDeclaration(String name) {
284: if (_super != null) {
285: return _super .lookupDeclaration(name);
286: }
287: return null;
288: }
289:
290: public InterfaceRef[] getInterfaces() {
291: return _interfaces;
292: }
293:
294: public InterfaceRef[] getBases() {
295: return _interfaces;
296: }
297:
298: public CompilableFunction getConstructor() {
299: if (_ctor == null) {
300: return _super .getConstructor();
301: }
302: return _ctor;
303: }
304:
305: public AnyClass newInstance() {
306: return null;
307: }
308:
309: public boolean hasMethod(String name) {
310: if (_methods.containsKey(name)) {
311: return true;
312: }
313: if (_super != null) {
314: return _super .has(name);
315: }
316: return false;
317: }
318:
319: public Any getAttribute(Context context, String attribute) {
320: Type type = (Type) _declarations.get(attribute);
321: if (type != null) {
322: switch (type.getType()) {
323: case Type.STATIC_VARIABLE:
324: case Type.CONSTANT_VARIABLE:
325: return ((StaticVariableType) type).getValue();
326: case Type.CLASS:
327: case Type.INTERFACE:
328: return (Reflection) type;
329: }
330: }
331: return Any.UNDEFINED;
332: }
333:
334: public Any checkAttribute(Context context, String attribute) {
335: return getAttribute(context, attribute);
336: }
337:
338: public Any setAttribute(Context context, String attribute, Any value) {
339: Type type = (Type) _declarations.get(attribute);
340: if (type != null) {
341: if (type.getType() == Type.STATIC_VARIABLE) {
342: return ((VariableType) type).setValue(value);
343: }
344: }
345: return value;
346: }
347:
348: public Any getReference(Context context, Any index) {
349: if (index.isInt()) {
350: return Any.create(Array.newInstance(_class, index.toInt()));
351:
352: } else if (index.isTuple()) {
353: int n = index.sizeOf();
354: Any[] list = index.toTuple();
355: int dims[] = new int[n];
356: for (int i = 0; i < n; i++) {
357: dims[i] = list[i].toInt();
358: }
359: return Any.create(Array.newInstance(_class, dims));
360:
361: } else {
362: Type type = (Type) _declarations.get(index.toString());
363: if (type != null) {
364: switch (type.getType()) {
365: case Type.STATIC_VARIABLE:
366: case Type.CONSTANT_VARIABLE:
367: return ((VariableType) type).getValue();
368: case Type.CLASS:
369: case Type.INTERFACE:
370: return (Reflection) type;
371: }
372: }
373: }
374: return Any.UNDEFINED;
375: }
376:
377: public Any checkReference(Context context, Any index) {
378: return getReference(context, index);
379: }
380:
381: public Any setReference(Context context, Any index, Any value) {
382: Type type = (Type) _declarations.get(index.toString());
383: if (type != null) {
384: if (type.getType() == Type.STATIC_VARIABLE) {
385: return ((StaticVariableType) type).setValue(value);
386: }
387: }
388: return value;
389: }
390:
391: public Any invoke(Context context, Object instance,
392: int methodIndex, Any[] parameters) {
393: ParameterTree tree = (ParameterTree) _methods.get(ObjectPool
394: .createInteger(methodIndex));
395: if (tree != null) {
396: return tree.invoke(context, instance, parameters);
397: } else {
398: throw context.NoSuchMethod(_name, methodIndex);
399: }
400: }
401:
402: public Any invoke(Context context, Object instance,
403: String methodName, Any[] parameters) {
404: ParameterTree tree = (ParameterTree) _methods.get(methodName);
405: if (tree != null) {
406: return tree.invoke(context, instance, parameters);
407: } else {
408: throw context.NoSuchMethod(_name + '.' + methodName);
409: }
410: }
411:
412: public Any invoke(Context context, int methodIndex, Any[] parameters) {
413: return invoke(context, null, methodIndex, parameters);
414: }
415:
416: public Any invoke(Context context, int methodIndex) {
417: return invoke(context, null, methodIndex, Any.ARRAY0);
418: }
419:
420: public Any invoke(Context context, int methodIndex, Any param1) {
421: return invoke(context, null, methodIndex, new Any[] { param1 });
422: }
423:
424: public Any invoke(Context context, int methodIndex, Any param1,
425: Any param2) {
426: return invoke(context, null, methodIndex, new Any[] { param1,
427: param2 });
428: }
429:
430: public Any invoke(Context context, int methodIndex, Any param1,
431: Any param2, Any param3) {
432: return invoke(context, null, methodIndex, new Any[] { param1,
433: param2, param3 });
434: }
435:
436: public Any invoke(Context context, int methodIndex, Any param1,
437: Any param2, Any param3, Any param4) {
438: return invoke(context, null, methodIndex, new Any[] { param1,
439: param2, param3, param4 });
440: }
441:
442: public Any invoke(Context context, String methodName,
443: Any[] parameters) {
444: return invoke(context, null, methodName, parameters);
445: }
446:
447: public Any invoke(Context context, String methodName) {
448: return invoke(context, null, methodName, Any.ARRAY0);
449: }
450:
451: public Any invoke(Context context, String methodName, Any param1) {
452: return invoke(context, null, methodName, new Any[] { param1 });
453: }
454:
455: public Any invoke(Context context, String methodName, Any param1,
456: Any param2) {
457: return invoke(context, null, methodName, new Any[] { param1,
458: param2 });
459: }
460:
461: public Any invoke(Context context, String methodName, Any param1,
462: Any param2, Any param3) {
463: return invoke(context, null, methodName, new Any[] { param1,
464: param2, param3 });
465: }
466:
467: public Any invoke(Context context, String methodName, Any param1,
468: Any param2, Any param3, Any param4) {
469: return invoke(context, null, methodName, new Any[] { param1,
470: param2, param3, param4 });
471: }
472:
473: public ClassDispatcher getDispatcher(Context context) {
474: return null;
475: }
476:
477: public Any execute(Context context, Any[] parameters) {
478: if (_ctor != null) {
479: return _ctor.invoke(context, null, parameters);
480: } else {
481: return UNDEFINED;
482: }
483: }
484:
485: public Any execute(Context context) {
486: if (_ctor != null) {
487: return _ctor.invoke(context, null, Any.ARRAY0);
488: } else {
489: return UNDEFINED;
490: }
491: }
492:
493: public Any execute(Context context, Any param1) {
494: if (_ctor != null) {
495: return _ctor.invoke(context, null, new Any[] { param1 });
496: } else {
497: return UNDEFINED;
498: }
499: }
500:
501: public Any execute(Context context, Any param1, Any param2) {
502: if (_ctor != null) {
503: return _ctor.invoke(context, null, new Any[] { param1,
504: param2 });
505: } else {
506: return UNDEFINED;
507: }
508: }
509:
510: public Any execute(Context context, Any param1, Any param2,
511: Any param3) {
512: if (_ctor != null) {
513: return _ctor.invoke(context, null, new Any[] { param1,
514: param2, param3 });
515: } else {
516: return UNDEFINED;
517: }
518: }
519:
520: public Any execute(Context context, Any param1, Any param2,
521: Any param3, Any param4) {
522: if (_ctor != null) {
523: return _ctor.invoke(context, null, new Any[] { param1,
524: param2, param3, param4 });
525: } else {
526: return UNDEFINED;
527: }
528: }
529:
530: public String getDescriptor() {
531: return null;
532: }
533:
534: public int getTypeRef(anvil.codec.ConstantPool pool) {
535: return 0;
536: }
537:
538: public int getConstructorReference(anvil.codec.ConstantPool pool) {
539: return 0;
540: }
541:
542: public Any arrayGet(Object array, int index) {
543: switch (_arraytype) {
544: case BOOLEAN:
545: return Array.getBoolean(array, index) ? TRUE : FALSE;
546:
547: case BYTE:
548: return Any.create(Array.getByte(array, index));
549:
550: case CHAR:
551: return Any.create(Array.getChar(array, index));
552:
553: case SHORT:
554: return Any.create(Array.getShort(array, index));
555:
556: case INT:
557: return Any.create(Array.getInt(array, index));
558:
559: case LONG:
560: return Any.create(Array.getLong(array, index));
561:
562: case FLOAT:
563: return Any.create(Array.getFloat(array, index));
564:
565: case DOUBLE:
566: return Any.create(Array.getDouble(array, index));
567:
568: case JAVA_LANG_OBJECT:
569: return Any.create(Array.get(array, index));
570:
571: case ANVIL_CORE_ANY:
572: return (Any) Array.get(array, index);
573:
574: default:
575: return UNDEFINED;
576: }
577: }
578:
579: public void arraySet(Object array, int index, Any value) {
580: switch (_arraytype) {
581: case BOOLEAN:
582: Array.setBoolean(array, index, value.toBoolean());
583: return;
584:
585: case BYTE:
586: Array.setByte(array, index, (byte) value.toInt());
587: return;
588:
589: case CHAR:
590: Array.setChar(array, index, value.toChar());
591: return;
592:
593: case SHORT:
594: Array.setShort(array, index, (short) value.toInt());
595: return;
596:
597: case INT:
598: Array.setInt(array, index, value.toInt());
599: return;
600:
601: case LONG:
602: Array.setLong(array, index, value.toLong());
603: return;
604:
605: case FLOAT:
606: Array.setFloat(array, index, (float) value.toDouble());
607: return;
608:
609: case DOUBLE:
610: Array.setDouble(array, index, value.toDouble());
611: return;
612:
613: case JAVA_LANG_OBJECT:
614: Array.set(array, index, value.toObject());
615: return;
616:
617: case ANVIL_CORE_ANY:
618: Array.set(array, index, value);
619: return;
620: }
621: }
622:
623: public boolean isArray() {
624: return _class.isArray();
625: }
626:
627: public int arrayLength(Object array) {
628: if (_class.isArray()) {
629: return ((Object[]) array).length;
630: }
631: return 0;
632: }
633:
634: }
|