Source Code Cross Referenced for SimpleCompiler.java in  » Scripting » jacl » org » codehaus » janino » 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 » org.codehaus.janino 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Janino - An embedded Java[TM] compiler
003:         *
004:         * Copyright (c) 2006, Arno Unkrig
005:         * All rights reserved.
006:         *
007:         * Redistribution and use in source and binary forms, with or without
008:         * modification, are permitted provided that the following conditions
009:         * are met:
010:         *
011:         *    1. Redistributions of source code must retain the above copyright
012:         *       notice, this list of conditions and the following disclaimer.
013:         *    2. Redistributions in binary form must reproduce the above
014:         *       copyright notice, this list of conditions and the following
015:         *       disclaimer in the documentation and/or other materials
016:         *       provided with the distribution.
017:         *    3. The name of the author may not be used to endorse or promote
018:         *       products derived from this software without specific prior
019:         *       written permission.
020:         *
021:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
022:         * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
023:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024:         * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
025:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
026:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
027:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
029:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
030:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
031:         * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
032:         */
033:
034:        package org.codehaus.janino;
035:
036:        import java.io.*;
037:        import java.lang.reflect.*;
038:        import java.util.*;
039:
040:        import org.codehaus.janino.tools.Disassembler;
041:        import org.codehaus.janino.util.*;
042:        import org.codehaus.janino.util.enumerator.*;
043:
044:        import org.codehaus.janino.util.resource.PathResourceFinder;
045:
046:        /**
047:         * A simplified version of {@link Compiler} that can compile only a single
048:         * compilation unit. (A "compilation unit" is the characters stored in a
049:         * ".java" file.)
050:         * <p>
051:         * Opposed to a normal ".java" file, you can declare multiple public classes
052:         * here.
053:         * <p>
054:         * To set up a {@link SimpleCompiler} object, proceed as follows:
055:         * <ol>
056:         *   <li>
057:         *   Create the {@link SimpleCompiler} using {@link #SimpleCompiler()}
058:         *   <li>
059:         *   Optionally set an alternate parent class loader through
060:         *   {@link #setParentClassLoader(ClassLoader)}.
061:         *   <li>
062:         *   Call any of the {@link org.codehaus.janino.Cookable#cook(Scanner)} methods to scan,
063:         *   parse, compile and load the compilation unit into the JVM.
064:         * </ol>
065:         * Alternatively, a number of "convenience constructors" exist that execute the steps described
066:         * above instantly.
067:         */
068:        public class SimpleCompiler extends Cookable {
069:            private final static boolean DEBUG = false;
070:
071:            private final ClassLoaderIClassLoader DEFAULT_ICLASSLOADER = new ClassLoaderIClassLoader(
072:                    Thread.currentThread().getContextClassLoader());
073:            private ClassLoaderIClassLoader classLoaderIClassLoader = this .DEFAULT_ICLASSLOADER;
074:
075:            private ClassLoader classLoader = null; // null=uncooked
076:
077:            public static void main(String[] args) throws Exception {
078:                if (args.length < 1) {
079:                    System.err.println("Usage:");
080:                    System.err
081:                            .println("    org.codehaus.janino.SimpleCompiler <source-file> <class-name> <arg> [ ... ]");
082:                    System.err
083:                            .println("Reads a compilation unit from the given <source-file> and invokes method");
084:                    System.err
085:                            .println("\"public static void main(String[])\" of class <class-name>.");
086:                    System.exit(1);
087:                }
088:
089:                String sourceFileName = args[0];
090:                String className = args[1];
091:                String[] mainArgs = new String[args.length - 2];
092:                System.arraycopy(args, 2, mainArgs, 0, mainArgs.length);
093:
094:                ClassLoader cl = new SimpleCompiler(sourceFileName,
095:                        new FileInputStream(sourceFileName)).getClassLoader();
096:                Class c = cl.loadClass(className);
097:                Method m = c.getMethod("main", new Class[] { String[].class });
098:                m.invoke(null, new Object[] { mainArgs });
099:            }
100:
101:            /**
102:             * Equivalent to<pre>
103:             * SimpleCompiler sc = new SimpleCompiler();
104:             * sc.cook(optionalFileName, in);</pre>
105:             *
106:             * @see #SimpleCompiler()
107:             * @see Cookable#cook(String, Reader)
108:             */
109:            public SimpleCompiler(String optionalFileName, Reader in)
110:                    throws IOException, Scanner.ScanException,
111:                    Parser.ParseException, CompileException {
112:                this .cook(optionalFileName, in);
113:            }
114:
115:            /**
116:             * Equivalent to<pre>
117:             * SimpleCompiler sc = new SimpleCompiler();
118:             * sc.cook(optionalFileName, is);</pre>
119:             *
120:             * @see #SimpleCompiler()
121:             * @see Cookable#cook(String, InputStream)
122:             */
123:            public SimpleCompiler(String optionalFileName, InputStream is)
124:                    throws IOException, Scanner.ScanException,
125:                    Parser.ParseException, CompileException {
126:                this .cook(optionalFileName, is);
127:            }
128:
129:            /**
130:             * Equivalent to<pre>
131:             * SimpleCompiler sc = new SimpleCompiler();
132:             * sc.cook(fileName);</pre>
133:             *
134:             * @see #SimpleCompiler()
135:             * @see Cookable#cookFile(String)
136:             */
137:            public SimpleCompiler(String fileName) throws IOException,
138:                    Scanner.ScanException, Parser.ParseException,
139:                    CompileException {
140:                this .cookFile(fileName);
141:            }
142:
143:            /**
144:             * Equivalent to<pre>
145:             * SimpleCompiler sc = new SimpleCompiler();
146:             * sc.setParentClassLoader(optionalParentClassLoader);
147:             * sc.cook(scanner);</pre>
148:             *
149:             * @see #SimpleCompiler()
150:             * @see #setParentClassLoader(ClassLoader)
151:             * @see Cookable#cook(Scanner)
152:             */
153:            public SimpleCompiler(Scanner scanner,
154:                    ClassLoader optionalParentClassLoader) throws IOException,
155:                    Scanner.ScanException, Parser.ParseException,
156:                    CompileException {
157:                this .setParentClassLoader(optionalParentClassLoader);
158:                this .cook(scanner);
159:            }
160:
161:            public SimpleCompiler() {
162:            }
163:
164:            /**
165:             * This SimpleCompiler implementation is used when compiling Java
166:             * source code stored in a String value. The SimpleCompiler object
167:             * is created once and the CLASSPATH is setup. Then the compile()
168:             * method is invoked 1 or more times to compile Java class source
169:             * contained in a String object. Unlike the other implementations,
170:             * this version of the SimpleCompiler will not attempt to load the
171:             * compiled class data into the current thread using the class loader.
172:             * This implementation will just compile the source code into
173:             * an array of ClassFile objects.
174:             */
175:
176:            boolean noloadSimpleCompiler = false;
177:            IClassLoader icloader = null;
178:
179:            public SimpleCompiler(boolean noload) {
180:                //super(null);
181:                //this.classLoader = null;
182:                this .setParentClassLoader(null);
183:                if (noload == false) {
184:                    throw new RuntimeException("noload must be true");
185:                }
186:                noloadSimpleCompiler = true;
187:
188:                // Use context class loader unless explicit class loader is given
189:                //ClassLoader cloader = null;
190:                //if (cloader == null) {
191:                //    Thread cthread = Thread.currentThread();
192:                //    cloader = cthread.getContextClassLoader();
193:                //}
194:
195:                /*
196:                 // Load classes from the CLASSPATH
197:                 String classPath = System.getProperty("java.class.path");
198:                 System.out.println("classPath is \"" + classPath + "\"");
199:                 ResourceFinder classPathResourceFinder = new PathResourceFinder(
200:                 PathResourceFinder.parsePath(classPath));
201:
202:                 ResourceFinder classLoaderResourceFinder = new ResourceFinderClassLoader(            
203:                 classPathResourceFinder, cloader);
204:
205:                 IClassLoader icloader = new ResourceFinderIClassLoader(
206:                 //classPathResourceFinder,
207:                 classLoaderResourceFinder,
208:                 null);
209:
210:                 //cloader = new ResourceFinderClassLoader(classPathResourceFinder, cloader);
211:                 //ClassLoaderIClassLoader icloader = new ClassLoaderIClassLoader(cloader);
212:                 */
213:
214:                /*
215:                 // Load classes from the CLASSPATH
216:
217:                 String classPath = System.getProperty("java.class.path");
218:                 System.out.println("classPath is \"" + classPath + "\"");
219:                 ResourceFinder classPathResourceFinder = new PathResourceFinder(
220:                 PathResourceFinder.parsePath(classPath));
221:                 icloader = new ResourceFinderIClassLoader(
222:                 classPathResourceFinder,
223:                 null);
224:                 */
225:
226:                String classPath = System.getProperty("java.class.path");
227:                //System.out.println("CLASSPATH is \"" + classPath + "\"");
228:
229:                icloader = Compiler.createJavacLikePathIClassLoader(null, // optionalBootClassPath
230:                        null, // optionalExtDirs
231:                        PathResourceFinder.parsePath(classPath));
232:            }
233:
234:            public ClassFile[] compile(String javasrc) {
235:                if (!noloadSimpleCompiler) {
236:                    throw new RuntimeException(
237:                            "SimpleCompiler.compile() can only be used with "
238:                                    + "a SimpleCompiler() constructed with no arguments");
239:                }
240:
241:                try {
242:                    // FIXME: Not clear that this implementation is saving
243:                    // the Class data read from the CLASSPATH, keeping
244:                    // already read classes around would really speed things
245:                    // on successive compiles. Look more into optimizing this.
246:                    StringReader sreader = new StringReader(javasrc);
247:                    Scanner scanner = new Scanner(null, sreader);
248:                    Parser parser = new Parser(scanner);
249:                    Java.CompilationUnit cunit = parser.parseCompilationUnit();
250:
251:                    UnitCompiler ucompiler = new UnitCompiler(cunit, icloader);
252:                    EnumeratorSet defaultDebug = DebuggingInformation.DEFAULT_DEBUGGING_INFORMATION;
253:
254:                    ClassFile[] cfiles = ucompiler.compileUnit(defaultDebug);
255:                    return cfiles;
256:                } catch (Exception ex) {
257:                    ex.printStackTrace(System.err);
258:                    return null;
259:                }
260:            }
261:
262:            /**
263:             * The "parent class loader" is used to load referenced classes. It defaults to the current
264:             * thread's "context class loader".
265:             */
266:            public void setParentClassLoader(
267:                    ClassLoader optionalParentClassLoader) {
268:                this .classLoaderIClassLoader = (optionalParentClassLoader != null ? new ClassLoaderIClassLoader(
269:                        optionalParentClassLoader)
270:                        : this .DEFAULT_ICLASSLOADER);
271:            }
272:
273:            /**
274:             * Parse tokens delivered by the <code>scanner</code>, compile them and load them into the
275:             * JVM.
276:             * <p>
277:             * This method must be called exactly once.
278:             */
279:            protected void internalCook(Scanner scanner)
280:                    throws CompileException, Parser.ParseException,
281:                    Scanner.ScanException, IOException {
282:
283:                // Parse the compilation unit.
284:                Java.CompilationUnit compilationUnit = new Parser(scanner)
285:                        .parseCompilationUnit();
286:
287:                // Compile the classes and load them.
288:                this .compileToClassLoader(compilationUnit,
289:                        DebuggingInformation.DEFAULT_DEBUGGING_INFORMATION);
290:            }
291:
292:            /**
293:             * Returns a {@link ClassLoader} object through which the previously compiled classes can
294:             * be accessed. This {@link ClassLoader} can be used for subsequent calls to
295:             * {@link #SimpleCompiler(Scanner, ClassLoader)} in order to compile compilation units that
296:             * use types (e.g. declare derived types) declared in the previous one.
297:             * <p>
298:             * This method must only be called after {@link #cook(Scanner)}.
299:             * <p>
300:             * This method must not be called for instances of derived classes.
301:             */
302:            public ClassLoader getClassLoader() {
303:                if (this .getClass() != SimpleCompiler.class)
304:                    throw new IllegalStateException(
305:                            "Must not be called on derived instances");
306:                if (this .classLoader == null)
307:                    throw new IllegalStateException(
308:                            "Must only be called after \"cook()\"");
309:                return this .classLoader;
310:            }
311:
312:            /**
313:             * Two {@link SimpleCompiler}s are regarded equal iff
314:             * <ul>
315:             *   <li>Both are objects of the same class (e.g. both are {@link ScriptEvaluator}s)
316:             *   <li>Both generated functionally equal classes as seen by {@link ByteArrayClassLoader#equals(Object)}
317:             * </ul>
318:             */
319:            public boolean equals(Object o) {
320:                if (!(o instanceof  SimpleCompiler))
321:                    return false;
322:                SimpleCompiler that = (SimpleCompiler) o;
323:                if (this .getClass() != that.getClass())
324:                    return false;
325:                if (this .classLoader == null || that.classLoader == null)
326:                    throw new IllegalStateException(
327:                            "Equality can only be checked after cooking");
328:                return this .classLoader.equals(that.classLoader);
329:            }
330:
331:            public int hashCode() {
332:                return this .classLoader.hashCode();
333:            }
334:
335:            /**
336:             * Wrap a reflection {@link Class} in a {@link Java.Type} object.
337:             */
338:            protected Java.Type classToType(Location location,
339:                    final Class optionalClass) {
340:                if (optionalClass == null)
341:                    return null;
342:
343:                IClass iClass;
344:                try {
345:                    iClass = this .classLoaderIClassLoader.loadIClass(Descriptor
346:                            .fromClassName(optionalClass.getName()));
347:                } catch (ClassNotFoundException ex) {
348:                    throw new RuntimeException("Loading IClass \""
349:                            + optionalClass.getName() + "\": " + ex);
350:                }
351:                if (iClass == null)
352:                    throw new RuntimeException("Cannot load class \""
353:                            + optionalClass.getName()
354:                            + "\" through the given ClassLoader");
355:
356:                return new Java.SimpleType(location, iClass);
357:            }
358:
359:            /**
360:             * Convert an array of {@link Class}es into an array of{@link Java.Type}s.
361:             */
362:            protected Java.Type[] classesToTypes(Location location,
363:                    Class[] classes) {
364:                Java.Type[] types = new Java.Type[classes.length];
365:                for (int i = 0; i < classes.length; ++i) {
366:                    types[i] = this .classToType(location, classes[i]);
367:                }
368:                return types;
369:            }
370:
371:            /**
372:             * Compile the given compilation unit. (A "compilation unit" is typically the contents
373:             * of a Java<sup>TM</sup> source file.)
374:             * 
375:             * @param compilationUnit The parsed compilation unit
376:             * @param debuggingInformation What kind of debugging information to generate in the class file
377:             * @return The {@link ClassLoader} into which the compiled classes were defined
378:             * @throws CompileException
379:             */
380:            protected ClassLoader compileToClassLoader(
381:                    Java.CompilationUnit compilationUnit,
382:                    EnumeratorSet debuggingInformation) throws CompileException {
383:                if (SimpleCompiler.DEBUG) {
384:                    UnparseVisitor.unparse(compilationUnit,
385:                            new OutputStreamWriter(System.out));
386:                }
387:
388:                // Compile compilation unit to class files.
389:                ClassFile[] classFiles = new UnitCompiler(compilationUnit,
390:                        this .classLoaderIClassLoader)
391:                        .compileUnit(debuggingInformation);
392:
393:                // Convert the class files to bytes and store them in a Map.
394:                Map classes = new HashMap(); // String className => byte[] data
395:                for (int i = 0; i < classFiles.length; ++i) {
396:                    ClassFile cf = classFiles[i];
397:                    classes.put(cf.getThisClassName(), cf.toByteArray());
398:                }
399:
400:                // Disassemble all generated classes (for debugging).
401:                if (SimpleCompiler.DEBUG) {
402:                    //            try {
403:                    //                Disassembler.disasm(new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }));
404:                    //            } catch (IOException e) {
405:                    //                // TODO Auto-generated catch block
406:                    //                e.printStackTrace();
407:                    //            }
408:                    for (Iterator it = classes.entrySet().iterator(); it
409:                            .hasNext();) {
410:                        Map.Entry me = (Map.Entry) it.next();
411:                        String className = (String) me.getKey();
412:                        byte[] bytecode = (byte[]) me.getValue();
413:                        System.out.println("*** Disassembly of class \""
414:                                + className + "\":");
415:                        try {
416:                            new Disassembler().disasm(new ByteArrayInputStream(
417:                                    bytecode));
418:                            System.out.flush();
419:                        } catch (IOException ex) {
420:                            throw new RuntimeException(
421:                                    "SNO: IOException despite ByteArrayInputStream");
422:                        }
423:                    }
424:                }
425:
426:                // Create a ClassLoader that loads the generated classes.
427:                this .classLoader = new ByteArrayClassLoader(classes, // classes
428:                        this .classLoaderIClassLoader.getClassLoader() // parent
429:                );
430:                return this.classLoader;
431:            }
432:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.