Source Code Cross Referenced for TJCCompileCmd.java in  » Scripting » jacl » tcl » 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 » jacl » tcl.lang 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2005 Advanced Micro Devices, Inc.
003:         *
004:         * See the file "license.amd" for information on usage and
005:         * redistribution of this file, and for a DISCLAIMER OF ALL
006:         * WARRANTIES.
007:         * 
008:         * RCS: @(#) $Id: TJCCompileCmd.java,v 1.4 2006/08/06 00:38:58 mdejong Exp $
009:         *
010:         */
011:
012:        package tcl.lang;
013:
014:        import java.util.ArrayList;
015:
016:        public class TJCCompileCmd implements  Command {
017:
018:            // Implementation of TJC::compile used to compile
019:            // Tcl commands into Java byte code and load them
020:            // into the JVM at runtime.
021:
022:            public void cmdProc(Interp interp, TclObject[] objv)
023:                    throws TclException {
024:                // Usage:
025:                //
026:                // TJC::compile cmd
027:                // TJC::compile cmd -readycmd {my_command_ready_cmd}
028:                // TJC::compile cmd -readyvar myarr(cmd)
029:                //
030:                // TJC::compile -java JINFO -readycmd {my_java_ready_cmd}
031:                // TJC::compile -java JINFO -readyvar my_java_status
032:
033:                if (objv.length < 2 || objv.length == 3 || objv.length > 5) {
034:                    throw new TclNumArgsException(interp, 1, objv,
035:                            "?cmd? ?options?");
036:                }
037:
038:                String javaInfo = null;
039:                String cmd = null;
040:                String readycmd = null;
041:                String readyvar = null;
042:                int next;
043:
044:                // Argument 1 can be a command name or -java
045:                // if there are 3 or more arguments
046:
047:                cmd = objv[1].toString();
048:
049:                if (cmd.equals("-java")) {
050:                    // -java usage requires either a -readycmd
051:                    // or a -readyvar argument pair since
052:                    // the user code needs some way to know
053:                    // when the source has been compiled
054:                    // and loaded into the JVM.
055:
056:                    if (objv.length != 5) {
057:                        throw new TclNumArgsException(interp, 1, objv,
058:                                "?cmd? ?options?");
059:                    }
060:
061:                    // javaInfo should be a list of length 2, with the
062:                    // following contents: {JCLASSNAME JSRCCODE}
063:
064:                    TclObject obj = objv[2];
065:                    if (TclList.getLength(interp, obj) != 2) {
066:                        throw new TclException(interp,
067:                                "-java JINFO argument must be a 2 element list of {JCLASSNAME JSRCCODE}");
068:                    }
069:                    javaInfo = objv[2].toString();
070:                    cmd = null;
071:                    next = 3;
072:                } else {
073:                    next = 2;
074:                }
075:
076:                if (next == objv.length) {
077:                    // TJC::command cmd
078:                } else {
079:                    // There should be 2 more arguments, either
080:                    // -readycmd cmd or -readyvar var.
081:
082:                    if ((next + 2) != objv.length) {
083:                        throw new TclNumArgsException(interp, 1, objv,
084:                                "?cmd? ?options?");
085:                    }
086:
087:                    String option = objv[next].toString();
088:                    String value = objv[next + 1].toString();
089:
090:                    if (option.equals("-readycmd")) {
091:                        readycmd = value;
092:                    } else if (option.equals("-readyvar")) {
093:                        readyvar = value;
094:                    } else {
095:                        throw new TclNumArgsException(interp, 1, objv,
096:                                "?cmd? ?options?");
097:                    }
098:                }
099:
100:                // Double check settings
101:
102:                if (javaInfo != null && cmd != null) {
103:                    throw new TclRuntimeError("can set both cmd and -java");
104:                }
105:                if (readycmd != null && readyvar != null) {
106:                    throw new TclRuntimeError(
107:                            "can set both -readyvar and -readycmd");
108:                }
109:
110:                // If compiling a Java class, init helper method that
111:                // will be invoked when the Java method is compiled.
112:
113:                if (javaInfo != null) {
114:                    JavaCompile(interp, javaInfo, readycmd, readyvar);
115:                } else {
116:                    TclCompile(interp, cmd, readycmd, readyvar);
117:                }
118:
119:                return;
120:            }
121:
122:            // Process Java source code, compile it to byte code and
123:            // then load the byte code into the interp.
124:
125:            static void JavaCompile(Interp interp, String javaInfo,
126:                    String readyCmd, String readyVar) throws TclException {
127:                // Make sure compiler thread is running
128:                TJCThread.startThread();
129:
130:                TJCCompileJavaCmd cjobj = new TJCCompileJavaCmd(interp,
131:                        javaInfo, readyCmd, readyVar);
132:
133:                // The fully qualified Java source file name must be passed
134:                // to the compiler layer. For example, a class named Test11
135:                // in the package foo.bar must be compiled with the source
136:                // file name "foo/bar/Test11.java". The user needs to pass
137:                // the class name in the JINFO argument, so construct the
138:                // Java file name from the Java class name.
139:
140:                String javaFileName = cjobj.getJavaFileName();
141:                String javaSrc = cjobj.getJavaSource();
142:
143:                if (cjobj.debug) {
144:                    System.out.println("Sending Java file name: "
145:                            + javaFileName);
146:                    System.out.println("Sending javaSrc:\n" + javaSrc);
147:                }
148:
149:                TJCThread.compileJavaSource(javaFileName, javaSrc, cjobj);
150:            }
151:
152:            // Compile Tcl proc currently defined in the interpreter.
153:
154:            static void TclCompile(Interp interp, String cmd, String readyCmd,
155:                    String readyVar) throws TclException {
156:                int i, len;
157:
158:                String fullyQualifiedCmd;
159:
160:                // Make sure compiler thread is running
161:                TJCThread.startThread();
162:
163:                // Lookup Procedure in the interp.
164:
165:                Procedure proc = Procedure.findProc(interp, cmd);
166:                if (proc == null) {
167:                    throw new TclException(interp, "\"" + cmd
168:                            + "\" isn't a procedure");
169:                }
170:
171:                // Generate non-unique Java class name based on the
172:                // Tcl proc name. The proc includes any namespace
173:                // qualifiers.
174:
175:                StringBuffer pname = new StringBuffer(64);
176:                StringBuffer cname = new StringBuffer(64);
177:
178:                if (cmd.startsWith("::")) {
179:                    // already fully qualified
180:                    pname.append(cmd);
181:                } else {
182:                    // make it fully qualified
183:                    String nsName = proc.wcmd.ns.fullName;
184:
185:                    if (nsName.equals("::")) {
186:                        pname.append(nsName);
187:                    } else {
188:                        pname.append(nsName);
189:                        pname.append("::");
190:                    }
191:                    pname.append(NamespaceCmd.tail(cmd));
192:                }
193:
194:                if (false) {
195:                    // Debug
196:                    interp.eval("namespace current", 0);
197:                    String cns = interp.getResult().toString();
198:                    System.out.println("current namespace is \"" + cns + "\"");
199:                    System.out.println("looked up proc \"" + cmd + "\"");
200:                    System.out.println("found proc in namespace \""
201:                            + proc.wcmd.ns.fullName + "\"");
202:                    System.out.println("fully qualified name is \""
203:                            + pname.toString());
204:                }
205:
206:                // Generate Java class name for Tcl proc
207:
208:                fullyQualifiedCmd = pname.toString();
209:
210:                String upper = fullyQualifiedCmd;
211:                boolean cap = true;
212:                len = upper.length();
213:                for (i = 0; i < len; i++) {
214:                    char c = upper.charAt(i);
215:                    if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')
216:                            || (c >= '0' && c <= '9')) {
217:                        if (cap) {
218:                            c = Character.toUpperCase(c);
219:                            cap = false;
220:                        }
221:                        cname.append(c);
222:                    } else {
223:                        cap = true;
224:                    }
225:                }
226:                cname.append("Cmd");
227:                String javaClassName = cname.toString();
228:
229:                // Determine if a Tcl proc with this name
230:                // was already compiled and loaded into
231:                // the current ClassLoader. In this case,
232:                // we need to make the Java class name
233:                // unique so that the ClassLoader does not
234:                // fail to load the class once it has
235:                // been compiled.
236:
237:                if (isClassDefined(interp, javaClassName)) {
238:                    String prefix = cname.toString();
239:                    String suffix = null;
240:
241:                    for (i = 2; i < Integer.MAX_VALUE; i++) {
242:                        suffix = String.valueOf(i);
243:
244:                        if (!isClassDefined(interp, prefix + suffix)) {
245:                            break;
246:                        }
247:                    }
248:                    if (i == Integer.MAX_VALUE) {
249:                        // This should never happen
250:                        throw new TclRuntimeError("suffix integer overflow");
251:                    }
252:
253:                    cname.append(suffix);
254:                    javaClassName = cname.toString();
255:                }
256:
257:                // Generate proc declaration
258:
259:                TclObject procList = TclList.newInstance();
260:                TclList.append(interp, procList, TclString.newInstance("proc"));
261:                TclList.append(interp, procList, TclString.newInstance(cmd));
262:
263:                // Build up args list from the Procedure object
264:
265:                TclObject args = TclList.newInstance();
266:                len = proc.argList.length;
267:                for (i = 0; i < len; i++) {
268:                    TclObject name = proc.argList[i][0];
269:                    TclObject defval = proc.argList[i][1];
270:
271:                    if (defval == null) {
272:                        TclList.append(interp, args, TclString.newInstance(name
273:                                .toString()));
274:                    } else {
275:                        TclObject defpair = TclList.newInstance();
276:                        TclList.append(interp, defpair, TclString
277:                                .newInstance(name.toString()));
278:                        TclList.append(interp, defpair, TclString
279:                                .newInstance(defval.toString()));
280:                        TclList.append(interp, args, defpair);
281:                    }
282:                }
283:                if (proc.isVarArgs) {
284:                    TclList.append(interp, args, TclString.newInstance("args"));
285:                }
286:                TclList.append(interp, procList, TclString.newInstance(args));
287:
288:                // Get proc body and append it to the proc decl
289:
290:                TclList.append(interp, procList, TclString
291:                        .newInstance(proc.body.toString()));
292:
293:                TJCCompileTclCmd ctobj = new TJCCompileTclCmd(interp,
294:                        fullyQualifiedCmd, readyCmd, readyVar);
295:
296:                if (ctobj.debug) {
297:                    System.out.println("Sending proc decl\n"
298:                            + procList.toString());
299:                }
300:
301:                TJCThread.compileTclSource(javaClassName, procList.toString(),
302:                        ctobj);
303:            }
304:
305:            // Return true if a Java class with the given name has
306:            // already been defined in the ClassLoader for the
307:            // given interp.
308:
309:            static boolean isClassDefined(Interp interp, String javaClassName) {
310:                final boolean debug = false;
311:
312:                TclClassLoader tclClassLoader = (TclClassLoader) interp
313:                        .getClassLoader();
314:                Class alreadyLoaded = null;
315:
316:                try {
317:                    if (debug) {
318:                        System.out
319:                                .println("checking for duplicate class name : "
320:                                        + javaClassName);
321:                    }
322:
323:                    alreadyLoaded = tclClassLoader.loadClass(javaClassName);
324:                } catch (ClassNotFoundException e) {
325:                    // No-op
326:                } catch (PackageNameException e) {
327:                    // Should not be possible to catch a PackageNameException
328:                    // since the Java class is not in the tcl.* or java.* packages.
329:
330:                    throw new TclRuntimeError(
331:                            "unexpected PackageNameException :"
332:                                    + e.getMessage());
333:                }
334:
335:                boolean isDefined = (alreadyLoaded != null);
336:
337:                if (debug) {
338:                    System.out.println("class isDefined is " + isDefined);
339:                }
340:
341:                return isDefined;
342:            }
343:
344:        } // end class TJCCompileCmd
345:
346:        // Helper class to load compiled class into the
347:        // current thread and register a compiled command
348:        // implementation in the current interp. An
349:        // instance of this object is created for each
350:        // command that is compiled.
351:
352:        class TJCCompileTclCmd extends TclEvent implements 
353:                TJCThread.CompiledClassReady {
354:            final boolean debug = false;
355:
356:            final Interp interp;
357:            final String cmd;
358:            final String readyCmd;
359:            final String readyVar;
360:
361:            boolean status;
362:            String errorMsg = "";
363:            String className = null; // Java class name for this command
364:            byte[] classBytes = null; // Java class bytes for this command
365:
366:            TJCCompileTclCmd(Interp interp, String cmd, String readyCmd,
367:                    String readyVar) {
368:                this .interp = interp;
369:                this .cmd = cmd;
370:                this .readyCmd = readyCmd;
371:                this .readyVar = readyVar;
372:            }
373:
374:            // Invoked by TJCThread when a compile job is finished.
375:            // This implementation will queue an event in the original
376:            // thread that will replace the Tcl command with a
377:            // compiled implementation of the command.
378:
379:            public void compiled(final String geninfo, // Name of Tcl command that was compiled.
380:                    final String jfilename, // File name for Java source,
381:                    // like "Test.java".
382:                    final String jsrcode, // Java source that was compiled.
383:                    final ArrayList cnames, // List of compiled class names.
384:                    final ArrayList cdata, // List of compiled class data as byte[].
385:                    final int status, final String msg) {
386:                // Add an event to the thread safe Tcl event queue that
387:                // will replace the existing command with a compiled one.
388:
389:                if (debug) {
390:                    System.out
391:                            .println("TJCCompileTclCmd CompiledClassReady.compiled()");
392:                    System.out.println("geninfo was " + geninfo);
393:                    System.out.println("jfilename was " + jfilename);
394:                    System.out.println("jsrcode was " + jsrcode);
395:                    System.out.println("cnames was " + cnames);
396:                    if (cdata == null) {
397:                        System.out.println("cdata was null");
398:                    } else {
399:                        System.out.println("cdata length was " + cdata.size());
400:                    }
401:                }
402:
403:                // Check compile status:
404:
405:                if (status == TJCThread.STATUS_OK) {
406:                    this .status = true;
407:
408:                    if (debug) {
409:                        System.out.println("Status was OK");
410:                    }
411:                } else {
412:                    this .status = false;
413:                    this .errorMsg = msg;
414:
415:                    if (debug) {
416:                        System.out.println("Status was not OK");
417:                        System.out.println("errorMsg was \"" + this .errorMsg
418:                                + "\"");
419:                    }
420:                }
421:
422:                // Tcl command should compile into one class file.
423:
424:                if (cdata == null) {
425:                    // Error should be indicated in errorMsg
426:                } else if (cdata.size() == 1) {
427:                    className = (String) cnames.get(0); // Name of class, could be null if not known
428:                    classBytes = (byte[]) cdata.get(0);
429:                } else {
430:                    this .status = false;
431:                    this .errorMsg = "unexpected number of class files "
432:                            + cdata.size();
433:
434:                    if (debug) {
435:                        System.out.println("Status was not OK");
436:                        System.out.println("errorMsg was \"" + this .errorMsg
437:                                + "\"");
438:                    }
439:                }
440:
441:                interp.getNotifier().queueEvent(this , TCL.QUEUE_TAIL);
442:
443:                // Don't wait for the event to be processed in the
444:                // original thread. Just continue to process the
445:                // next event in TJCThread.
446:                //event.sync();
447:            }
448:
449:            // Invoked by the original thread (not by TJCThread)
450:            // when the original thread enters the event loop.
451:            // This method will replace the Tcl proc with the
452:            // compiled implementation of the proc.
453:
454:            public int processEvent(int flags) {
455:                if (debug) {
456:                    System.out.println("TJCCompileTclCmd.processEvent()");
457:                }
458:
459:                // If the compile failed, report that now
460:                if (status == false) {
461:                    readyReport();
462:                    return 1;
463:                }
464:
465:                // Otherwise, load the class file via the TclClassLoader
466:                // and replace the Tcl proc with the compiled command.
467:
468:                TclClassLoader tclClassLoader = (TclClassLoader) interp
469:                        .getClassLoader();
470:                // Flush class loader cache in case it holds the last ref to
471:                // a previously loaded version of this same class (Tcl command).
472:                if (className != null) {
473:                    tclClassLoader.removeCache(className);
474:                }
475:                Class class_obj = tclClassLoader.defineClass(className,
476:                        classBytes);
477:                if (class_obj == null) {
478:                    // Class could not be loaded, status is fail
479:                    status = false;
480:                    errorMsg = "class not loaded by TclClassLoader";
481:                    readyReport();
482:                    return 1;
483:                }
484:
485:                Object o = null;
486:                String instErr = null;
487:                if (className == null) {
488:                    className = class_obj.getName();
489:                }
490:                try {
491:                    o = class_obj.newInstance();
492:                } catch (InstantiationException ie) {
493:                    instErr = "instance of class " + className
494:                            + " could not be created";
495:                } catch (IllegalAccessException iae) {
496:                    instErr = "instance of class " + className
497:                            + " could not be created";
498:                }
499:                if (!(o instanceof  TJC.CompiledCommand)) {
500:                    instErr = "instance of class " + className
501:                            + " must extend TJC.CompiledCommand";
502:                }
503:                if (instErr != null) {
504:                    status = false;
505:                    errorMsg = instErr;
506:                    readyReport();
507:                    return 1;
508:                }
509:                TJC.CompiledCommand cmdObj = (TJC.CompiledCommand) o;
510:                try {
511:                    if (debug) {
512:                        System.out.println("now to create command \"" + cmd
513:                                + "\"");
514:                    }
515:                    TJC.createCommand(interp, cmd, cmdObj);
516:                } catch (TclException te) {
517:                    status = false;
518:                    errorMsg = te.getMessage();
519:                    readyReport();
520:                    return 1;
521:                }
522:
523:                readyReport(); // Report success
524:                return 1;
525:            }
526:
527:            // This method is invoked to indicate that a command has been
528:            // compiled and installer, or that it failed. This method
529:            // will set a -readyvar or invoke a -readycmd callback
530:            // if one was indicated via the TJC::compile command.
531:
532:            void readyReport() {
533:                try {
534:
535:                    if (readyVar != null) {
536:                        // Set readyVar to: {STATUS CMDNAME MSG}
537:                        //
538:                        // STATUS: OK or FAIL
539:                        // CMDNAME: Name of Tcl command
540:                        // MSG: text of error message if (STATUS == FAIL)
541:
542:                        TclObject tlist = TclList.newInstance();
543:
544:                        // STATUS:
545:                        if (status) {
546:                            TclList.append(interp, tlist, TclString
547:                                    .newInstance("OK"));
548:                        } else {
549:                            TclList.append(interp, tlist, TclString
550:                                    .newInstance("FAIL"));
551:                        }
552:
553:                        // CMDNAME:
554:                        TclList.append(interp, tlist, TclString
555:                                .newInstance(cmd));
556:
557:                        // MSG:
558:                        TclList.append(interp, tlist, TclString
559:                                .newInstance(errorMsg));
560:
561:                        if (debug) {
562:                            System.out.println("now to set readyVar: "
563:                                    + readyVar + " " + tlist);
564:                        }
565:
566:                        interp.setVar(readyVar, null, tlist, TCL.GLOBAL_ONLY);
567:                    } else if (readyCmd != null) {
568:                        // Invoke readyCmd with the following arguments:
569:                        // readyCmd STATUS CMDNAME MSG
570:                        //
571:                        // STATUS: OK or FAIL
572:                        // CMDNAME: Name of Tcl command
573:                        // MSG: text of error message if (STATUS == FAIL)
574:
575:                        TclObject tlist = TclList.newInstance();
576:
577:                        // readyCmd
578:                        TclList.append(interp, tlist, TclString
579:                                .newInstance(readyCmd));
580:
581:                        // STATUS:
582:                        if (status) {
583:                            TclList.append(interp, tlist, TclString
584:                                    .newInstance("OK"));
585:                        } else {
586:                            TclList.append(interp, tlist, TclString
587:                                    .newInstance("FAIL"));
588:                        }
589:
590:                        // CMDNAME:
591:                        TclList.append(interp, tlist, TclString
592:                                .newInstance(cmd));
593:
594:                        // MSG:
595:                        TclList.append(interp, tlist, TclString
596:                                .newInstance(errorMsg));
597:
598:                        if (debug) {
599:                            System.out
600:                                    .println("now to eval readyCmd: " + tlist);
601:                        }
602:
603:                        interp.eval(tlist, TCL.EVAL_GLOBAL);
604:                    }
605:
606:                } catch (TclException te) {
607:                    // TclException should not be thrown above
608:                    te.printStackTrace(System.err);
609:                }
610:            }
611:        }
612:
613:        // Helper class to load compiled class into the current
614:        // thread.
615:
616:        class TJCCompileJavaCmd extends TclEvent implements 
617:                TJCThread.CompiledClassReady {
618:            final boolean debug = false;
619:
620:            final Interp interp;
621:            final TclObject javaInfo;
622:            final String readyCmd;
623:            final String readyVar;
624:
625:            boolean status;
626:            String errorMsg = "";
627:
628:            ArrayList cnames; // Array of class names
629:            ArrayList cdata; // Array of class bytes
630:
631:            TJCCompileJavaCmd(Interp interp, String javaInfo, String readyCmd,
632:                    String readyVar) {
633:                this .interp = interp;
634:                // Allocate new TclObject so we don't need to worry about
635:                // releasing it.
636:                this .javaInfo = TclString.newInstance(javaInfo);
637:                this .readyCmd = readyCmd;
638:                this .readyVar = readyVar;
639:            }
640:
641:            // Invoked by TJCThread when a compile job is finished.
642:            // This implementation will queue an event in the original
643:            // thread that will define the Java class.
644:
645:            public void compiled(final String geninfo, // Unused
646:                    final String jfilename, // File name for Java source,
647:                    // like "Test.java".
648:                    final String jsrcode, // Java source that was compiled.
649:                    final ArrayList cnames, // List of compiled class names.
650:                    final ArrayList cdata, // List of compiled class data as byte[].
651:                    final int status, final String msg) {
652:                // Add an event to the thread safe Tcl event queue that
653:                // will define the Java class.
654:
655:                if (debug) {
656:                    System.out
657:                            .println("TJCCompileJavaCmd CompiledClassReady.compiled()");
658:                    System.out.println("geninfo was " + geninfo);
659:                    System.out.println("jfilename was " + jfilename);
660:                    System.out.println("jsrcode was " + jsrcode);
661:                    System.out.println("cnames was " + cnames);
662:                    if (cdata == null) {
663:                        System.out.println("cdata was null");
664:                    } else {
665:                        System.out.println("cdata length was " + cdata.size());
666:                    }
667:                }
668:
669:                // Check compile status:
670:
671:                if (status == TJCThread.STATUS_OK) {
672:                    this .status = true;
673:
674:                    if (debug) {
675:                        System.out.println("Status was OK");
676:                    }
677:                } else {
678:                    this .status = false;
679:                    this .errorMsg = msg;
680:
681:                    if (debug) {
682:                        System.out.println("Status was not OK");
683:                        System.out.println("errorMsg was \"" + this .errorMsg
684:                                + "\"");
685:                    }
686:                }
687:
688:                // A Java class declaration can compile into multiple classes.
689:
690:                if (cdata == null) {
691:                    // Error should be indicated in errorMsg
692:                } else {
693:                    this .cnames = cnames;
694:                    this .cdata = cdata;
695:                }
696:
697:                interp.getNotifier().queueEvent(this , TCL.QUEUE_TAIL);
698:
699:                // Don't wait for the event to be processed in the
700:                // original thread. Just continue to process the
701:                // next event in TJCThread.
702:                //event.sync();
703:            }
704:
705:            // Invoked by the original thread (not by TJCThread)
706:            // when the original thread enters the event loop.
707:            // This method will define the Java class in
708:            // the interpreter.
709:
710:            public int processEvent(int flags) {
711:                Class cl;
712:
713:                if (debug) {
714:                    System.out.println("TJCCompileJavaCmd.processEvent()");
715:                }
716:
717:                // If the compile failed, report that now
718:                if (status == false) {
719:                    readyReport();
720:                    return 1;
721:                }
722:
723:                // Otherwise, load the classes via the TclClassLoader.
724:
725:                TclClassLoader tclClassLoader = (TclClassLoader) interp
726:                        .getClassLoader();
727:
728:                // Class names may or may not be known, if class name is the empty
729:                // string then query the class name from the class object after
730:                // the class is defined.
731:
732:                ArrayList resolved_cnames = new ArrayList();
733:
734:                for (int i = 0; i < cdata.size(); i++) {
735:                    String cname = null;
736:                    if (cnames != null) {
737:                        cname = (String) cnames.get(i);
738:                        if (cname.length() == 0) {
739:                            cname = null;
740:                        }
741:                    }
742:                    byte[] classBytes = (byte[]) cdata.get(i);
743:                    cl = tclClassLoader.defineClass(cname, classBytes);
744:                    if (cl == null) {
745:                        // Class could not be loaded, status is fail
746:                        status = false;
747:                        if (cname != null) {
748:                            errorMsg = "class \"" + cname
749:                                    + "\" not loaded by TclClassLoader";
750:                        } else {
751:                            errorMsg = "class not loaded by TclClassLoader";
752:                        }
753:                        readyReport();
754:                        return 1;
755:                    }
756:                    if (cname == null) {
757:                        cname = cl.getName();
758:                    }
759:                    resolved_cnames.add(cname);
760:                }
761:                cnames = resolved_cnames;
762:
763:                readyReport(); // Report success
764:                return 1;
765:            }
766:
767:            // This method is invoked to indicate that a Java class
768:            // was compiled and loaded, or that it failed. This method
769:            // will set a -readyvar or invoke a -readycmd callback
770:            // if one was indicated via the TJC::compile command.
771:
772:            void readyReport() {
773:                try {
774:
775:                    if (readyVar != null) {
776:                        // Set readyVar to: {STATUS CLASSNAMES MSG}
777:                        //
778:                        // STATUS: OK or FAIL
779:                        // CLASSNAMES: List of fully qualified Java class names
780:                        // MSG: text of error message if (STATUS == FAIL)
781:
782:                        TclObject tlist = TclList.newInstance();
783:
784:                        // STATUS:
785:                        if (status) {
786:                            TclList.append(interp, tlist, TclString
787:                                    .newInstance("OK"));
788:                        } else {
789:                            TclList.append(interp, tlist, TclString
790:                                    .newInstance("FAIL"));
791:                        }
792:
793:                        // CLASSNAMES:
794:                        TclObject cnames_list = TclList.newInstance();
795:                        if (cnames != null) {
796:                            for (int i = 0; i < cnames.size(); i++) {
797:                                String cname = (String) cnames.get(i);
798:                                TclList.append(interp, cnames_list, TclString
799:                                        .newInstance(cname));
800:                            }
801:                        }
802:                        TclList.append(interp, tlist, cnames_list);
803:
804:                        // MSG:
805:                        TclList.append(interp, tlist, TclString
806:                                .newInstance(errorMsg));
807:
808:                        if (debug) {
809:                            System.out.println("now to set readyVar: "
810:                                    + readyVar + " " + tlist);
811:                        }
812:
813:                        interp.setVar(readyVar, null, tlist, TCL.GLOBAL_ONLY);
814:                    } else if (readyCmd != null) {
815:                        // Invoke readyCmd with the following arguments:
816:                        // readyCmd STATUS CLASSNAMES MSG
817:                        //
818:                        // STATUS: OK or FAIL
819:                        // CLASSNAMES: List of fully qualified Java class names
820:                        // MSG: text of error message if (STATUS == FAIL)
821:
822:                        TclObject tlist = TclList.newInstance();
823:
824:                        // readyCmd
825:                        TclList.append(interp, tlist, TclString
826:                                .newInstance(readyCmd));
827:
828:                        // STATUS:
829:                        if (status) {
830:                            TclList.append(interp, tlist, TclString
831:                                    .newInstance("OK"));
832:                        } else {
833:                            TclList.append(interp, tlist, TclString
834:                                    .newInstance("FAIL"));
835:                        }
836:
837:                        // CLASSNAMES:
838:                        TclObject cnames_list = TclList.newInstance();
839:                        if (cnames != null) {
840:                            for (int i = 0; i < cnames.size(); i++) {
841:                                String cname = (String) cnames.get(i);
842:                                TclList.append(interp, cnames_list, TclString
843:                                        .newInstance(cname));
844:                            }
845:                        }
846:                        TclList.append(interp, tlist, cnames_list);
847:
848:                        // MSG:
849:                        TclList.append(interp, tlist, TclString
850:                                .newInstance(errorMsg));
851:
852:                        if (debug) {
853:                            System.out
854:                                    .println("now to eval readyCmd: " + tlist);
855:                        }
856:
857:                        interp.eval(tlist, TCL.EVAL_GLOBAL);
858:                    }
859:
860:                } catch (TclException te) {
861:                    // TclException should not be thrown above
862:                    te.printStackTrace(System.err);
863:                }
864:            }
865:
866:            // Get the fully qualified Java file name for the given
867:            // javaInfo pair.
868:
869:            String getJavaFileName() throws TclException {
870:                TclObject obj = TclList.index(interp, javaInfo, 0);
871:                String clName = obj.toString();
872:
873:                // Generate file name from the class name.
874:                // "Foo" -> "Foo.java"
875:                // "one.two.Three" -> "one/two/Three.java"
876:
877:                StringBuffer nbuff = new StringBuffer(64);
878:                if (clName.indexOf('.') == -1) {
879:                    // Default package
880:                    nbuff.append(clName);
881:                } else {
882:                    // Replace each instance of '.' with '/'
883:                    nbuff.append(clName.replace('.', '/'));
884:                }
885:                nbuff.append(".java");
886:                return nbuff.toString();
887:            }
888:
889:            // Get the Java source code portion of the javaInfo pair.
890:
891:            String getJavaSource() throws TclException {
892:                TclObject src = TclList.index(interp, javaInfo, 1);
893:                return src.toString();
894:            }
895:
896:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.