Source Code Cross Referenced for SubtypeGenerator.java in  » Scripting » Pnuts » org » pnuts » lang » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » Pnuts » org.pnuts.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * SubtypeGenerator.java
003:         *
004:         * Copyright (c) 1997-2006 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.lang;
010:
011:        import java.io.*;
012:        import java.lang.reflect.Constructor;
013:        import java.lang.reflect.Method;
014:        import java.lang.reflect.Modifier;
015:        import java.util.ArrayList;
016:        import java.util.List;
017:        import java.util.Iterator;
018:        import java.util.HashSet;
019:        import java.util.Set;
020:        import java.util.Map;
021:        import java.util.HashMap;
022:        import java.util.Enumeration;
023:        import java.util.Hashtable;
024:
025:        import pnuts.compiler.Compiler;
026:        import pnuts.compiler.ClassFile;
027:        import pnuts.compiler.Constants;
028:        import pnuts.compiler.Label;
029:        import pnuts.compiler.MultiClassLoader;
030:        import pnuts.compiler.Opcode;
031:        import pnuts.compiler.ClassGenerator;
032:        import pnuts.lang.Context;
033:        import pnuts.lang.Function;
034:        import pnuts.lang.Package;
035:        import pnuts.lang.Pnuts;
036:        import pnuts.lang.SimpleNode;
037:        import pnuts.lang.PnutsException;
038:        import pnuts.lang.PnutsFunction;
039:        import pnuts.lang.Runtime;
040:
041:        /**
042:         * This class provides a way to extends a Java class in Pnuts.
043:         */
044:        public class SubtypeGenerator extends Runtime {
045:
046:            private final static boolean DEBUG = false;
047:
048:            public final static int THIS = 0x0001;
049:            public final static int SUPER = 0x0002;
050:
051:            private final static String SUPER_PROXY_NAME = "pnuts.compiler.ClassGenerator$SuperCallProxy";
052:
053:            protected SubtypeGenerator() {
054:            }
055:
056:            /**
057:             * Generates a class that extends the superClass and implements the
058:             * interfaces. Functions in the pkg are mapped to non-final/static
059:             * public/protected methods with the same name and the same number of
060:             * parameters. Note that this method may throw ClassFormatError.
061:             * 
062:             * @param superClass
063:             *            super class that the generated class extends
064:             * @param interfaces
065:             *            list of interfaces that the generated class implements
066:             * @param pkg
067:             *            a Package that includes functions to be mapped to methods.
068:             * @param context
069:             *            a Context in which functions are extracted from pkg
070:             * @param mode
071:             *            THIS if each function has 'this' parameter, otherwise 0.
072:             * @return the generated class
073:             */
074:            public static Class generateSubclass(Class super Class,
075:                    Class[] interfaces, Package pkg, Context context, int mode) {
076:                String super ClassName = super Class.getName();
077:                String className = super ClassName.replace('.', '_')
078:                        + "__adapter";
079:                return generateSubclass(className, super Class, interfaces, pkg,
080:                        context, mode);
081:            }
082:
083:            /**
084:             * Generates a class that extends the superClass and implements the
085:             * interfaces. Functions in the pkg are mapped to non-final/static
086:             * public/protected methods with the same name and the same number of
087:             * parameters. Note that this method may throw ClassFormatError.
088:             * 
089:             * @param className
090:             *            the name of the class to be generated
091:             * @param superClass
092:             *            super class that the generated class extends
093:             * @param interfaces
094:             *            list of interfaces that the generated class implements
095:             * @param pkg
096:             *            a Package that includes functions to be mapped to methods.
097:             * @param context
098:             *            a Context in which functions are extracted from pkg
099:             * @param mode
100:             *            THIS if each function has 'this' parameter, otherwise 0.
101:             * @return the generated class
102:             */
103:            public static Class generateSubclass(String className,
104:                    Class super Class, Class[] interfaces, Package pkg,
105:                    Context context, int mode) {
106:                return generateSubclass(className, super Class, interfaces,
107:                        null, pkg, context, mode);
108:            }
109:
110:            /**
111:             * Generates a class that extends the superClass and implements the
112:             * interfaces. Functions in the pkg are mapped to non-final/static
113:             * public/protected methods with the same name and the same number of
114:             * parameters. Note that this method may throw ClassFormatError.
115:             * 
116:             * @param className
117:             *            the name of the class to be generated
118:             * @param superClass
119:             *            super class that the generated class extends
120:             * @param interfaces
121:             *            list of interfaces that the generated class implements
122:             * @param sigs
123:             *            an array of optional explicit method signature.
124:             *            If it is null, method signatures are determined by
125:             *            supertypes' method signature and number of function parameters.
126:             *            If it isn't null, the array of method signature
127:             *            is used to determin method signatures.
128:             * @param pkg
129:             *            a Package that includes functions to be mapped to methods.
130:             * @param context
131:             *            a Context in which functions are extracted from pkg
132:             * @param mode
133:             *            THIS if each function has 'this' parameter, otherwise 0.
134:             * @return the generated class
135:             */
136:            public static Class generateSubclass(String className,
137:                    Class super Class, Class[] interfaces, Signature[] sigs,
138:                    Package pkg, Context context, int mode) {
139:                return generateSubclass(className, super Class, interfaces,
140:                        sigs, pkg, null, context, mode);
141:            }
142:
143:            public static Class generateSubclass(String className,
144:                    Class super Class, Class[] interfaces, Signature[] sigs,
145:                    Package pkg, Map typeMap, Context context, int mode) {
146:                ClassLoader classLoader = context.getClassLoader();
147:                if (classLoader == null) {
148:                    classLoader = Thread.currentThread()
149:                            .getContextClassLoader();
150:                }
151:                ClassFileLoader handler = new ClassFileLoader(classLoader);
152:                handler.setup(pkg, context);
153:                ClassFile cf = getClassFileForSubclass(className, super Class,
154:                        interfaces, pkg, typeMap, context, mode, sigs);
155:
156:                if (DEBUG) {
157:                    try {
158:                        FileOutputStream fout = new FileOutputStream("c:/tmp/"
159:                                + className + ".class");
160:                        DataOutputStream dout = new DataOutputStream(fout);
161:                        cf.write(dout);
162:                        fout.close();
163:                        System.out.println(className);
164:                    } catch (Exception e) {
165:                        e.printStackTrace();
166:                    }
167:                }
168:                return (Class) handler.handle(cf);
169:            }
170:
171:            /**
172:             * Generates a subtype of the specified class and instantiates with the
173:             * given arguments.
174:             * 
175:             * @param context
176:             *            the context
177:             * @param superClass
178:             *            the super class to extend
179:             * @param interfaces
180:             *            the interfaces to implement
181:             * @param pkg
182:             *            a Package that includes functions to be mapped to methods.
183:             * @param args
184:             *            the arguments to the constructor
185:             */
186:            public static Object instantiateSubtype(Context context,
187:                    Class super Class, Class[] interfaces, Package pkg,
188:                    Object[] args) {
189:                try {
190:                    if (super Class == null) {
191:                        super Class = Object.class;
192:                    }
193:                    Class cls = generateSubclass(super Class, interfaces, pkg,
194:                            context, 0);
195:                    return Runtime.callConstructor(context, cls, args, null);
196:                } catch (Throwable t) {
197:                    throw new PnutsException(t, context);
198:                }
199:            }
200:
201:            /**
202:             * Creates a class file image of a subtype of superClass (or some
203:             * interfaces) and writes to the output stream.
204:             * 
205:             * @param superClass
206:             *            super class that the generated class extends
207:             * @param interfaces
208:             *            list of interfaces that the generated class implements
209:             * @param pkg
210:             *            a Package that includes functions to be mapped to methods.
211:             * @param context
212:             *            a Context in which functions are extracted from pkg
213:             * @param mode
214:             *            THIS if each function has 'this' parameter, otherwise 0.
215:             */
216:            public static ClassFile getClassFileForSubclass(String className,
217:                    Class super Class, Class[] interfaces, Package pkg,
218:                    Context context, int mode) {
219:                return getClassFileForSubclass(className, super Class,
220:                        interfaces, pkg, null, context, mode, null);
221:            }
222:
223:            /**
224:             * Creates a class file image of a subtype of superClass (or some
225:             * interfaces) and writes to the output stream.
226:             * 
227:             * @param superClass
228:             *            super class that the generated class extends
229:             * @param interfaces
230:             *            list of interfaces that the generated class implements
231:             * @param pkg
232:             *            a Package that includes functions to be mapped to methods.
233:             * @param context
234:             *            a Context in which functions are extracted from pkg
235:             * @param mode
236:             *            THIS if each function has 'this' parameter, otherwise 0.
237:             * @param signatures
238:             *            signature information
239:             */
240:            public static ClassFile getClassFileForSubclass(String className,
241:                    Class super Class, Class[] interfaces, Package pkg,
242:                    Map typeMap, Context context, int mode,
243:                    Signature[] signatures) {
244:                ClassFile cf = ClassGenerator.createClassFile(className,
245:                        super Class, interfaces, null);
246:                constructor(cf, super Class);
247:
248:                cf.addField("_package", "Lpnuts/lang/Package;",
249:                        (short) (Constants.ACC_PRIVATE | Constants.ACC_STATIC));
250:
251:                //
252:                // public static void attach(Context, Package);
253:                //
254:                cf.openMethod("attach",
255:                        "(Lpnuts/lang/Context;Lpnuts/lang/Package;)V",
256:                        (short) (Constants.ACC_PUBLIC | Constants.ACC_STATIC));
257:
258:                cf.add(Opcode.ALOAD_0);
259:                cf.add(Opcode.PUTSTATIC, className, "_context",
260:                        "Lpnuts/lang/Context;");
261:                cf.add(Opcode.ALOAD_1);
262:                cf.add(Opcode.PUTSTATIC, className, "_package",
263:                        "Lpnuts/lang/Package;");
264:                cf.add(Opcode.RETURN);
265:                cf.closeMethod();
266:
267:                if (typeMap != null) {
268:                    for (Iterator it = typeMap.entrySet().iterator(); it
269:                            .hasNext();) {
270:                        Map.Entry entry = (Map.Entry) it.next();
271:                        String name = (String) entry.getKey();
272:                        Class type = (Class) entry.getValue();
273:                        cf.addField(name, Signature.makeSignature(type),
274:                                Constants.ACC_PRIVATE);
275:                    }
276:                }
277:
278:                if (signatures != null && typeMap != null) {
279:                    defineMethods(cf, pkg, super Class, interfaces, context,
280:                            mode, signatures);
281:                    Set sigset = new HashSet();
282:                    for (int i = 0; i < signatures.length; i++) {
283:                        sigset.add(signatures[i]);
284:                    }
285:                    for (Iterator it = typeMap.entrySet().iterator(); it
286:                            .hasNext();) {
287:                        Map.Entry entry = (Map.Entry) it.next();
288:                        String name = (String) entry.getKey();
289:                        Class type = (Class) entry.getValue();
290:                        Signature s = Compiler.getterSignature(type, name);
291:                        if (!sigset.contains(s)) {
292:                            generateGetter(cf, name, type, s.getMethodName());
293:                        }
294:                        s = Compiler.setterSignature(type, name);
295:                        if (!sigset.contains(s)) {
296:                            generateSetter(cf, name, type, s.getMethodName());
297:                        }
298:                    }
299:
300:                } else {
301:                    // just for subclass() function
302:                    defineMethods(cf, pkg, super Class, interfaces, context,
303:                            mode);
304:                }
305:
306:                return cf;
307:            }
308:
309:            static void generateGetter(ClassFile cf, String name, Class type,
310:                    String methodName) {
311:                String className = cf.getClassName();
312:                String param = Signature.makeSignature(type);
313:                cf.openMethod(methodName, "()" + param, Constants.ACC_PUBLIC);
314:                cf.add(Opcode.ALOAD_0);
315:                cf.add(Opcode.GETFIELD, className, name, param);
316:
317:                if (param.length() == 1) { // primitive
318:                    char ch = param.charAt(0);
319:                    switch (ch) {
320:                    case 'I':
321:                    case 'S':
322:                    case 'B':
323:                    case 'C':
324:                    case 'Z':
325:                        cf.add(Opcode.IRETURN);
326:                        break;
327:                    case 'J':
328:                        cf.add(Opcode.LRETURN);
329:                        break;
330:                    case 'F':
331:                        cf.add(Opcode.FRETURN);
332:                        break;
333:                    case 'D':
334:                        cf.add(Opcode.DRETURN);
335:                        break;
336:                    }
337:                } else {
338:                    cf.add(Opcode.ARETURN);
339:                }
340:                cf.closeMethod();
341:            }
342:
343:            static void generateSetter(ClassFile cf, String name, Class type,
344:                    String methodName) {
345:                String className = cf.getClassName();
346:                String param = Signature.makeSignature(type);
347:                cf.openMethod(methodName, "(" + param + ")V",
348:                        Constants.ACC_PUBLIC);
349:                cf.add(Opcode.ALOAD_0);
350:                if (param.length() == 1) { // primitive
351:                    char ch = param.charAt(0);
352:                    switch (ch) {
353:                    case 'I':
354:                    case 'S':
355:                    case 'B':
356:                    case 'C':
357:                    case 'Z':
358:                        cf.add(Opcode.ILOAD_1);
359:                        cf.add(Opcode.PUTFIELD, className, name, param);
360:                        break;
361:                    case 'J':
362:                        cf.add(Opcode.LLOAD_1);
363:                        cf.add(Opcode.PUTFIELD, className, name, param);
364:                        break;
365:                    case 'F':
366:                        cf.add(Opcode.FLOAD_1);
367:                        cf.add(Opcode.PUTFIELD, className, name, param);
368:                        break;
369:                    case 'D':
370:                        cf.add(Opcode.DLOAD_1);
371:                        cf.add(Opcode.PUTFIELD, className, name, param);
372:                        break;
373:                    }
374:                } else {
375:                    cf.add(Opcode.ALOAD_1);
376:                    cf.add(Opcode.PUTFIELD, className, name, param);
377:                }
378:                cf.add(Opcode.RETURN);
379:                cf.closeMethod();
380:            }
381:
382:            static void defineMethods(ClassFile cf, Package pkg,
383:                    Class super Class, Class[] interfaces, Context context,
384:                    int mode, Signature[] signatures) {
385:                for (int i = 0; i < signatures.length; i++) {
386:                    Signature s = signatures[i];
387:                    Object value = pkg.get(s.toString(), context);
388:                    if (value instanceof  PnutsFunction) {
389:                        PnutsFunction func = (PnutsFunction) value;
390:                        List methods = new ArrayList();
391:                        if (s.resolve(super Class, interfaces, methods)) {
392:                            String sig = s.toString();
393:                            Class returnType = s.returnType;
394:                            if (returnType == null) {
395:                                returnType = Object.class;
396:                            }
397:                            defineMethod(cf, s.parameterTypes, returnType,
398:                                    s.exceptionTypes, s.modifiers,
399:                                    s.methodName, sig, mode);
400:                        } else {
401:                            for (Enumeration e = getFunctions(func); e
402:                                    .hasMoreElements();) {
403:                                Signature s2 = (Signature) s.clone();
404:                                Function f = (Function) e.nextElement();
405:                                int n = f.getNumberOfParameter();
406:                                if ((mode & THIS) == THIS) {
407:                                    n--;
408:                                }
409:                                if ((mode & SUPER) == SUPER) {
410:                                    n--;
411:                                }
412:                                if (s.parameterTypes == null) {
413:                                    Class[] p = new Class[n];
414:                                    for (int j = 0; j < n; j++) {
415:                                        p[j] = Object.class;
416:                                    }
417:                                    s2.parameterTypes = p;
418:                                } else {
419:                                    for (int j = 0; j < n; j++) {
420:                                        if (s2.parameterTypes[j] == null) {
421:                                            s2.parameterTypes[j] = Object.class;
422:                                        }
423:                                    }
424:                                }
425:                                if (s2.returnType == null) {
426:                                    s2.returnType = Object.class;
427:                                }
428:                                String sig = s.methodName
429:                                        + Signature.makeSignature(
430:                                                s2.parameterTypes,
431:                                                s2.returnType);
432:                                sig = sig.intern();
433:                                pkg.set(sig, func, context);
434:                                defineMethod(cf, s2.parameterTypes,
435:                                        s2.returnType, s.exceptionTypes,
436:                                        Modifier.PUBLIC, s2.methodName, sig,
437:                                        mode);
438:                            }
439:                        }
440:                    }
441:                }
442:            }
443:
444:            static void defineMethods(ClassFile cf, Package pkg,
445:                    Class super Class, Class[] interfaces, Context context,
446:                    int mode) {
447:                for (Enumeration e = pkg.keys(); e.hasMoreElements();) {
448:                    String name = (String) e.nextElement();
449:                    Object value = pkg.get(name, context);
450:                    if (!(value instanceof  PnutsFunction)) {
451:                        continue;
452:                    }
453:                    PnutsFunction func = (PnutsFunction) value;
454:                    String sig = name;
455:                    String methodName = name;
456:
457:                    int idx = methodName.indexOf('(');
458:                    if (idx >= 0) {
459:                        methodName = methodName.substring(0, idx);
460:                    }
461:                    defineMethods(cf, methodName, sig, func, super Class,
462:                            interfaces, context, mode);
463:                }
464:            }
465:
466:            static int parseTypes(String sig, Context context, List types) {
467:                int idx = sig.indexOf('(');
468:                if (idx >= 0) {
469:                    try {
470:                        return parseParameterSignature(sig.substring(idx + 1),
471:                                types, context)
472:                                + idx + 1;
473:                    } catch (ClassNotFoundException e) {
474:                    }
475:                }
476:                return -1;
477:            }
478:
479:            static List returnTypeAndExceptions(String sig, Context context) {
480:                List types = new ArrayList();
481:                try {
482:                    parseParameterSignature(sig, types, context);
483:                } catch (ClassNotFoundException e) {
484:                    return null;
485:                }
486:                return types;
487:            }
488:
489:            public static void constructor(ClassFile cf, Class super Class) {
490:                constructor(cf, super Class, null, null, null);
491:            }
492:
493:            public static void constructor(ClassFile cf, Class super Class,
494:                    Compiler compiler, Context cc, List assignments) {
495:                String className = cf.getClassName();
496:
497:                cf.addField("_superCallProxy", "Lpnuts/lang/AbstractData;",
498:                        Constants.ACC_PRIVATE);
499:                if (super Class == null) {
500:                    super Class = Object.class;
501:                }
502:                Constructor constructors[] = super Class
503:                        .getDeclaredConstructors();
504:                int count = 0;
505:                for (int i = 0; i < constructors.length; i++) {
506:                    Constructor cons = constructors[i];
507:                    Class parameterTypes[] = cons.getParameterTypes();
508:                    String sig = ClassFile.signature(parameterTypes);
509:
510:                    int mod = cons.getModifiers();
511:                    short acc;
512:                    if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
513:                        continue;
514:                    }
515:                    count++;
516:                    cf.openMethod("<init>", sig + "V", Constants.ACC_PUBLIC);
517:                    cf.add(Opcode.ALOAD_0);
518:                    for (int j = 0, k = 0; j < parameterTypes.length; j++) {
519:                        Class type = parameterTypes[j];
520:                        if (type == int.class || type == byte.class
521:                                || type == short.class || type == char.class
522:                                || type == boolean.class) {
523:                            cf.iloadLocal(1 + j + k);
524:                        } else if (type == long.class) {
525:                            cf.lloadLocal(1 + j + k);
526:                            k++;
527:                        } else if (type == float.class) {
528:                            cf.floadLocal(1 + j + k);
529:                        } else if (type == double.class) {
530:                            cf.dloadLocal(1 + j + k);
531:                            k++;
532:                        } else {
533:                            cf.loadLocal(1 + j + k);
534:                        }
535:                    }
536:                    cf.add(Opcode.INVOKESPECIAL, super Class.getName(),
537:                            "<init>", sig, "V");
538:
539:                    assignSuperCallProxy(cf, className);
540:
541:                    if (compiler != null) {
542:                        declareFields(cf, cc, compiler, assignments);
543:                    }
544:
545:                    cf.add(Opcode.RETURN);
546:                    cf.closeMethod();
547:                }
548:                if (count == 0) {
549:                    cf.openMethod("<init>", "()V", Constants.ACC_PUBLIC);
550:                    cf.add(Opcode.ALOAD_0);
551:                    cf.add(Opcode.INVOKESPECIAL, super Class.getName(),
552:                            "<init>", "()", "V");
553:
554:                    assignSuperCallProxy(cf, className);
555:
556:                    if (compiler != null) {
557:                        declareFields(cf, cc, compiler, assignments);
558:                    }
559:
560:                    cf.add(Opcode.RETURN);
561:                    cf.closeMethod();
562:                }
563:            }
564:
565:            private static void declareFields(ClassFile cf, Context cc,
566:                    Compiler compiler, List assignments) {
567:                String className = cf.getClassName();
568:                for (int i = 0, n = assignments.size(); i < n; i++) {
569:                    SimpleNode assign = (SimpleNode) assignments.get(i);
570:                    SimpleNode lhs = assign.jjtGetChild(0);
571:                    SimpleNode rhs = assign.jjtGetChild(1);
572:                    cf.add(Opcode.GETSTATIC, className, "_context",
573:                            "Lpnuts/lang/Context;");
574:                    cf.add(Opcode.ALOAD_0); // this
575:                    cf.add(Opcode.LDC, cf.addConstant(lhs.str));
576:                    rhs.accept(compiler, cc);
577:                    cf
578:                            .add(
579:                                    Opcode.INVOKESTATIC,
580:                                    "pnuts.lang.Runtime",
581:                                    "putField",
582:                                    "(Lpnuts/lang/Context;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)",
583:                                    "V");
584:                }
585:            }
586:
587:            /*
588:             * this._superCallProxy = new SuperCallProxy(this);
589:             */
590:            private static void assignSuperCallProxy(ClassFile cf,
591:                    String className) {
592:                cf.add(Opcode.ALOAD_0);
593:                cf.add(Opcode.NEW, SUPER_PROXY_NAME);
594:                cf.add(Opcode.DUP);
595:                cf.add(Opcode.ALOAD_0);
596:                cf.add(Opcode.INVOKESPECIAL, SUPER_PROXY_NAME, "<init>",
597:                        "(Ljava/lang/Object;)", "V");
598:                cf.add(Opcode.PUTFIELD, className, "_superCallProxy",
599:                        "Lpnuts/lang/AbstractData;");
600:            }
601:
602:            private static void defineMethods(ClassFile cf, String name,
603:                    String sig, PnutsFunction func, Class super Class,
604:                    Class[] interfaces, Context context, int mode) {
605:                Hashtable methods = new Hashtable();
606:                int count = 0;
607:                if (interfaces != null) {
608:                    loop1: for (int i = 0; i < interfaces.length; i++) {
609:                        Class _interface = interfaces[i];
610:                        Method[] _methods = _interface.getMethods();
611:                        for (int j = 0; j < _methods.length; j++) {
612:                            Method m = _methods[j];
613:                            int modifiers = m.getModifiers();
614:                            if (!Modifier.isPublic(modifiers)
615:                                    && !Modifier.isProtected(modifiers)
616:                                    || Modifier.isStatic(modifiers)
617:                                    || Modifier.isFinal(modifiers)) {
618:                                continue;
619:                            }
620:                            Class[] parameterTypes = m.getParameterTypes();
621:                            Class[] exceptionTypes = m.getExceptionTypes();
622:                            String signature = name
623:                                    + ClassFile.signature(parameterTypes);
624:                            int expected_args = parameterTypes.length;
625:
626:                            if ((mode & THIS) == THIS) {
627:                                expected_args++;
628:                            }
629:                            if ((mode & SUPER) == SUPER) {
630:                                expected_args++;
631:                            }
632:                            if (m.getName().equals(name)
633:                                    && func.defined(expected_args)) {
634:                                if (sig == name) { // no type info
635:                                    if (methods.get(signature) == null) {
636:                                        defineMethod(cf, parameterTypes, m
637:                                                .getReturnType(),
638:                                                exceptionTypes,
639:                                                Modifier.PUBLIC, name, sig,
640:                                                mode);
641:                                        methods.put(signature, signature);
642:                                        count++;
643:                                    }
644:                                } else {
645:                                    if (!sig.equals(signature)) {
646:                                        continue;
647:                                    }
648:                                    if (methods.get(signature) == null) {
649:                                        defineMethod(cf, parameterTypes, m
650:                                                .getReturnType(),
651:                                                exceptionTypes,
652:                                                Modifier.PUBLIC, name, sig,
653:                                                mode);
654:                                        methods.put(signature, signature);
655:                                        count++;
656:                                    }
657:                                }
658:                            }
659:                        }
660:                    }
661:                }
662:                if (super Class == null) {
663:                    super Class = Object.class;
664:                }
665:                while (super Class != null) {
666:                    Method[] _methods = ReflectionUtil
667:                            .getInheritableMethods(super Class);
668:
669:                    loop2: for (int j = 0; j < _methods.length; j++) {
670:                        Method m = _methods[j];
671:                        int modifiers = m.getModifiers();
672:                        if (!Modifier.isPublic(modifiers)
673:                                && !Modifier.isProtected(modifiers)
674:                                || Modifier.isStatic(modifiers)
675:                                || Modifier.isFinal(modifiers)) {
676:                            continue;
677:                        }
678:                        Class[] parameterTypes = m.getParameterTypes();
679:                        Class[] exceptionTypes = m.getExceptionTypes();
680:                        String signature = name
681:                                + ClassFile.signature(parameterTypes);
682:                        int expected_args = parameterTypes.length;
683:                        if ((mode & THIS) == THIS) {
684:                            expected_args++;
685:                        }
686:                        if ((mode & SUPER) == SUPER) {
687:                            expected_args++;
688:                        }
689:                        if (m.getName().equals(name)
690:                                && func.defined(expected_args)) {
691:                            if (sig == name) { // no type info
692:                                if (methods.get(signature) == null) {
693:                                    defineMethod(cf, parameterTypes, m
694:                                            .getReturnType(), exceptionTypes,
695:                                            Modifier.PUBLIC, name, sig, mode);
696:                                    methods.put(signature, signature);
697:                                    count++;
698:                                }
699:                            } else {
700:                                if (!sig.equals(signature)) {
701:                                    continue;
702:                                }
703:                                if (methods.get(signature) == null) {
704:                                    defineMethod(cf, parameterTypes, m
705:                                            .getReturnType(), exceptionTypes,
706:                                            Modifier.PUBLIC, name, sig, mode);
707:                                    methods.put(signature, signature);
708:                                    count++;
709:                                }
710:                            }
711:                        }
712:                    }
713:                    super Class = super Class.getSuperclass();
714:                }
715:
716:                if (count == 0) { // when not override
717:                    Enumeration ee = getFunctions(func);
718:                    if (ee != null) {
719:                        Function f = (Function) ee.nextElement();
720:                        int narg = f.getNumberOfParameter();
721:                        if ((mode & THIS) == THIS && narg > 0) {
722:                            narg--;
723:                        }
724:                        if ((mode & SUPER) == SUPER && narg > 0) {
725:                            narg--;
726:                        }
727:                        Class[] parameterTypes = new Class[narg];
728:                        Class[] exceptionTypes = null;
729:                        Class returnType;
730:                        List types = null;
731:                        int pos = -1;
732:                        if (sig != name) {
733:                            types = new ArrayList();
734:                            pos = parseTypes(sig, context, types);
735:                        }
736:                        if (pos == -1) { // no type info
737:                            for (int i = 0; i < narg; i++) {
738:                                parameterTypes[i] = Object.class;
739:                            }
740:
741:                            returnType = Object.class;
742:                        } else {
743:                            for (int i = 0; i < narg; i++) {
744:                                parameterTypes[i] = (Class) types.get(i);
745:                            }
746:                            types = returnTypeAndExceptions(sig.substring(pos),
747:                                    context);
748:
749:                            returnType = (Class) types.get(0);
750:                            if (types.size() > 1) {
751:                                exceptionTypes = new Class[types.size() - 1];
752:                                for (int i = 0; i < exceptionTypes.length; i++) {
753:                                    exceptionTypes[i] = (Class) types
754:                                            .get(1 + i);
755:                                }
756:                            }
757:                        }
758:                        defineMethod(cf, parameterTypes, returnType,
759:                                exceptionTypes, Modifier.PUBLIC, name, sig,
760:                                mode);
761:                    }
762:                }
763:            }
764:
765:            public static void defineMethod(ClassFile cf,
766:                    Class[] parameterTypes, Class returnType,
767:                    Class[] exceptionTypes, int modifiers, String methodName,
768:                    String sig, int mode) {
769:                ClassGenerator.defineMethod(cf, parameterTypes, returnType,
770:                        exceptionTypes, modifiers, methodName, sig, mode);
771:            }
772:
773:            private static int parseParameterSignature(String signature,
774:                    List types, Context context) throws ClassNotFoundException {
775:                char[] c = signature.toCharArray();
776:                int index = 0;
777:                int dim = 0;
778:                //	boolean returnPart = false;
779:                loop: while (index < c.length) {
780:                    switch (c[index]) {
781:                    case 'V':
782:                        types.add(void.class);
783:                        dim = 0;
784:                        index++;
785:                        break;
786:                    case 'J':
787:                        types.add(Runtime.arrayType(Long.TYPE, dim));
788:                        dim = 0;
789:                        index++;
790:                        break;
791:                    case 'D':
792:                        types.add(Runtime.arrayType(Double.TYPE, dim));
793:                        dim = 0;
794:                        index++;
795:                        break;
796:                    case 'B':
797:                        types.add(Runtime.arrayType(Byte.TYPE, dim));
798:                        dim = 0;
799:                        index++;
800:                        break;
801:                    case 'S':
802:                        types.add(Runtime.arrayType(Short.TYPE, dim));
803:                        dim = 0;
804:                        index++;
805:                        break;
806:                    case 'C':
807:                        types.add(Runtime.arrayType(Character.TYPE, dim));
808:                        dim = 0;
809:                        index++;
810:                        break;
811:                    case 'I':
812:                        types.add(Runtime.arrayType(Integer.TYPE, dim));
813:                        dim = 0;
814:                        index++;
815:                        break;
816:                    case 'Z':
817:                        types.add(Runtime.arrayType(Boolean.TYPE, dim));
818:                        dim = 0;
819:                        index++;
820:                        break;
821:                    case 'F':
822:                        types.add(Runtime.arrayType(Float.TYPE, dim));
823:                        dim = 0;
824:                        index++;
825:                        break;
826:                    case '[':
827:                        while (c[index] == '[') {
828:                            dim++;
829:                            index++;
830:                        }
831:                        break;
832:                    case 'L':
833:                        int start = index + 1;
834:                        while (c[index++] != ';') {
835:                        }
836:                        String cn = new String(c, start, index - start - 1);
837:                        types.add(Runtime.arrayType(Pnuts.loadClass(cn.replace(
838:                                '/', '.'), context), dim));
839:                        dim = 0;
840:                        break;
841:                    case ')':
842:                        //		returnPart = true;
843:                        index++;
844:                        //		continue loop;
845:                        break loop;
846:                    default:
847:                        throw new PnutsException("illegal method signature",
848:                                context);
849:                    }
850:                    //	    if (returnPart){
851:                    //		break loop;
852:                    //	    }
853:                }
854:                return index;
855:            }
856:
857:            /**
858:             * Generates an interface
859:             * 
860:             * @param name
861:             *            the name of the interface
862:             * @param superInterfaces
863:             *            an array of super interface
864:             * @param signatures
865:             *            an array of method signatures
866:             * @param context
867:             *            the context in which the classes are loaded
868:             * @return the generated interface
869:             */
870:            public static Class generateInterface(String name,
871:                    Class[] super Interfaces, String[] signatures,
872:                    Context context) {
873:                return generateInterface(
874:                        name,
875:                        super Interfaces,
876:                        signatures,
877:                        context,
878:                        (short) (Constants.ACC_PUBLIC | Constants.ACC_INTERFACE));
879:            }
880:
881:            /**
882:             * Generates an interface
883:             * 
884:             * @param name
885:             *            the name of the interface
886:             * @param superInterfaces
887:             *            an array of super interface
888:             * @param signatures
889:             *            an array of method signatures
890:             * @param context
891:             *            the context in which the classes are loaded
892:             * @param modifiers
893:             *            the modifiers of the interface
894:             * @return the generated interface
895:             */
896:            public static Class generateInterface(String name,
897:                    Class[] super Interfaces, String[] signatures,
898:                    Context context, short modifiers) {
899:                ClassLoader classLoader = context.getClassLoader();
900:                if (classLoader == null) {
901:                    classLoader = Thread.currentThread()
902:                            .getContextClassLoader();
903:                }
904:                ClassFileLoader handler = new ClassFileLoader(classLoader);
905:                ClassFile cf = getClassFileForInterface(name, super Interfaces,
906:                        signatures, context, modifiers);
907:                return (Class) handler.handle(cf);
908:            }
909:
910:            public static ClassFile getClassFileForInterface(String name,
911:                    Class[] super Interfaces, String[] signatures,
912:                    Context context, short modifiers) {
913:                ClassFile cf = new ClassFile(name, "java.lang.Object", null,
914:                        modifiers);
915:                if (super Interfaces != null) {
916:                    for (int i = 0; i < super Interfaces.length; i++) {
917:                        cf.addInterface(super Interfaces[i].getName());
918:                    }
919:                }
920:                if (signatures != null) {
921:                    for (int i = 0; i < signatures.length; i++) {
922:                        String sig = signatures[i];
923:                        List types = new ArrayList();
924:                        int idx0 = sig.indexOf('(');
925:                        if (idx0 < 0) {
926:                            continue;
927:                        }
928:                        String methodName = sig.substring(0, idx0);
929:                        int idx = parseTypes(sig, context, types);
930:                        Class[] parameterTypes = new Class[types.size()];
931:                        types.toArray(parameterTypes);
932:                        if (idx > 0) {
933:                            List types2 = returnTypeAndExceptions(sig
934:                                    .substring(idx), context);
935:                            Class returnType = (Class) types2.get(0);
936:                            String[] exceptionTypeInfo = null;
937:                            if (types2.size() > 1) {
938:                                exceptionTypeInfo = new String[types2.size() - 1];
939:                                for (int j = 0; j < exceptionTypeInfo.length; j++) {
940:                                    exceptionTypeInfo[j] = ((Class) types2
941:                                            .get(j + 1)).getName();
942:                                }
943:                            }
944:                            cf
945:                                    .openMethod(
946:                                            methodName,
947:                                            Signature.makeSignature(
948:                                                    parameterTypes, returnType),
949:                                            (short) (Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT),
950:                                            exceptionTypeInfo);
951:                            cf.closeMethod();
952:                        }
953:                    }
954:                }
955:                return cf;
956:            }
957:
958:            public static ClassLoader mergeClassLoader(Class[] types,
959:                    ClassLoader loader) {
960:                ArrayList classLoaders = new ArrayList();
961:                for (int i = 0; i < types.length; i++) {
962:                    Class type = types[i];
963:                    try {
964:                        if (loader.loadClass(type.getName()) == type) {
965:                            continue;
966:                        }
967:                    } catch (Exception e) {
968:                    }
969:                    classLoaders.add(type.getClassLoader());
970:                }
971:                int size = classLoaders.size();
972:                if (size > 0) {
973:                    ClassLoader[] cl = new ClassLoader[size];
974:                    classLoaders.toArray(cl);
975:                    return new MultiClassLoader(loader, cl);
976:                } else {
977:                    return loader;
978:                }
979:            }
980:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.