001: /*
002: * @(#)subclass.java 1.3 05/04/29
003: *
004: * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.lib;
010:
011: import pnuts.lang.Context;
012: import pnuts.lang.PnutsFunction;
013: import pnuts.lang.PnutsException;
014: import pnuts.lang.Package;
015: import pnuts.lang.Runtime;
016: import pnuts.compiler.ClassFile;
017: import pnuts.compiler.ClassFileHandler;
018: import java.util.Enumeration;
019: import java.util.Map;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.List;
023: import org.pnuts.lang.ClassFileLoader;
024: import org.pnuts.lang.SubtypeGenerator;
025:
026: public class subclass extends PnutsFunction {
027:
028: private ClassFileHandler handler;
029:
030: public subclass() {
031: this (null);
032: }
033:
034: public subclass(ClassFileHandler handler) {
035: super ("subclass");
036: this .handler = handler;
037: }
038:
039: public boolean defined(int nargs) {
040: return nargs >= 2 && nargs <= 5;
041: }
042:
043: static Class parseSupertypes(Object super types, List interfaces,
044: Context context) {
045: Class super class = null;
046: if (super types == null) {
047: super class = Object.class;
048: } else if (Runtime.isArray(super types)
049: || (super types instanceof Collection)) {
050: Enumeration e = Runtime.toEnumeration(super types, context);
051: while (e.hasMoreElements()) {
052: Class c = (Class) e.nextElement();
053: if (c.isInterface()) {
054: interfaces.add(c);
055: } else {
056: if (super class != null) {
057: throw new IllegalArgumentException(
058: "multiple inheritance: "
059: + super class.getName() + ","
060: + c.getName());
061: }
062: super class = c;
063: }
064: }
065: } else {
066: Class c = (Class) super types;
067: if (c.isInterface()) {
068: interfaces.add(c);
069: } else {
070: super class = c;
071: }
072: }
073: if (super class == null) {
074: return Object.class;
075: } else {
076: return super class;
077: }
078: }
079:
080: protected Object exec(Object[] args, Context context) {
081: int nargs = args.length;
082: if (nargs < 2 || nargs > 5) {
083: undefined(args, context);
084: return null;
085: }
086: int pos = 0;
087: Object arg0 = args[0];
088: String className;
089: if (arg0 instanceof String) {
090: className = (String) arg0;
091: pos++;
092: } else {
093: className = null;
094: }
095: Object super types = args[pos++];
096: ArrayList interfaces = new ArrayList();
097: Class super class = parseSupertypes(super types, interfaces,
098: context);
099:
100: Object arg1 = args[pos++];
101: Package pkg = null;
102: if (arg1 instanceof Map) {
103: pkg = new MapPackage((Map) arg1);
104: } else if (arg1 instanceof Package) {
105: pkg = (Package) arg1;
106: } else {
107: throw new IllegalArgumentException(String.valueOf(arg1));
108: }
109: int mode = 0;
110: if (pos <= nargs - 1) {
111: if (((Boolean) args[pos++]).booleanValue()) {
112: mode |= SubtypeGenerator.THIS;
113: }
114: }
115: if (pos <= nargs - 1) {
116: if (((Boolean) args[pos++]).booleanValue()) {
117: mode |= SubtypeGenerator.SUPER;
118: }
119: }
120: try {
121: ClassFileHandler handler = this .handler;
122: Class[] array = null;
123: if (interfaces != null) {
124: array = new Class[interfaces.size()];
125: interfaces.toArray(array);
126: }
127: if (handler == null) {
128: Class[] types = new Class[array.length + 1];
129: types[0] = super class;
130: for (int i = 0; i < array.length; i++) {
131: types[i + 1] = array[i];
132: }
133: ClassLoader ccl = Thread.currentThread()
134: .getContextClassLoader();
135: ClassLoader cl = SubtypeGenerator.mergeClassLoader(
136: types, ccl);
137: ClassFileLoader cfl = new ClassFileLoader(cl);
138: handler = cfl;
139: if (className == null) {
140: className = super class.getName().replace('.', '_')
141: + "$" + cfl.getId() + "$"
142: + cfl.getClassCount();
143: }
144:
145: ClassLoader newCl = (ClassLoader) handler;
146: context.setClassLoader(newCl);
147: Thread.currentThread().setContextClassLoader(newCl);
148: }
149: if (handler instanceof ClassFileLoader) {
150: ClassFileLoader cfl = (ClassFileLoader) handler;
151: cfl.setup(pkg, context);
152: if (className == null) {
153: className = super class.getName().replace('.', '_')
154: + "$" + cfl.getId() + "$"
155: + cfl.getClassCount();
156: }
157: // } else {
158: // mode |= SubtypeGenerator.SERIALIZE;
159: }
160: if (className == null) {
161: className = super class.getName().replace('.', '_')
162: + "__adapter";
163: }
164:
165: ClassFile cf = SubtypeGenerator.getClassFileForSubclass(
166: className, super class, array, pkg, context, mode);
167: return handler.handle(cf);
168: } catch (Exception e) {
169: throw new PnutsException(e, context);
170: }
171: }
172:
173: public String toString() {
174: return "function subclass({ className ,} (supertype|supertypes[]), pkgOrMap {, hasThis { , hasSuper }} )";
175: }
176: }
|