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


001:        /*
002:         * Janino - An embedded Java[TM] compiler
003:         *
004:         * Copyright (c) 2001-2007, 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:        /**
045:         * A simplified version of {@link Compiler} that can compile only a single
046:         * compilation unit. (A "compilation unit" is the characters stored in a
047:         * ".java" file.)
048:         * <p>
049:         * Opposed to a normal ".java" file, you can declare multiple public classes
050:         * here.
051:         * <p>
052:         * To set up a {@link SimpleCompiler} object, proceed as follows:
053:         * <ol>
054:         *   <li>
055:         *   Create the {@link SimpleCompiler} using {@link #SimpleCompiler()}
056:         *   <li>
057:         *   Optionally set an alternate parent class loader through
058:         *   {@link #setParentClassLoader(ClassLoader)}.
059:         *   <li>
060:         *   Call any of the {@link org.codehaus.janino.Cookable#cook(Scanner)} methods to scan,
061:         *   parse, compile and load the compilation unit into the JVM.
062:         * </ol>
063:         * Alternatively, a number of "convenience constructors" exist that execute the steps described
064:         * above instantly.
065:         */
066:        public class SimpleCompiler extends Cookable {
067:            private final static boolean DEBUG = false;
068:
069:            private ClassLoader parentClassLoader = Thread.currentThread()
070:                    .getContextClassLoader();
071:            private Class[] optionalAuxiliaryClasses = null;
072:
073:            // Set when "cook()"ing.
074:            private AuxiliaryClassLoader classLoader = null;
075:            private IClassLoader iClassLoader = null;
076:
077:            private ClassLoader result = null;
078:
079:            public static void main(String[] args) throws Exception {
080:                if (args.length >= 1 && args[0].equals("-help")) {
081:                    System.out.println("Usage:");
082:                    System.out
083:                            .println("    org.codehaus.janino.SimpleCompiler <source-file> <class-name> { <argument> }");
084:                    System.out
085:                            .println("Reads a compilation unit from the given <source-file> and invokes method");
086:                    System.out
087:                            .println("\"public static void main(String[])\" of class <class-name>, passing the.");
088:                    System.out.println("given <argument>s.");
089:                    System.exit(1);
090:                }
091:
092:                if (args.length < 2) {
093:                    System.err
094:                            .println("Source file and/or class name missing; try \"-help\".");
095:                    System.exit(1);
096:                }
097:
098:                // Get source file.
099:                String sourceFileName = args[0];
100:
101:                // Get class name.
102:                String className = args[1];
103:
104:                // Get arguments.
105:                String[] arguments = new String[args.length - 2];
106:                System.arraycopy(args, 2, arguments, 0, arguments.length);
107:
108:                // Compile the source file.
109:                ClassLoader cl = new SimpleCompiler(sourceFileName,
110:                        new FileInputStream(sourceFileName)).getClassLoader();
111:
112:                // Load the class.
113:                Class c = cl.loadClass(className);
114:
115:                // Invoke the "public static main(String[])" method.
116:                Method m = c.getMethod("main", new Class[] { String[].class });
117:                m.invoke(null, new Object[] { arguments });
118:            }
119:
120:            /**
121:             * Equivalent to<pre>
122:             * SimpleCompiler sc = new SimpleCompiler();
123:             * sc.cook(optionalFileName, in);</pre>
124:             *
125:             * @see #SimpleCompiler()
126:             * @see Cookable#cook(String, Reader)
127:             */
128:            public SimpleCompiler(String optionalFileName, Reader in)
129:                    throws IOException, Scanner.ScanException,
130:                    Parser.ParseException, CompileException {
131:                this .cook(optionalFileName, in);
132:            }
133:
134:            /**
135:             * Equivalent to<pre>
136:             * SimpleCompiler sc = new SimpleCompiler();
137:             * sc.cook(optionalFileName, is);</pre>
138:             *
139:             * @see #SimpleCompiler()
140:             * @see Cookable#cook(String, InputStream)
141:             */
142:            public SimpleCompiler(String optionalFileName, InputStream is)
143:                    throws IOException, Scanner.ScanException,
144:                    Parser.ParseException, CompileException {
145:                this .cook(optionalFileName, is);
146:            }
147:
148:            /**
149:             * Equivalent to<pre>
150:             * SimpleCompiler sc = new SimpleCompiler();
151:             * sc.cook(fileName);</pre>
152:             *
153:             * @see #SimpleCompiler()
154:             * @see Cookable#cookFile(String)
155:             */
156:            public SimpleCompiler(String fileName) throws IOException,
157:                    Scanner.ScanException, Parser.ParseException,
158:                    CompileException {
159:                this .cookFile(fileName);
160:            }
161:
162:            /**
163:             * Equivalent to<pre>
164:             * SimpleCompiler sc = new SimpleCompiler();
165:             * sc.setParentClassLoader(optionalParentClassLoader);
166:             * sc.cook(scanner);</pre>
167:             *
168:             * @see #SimpleCompiler()
169:             * @see #setParentClassLoader(ClassLoader)
170:             * @see Cookable#cook(Scanner)
171:             */
172:            public SimpleCompiler(Scanner scanner,
173:                    ClassLoader optionalParentClassLoader) throws IOException,
174:                    Scanner.ScanException, Parser.ParseException,
175:                    CompileException {
176:                this .setParentClassLoader(optionalParentClassLoader);
177:                this .cook(scanner);
178:            }
179:
180:            public SimpleCompiler() {
181:            }
182:
183:            /**
184:             * The "parent class loader" is used to load referenced classes. Useful values are:
185:             * <table border="1"><tr>
186:             *   <td><code>System.getSystemClassLoader()</code></td>
187:             *   <td>The running JVM's class path</td>
188:             * </tr><tr>
189:             *   <td><code>Thread.currentThread().getContextClassLoader()</code> or <code>null</code></td>
190:             *   <td>The class loader effective for the invoking thread</td>
191:             * </tr><tr>
192:             *   <td>{@link #BOOT_CLASS_LOADER}</td>
193:             *   <td>The running JVM's boot class path</td>
194:             * </tr></table>
195:             * The parent class loader defaults to the current thread's context class loader.
196:             */
197:            public void setParentClassLoader(
198:                    ClassLoader optionalParentClassLoader) {
199:                this .setParentClassLoader(optionalParentClassLoader, null);
200:            }
201:
202:            /**
203:             * A {@link ClassLoader} that finds the classes on the JVM's <i>boot class path</i> (e.g.
204:             * <code>java.io.*</code>), but not the classes on the JVM's <i>class path</i>.
205:             */
206:            public static final ClassLoader BOOT_CLASS_LOADER = new ClassLoader(
207:                    null) {
208:            };
209:
210:            /**
211:             * Allowe references to the classes loaded through this parent class loader
212:             * (@see {@link #setParentClassLoader(ClassLoader)}), plus the extra
213:             * <code>auxiliaryClasses</code>.
214:             * <p>
215:             * Notice that the <code>auxiliaryClasses</code> must either be loadable through the
216:             * <code>optionalParentClassLoader</code> (in which case they have no effect), or
217:             * <b>no class with the same name</b> must be loadable through the
218:             * <code>optionalParentClassLoader</code>.
219:             */
220:            public void setParentClassLoader(
221:                    ClassLoader optionalParentClassLoader,
222:                    Class[] auxiliaryClasses) {
223:                this .parentClassLoader = (optionalParentClassLoader != null ? optionalParentClassLoader
224:                        : Thread.currentThread().getContextClassLoader());
225:                this .optionalAuxiliaryClasses = auxiliaryClasses;
226:            }
227:
228:            public void cook(Scanner scanner) throws CompileException,
229:                    Parser.ParseException, Scanner.ScanException, IOException {
230:                this .setUpClassLoaders();
231:
232:                // Parse the compilation unit.
233:                Java.CompilationUnit compilationUnit = new Parser(scanner)
234:                        .parseCompilationUnit();
235:
236:                // Compile the classes and load them.
237:                this .compileToClassLoader(compilationUnit,
238:                        DebuggingInformation.DEFAULT_DEBUGGING_INFORMATION);
239:            }
240:
241:            /**
242:             * Initializes {@link #classLoader} and {@link #iClassLoader} from the configured
243:             * {@link #parentClassLoader} and {@link #optionalAuxiliaryClasses}. These are needed by
244:             * {@link #classToType(Location, Class)} and friends which are used when creating the AST.
245:             */
246:            protected final void setUpClassLoaders() {
247:                if (this .classLoader != null)
248:                    throw new RuntimeException(
249:                            "\"cook()\" must not be called more than once");
250:
251:                // Set up the ClassLoader for the compilation and the loading.
252:                this .classLoader = new AuxiliaryClassLoader(
253:                        this .parentClassLoader);
254:                if (this .optionalAuxiliaryClasses != null) {
255:                    for (int i = 0; i < this .optionalAuxiliaryClasses.length; ++i) {
256:                        this .classLoader
257:                                .addAuxiliaryClass(this .optionalAuxiliaryClasses[i]);
258:                    }
259:                }
260:
261:                this .iClassLoader = new ClassLoaderIClassLoader(
262:                        this .classLoader);
263:            }
264:
265:            /**
266:             * A {@link ClassLoader} that intermixes that classes loaded by its parent with a map of
267:             * "auxiliary classes".
268:             */
269:            private static final class AuxiliaryClassLoader extends ClassLoader {
270:                private final Map auxiliaryClasses = new HashMap(); // String name => Class
271:
272:                private AuxiliaryClassLoader(ClassLoader parent) {
273:                    super (parent);
274:                }
275:
276:                protected Class loadClass(String name, boolean resolve)
277:                        throws ClassNotFoundException {
278:                    Class c = (Class) this .auxiliaryClasses.get(name);
279:                    if (c != null)
280:                        return c;
281:
282:                    return super .loadClass(name, resolve);
283:                }
284:
285:                private void addAuxiliaryClass(Class c) {
286:                    if (this .auxiliaryClasses.containsKey(c.getName()))
287:                        return;
288:
289:                    // Check whether the auxiliary class is conflicting with this ClassLoader.
290:                    try {
291:                        Class c2 = super .loadClass(c.getName(), false);
292:                        if (c2 != c)
293:                            throw new RuntimeException(
294:                                    "Trying to add an auxiliary class \""
295:                                            + c.getName()
296:                                            + "\" while another class with the same name is already loaded");
297:                    } catch (ClassNotFoundException ex) {
298:                        ;
299:                    }
300:
301:                    this .auxiliaryClasses.put(c.getName(), c);
302:
303:                    {
304:                        Class sc = c.getSuperclass();
305:                        if (sc != null)
306:                            this .addAuxiliaryClass(sc);
307:                    }
308:
309:                    {
310:                        Class[] ifs = c.getInterfaces();
311:                        for (int i = 0; i < ifs.length; ++i)
312:                            this .addAuxiliaryClass(ifs[i]);
313:                    }
314:                }
315:
316:                public boolean equals(Object o) {
317:                    if (!(o instanceof  AuxiliaryClassLoader))
318:                        return false;
319:                    AuxiliaryClassLoader that = (AuxiliaryClassLoader) o;
320:
321:                    {
322:                        final ClassLoader parentOfThis = this .getParent();
323:                        final ClassLoader parentOfThat = that.getParent();
324:                        if (parentOfThis == null ? parentOfThat != null
325:                                : !parentOfThis.equals(parentOfThat))
326:                            return false;
327:                    }
328:
329:                    return this .auxiliaryClasses.equals(that.auxiliaryClasses);
330:                }
331:
332:                public int hashCode() {
333:                    ClassLoader parent = this .getParent();
334:                    return (parent == null ? 0 : parent.hashCode())
335:                            ^ this .auxiliaryClasses.hashCode();
336:                }
337:            }
338:
339:            /**
340:             * Returns a {@link ClassLoader} object through which the previously compiled classes can
341:             * be accessed. This {@link ClassLoader} can be used for subsequent calls to
342:             * {@link #SimpleCompiler(Scanner, ClassLoader)} in order to compile compilation units that
343:             * use types (e.g. declare derived types) declared in the previous one.
344:             * <p>
345:             * This method must only be called after {@link #cook(Scanner)}.
346:             * <p>
347:             * This method must not be called for instances of derived classes.
348:             */
349:            public ClassLoader getClassLoader() {
350:                if (this .getClass() != SimpleCompiler.class)
351:                    throw new IllegalStateException(
352:                            "Must not be called on derived instances");
353:                if (this .result == null)
354:                    throw new IllegalStateException(
355:                            "Must only be called after \"cook()\"");
356:                return this .result;
357:            }
358:
359:            /**
360:             * Two {@link SimpleCompiler}s are regarded equal iff
361:             * <ul>
362:             *   <li>Both are objects of the same class (e.g. both are {@link ScriptEvaluator}s)
363:             *   <li>Both generated functionally equal classes as seen by {@link ByteArrayClassLoader#equals(Object)}
364:             * </ul>
365:             */
366:            public boolean equals(Object o) {
367:                if (!(o instanceof  SimpleCompiler))
368:                    return false;
369:                SimpleCompiler that = (SimpleCompiler) o;
370:                if (this .getClass() != that.getClass())
371:                    return false;
372:                if (this .result == null || that.result == null)
373:                    throw new IllegalStateException(
374:                            "Equality can only be checked after cooking");
375:                return this .result.equals(that.result);
376:            }
377:
378:            public int hashCode() {
379:                return this .classLoader.hashCode();
380:            }
381:
382:            /**
383:             * Wrap a reflection {@link Class} in a {@link Java.Type} object.
384:             */
385:            protected Java.Type classToType(Location location,
386:                    final Class optionalClass) {
387:                if (optionalClass == null)
388:                    return null;
389:
390:                this .classLoader.addAuxiliaryClass(optionalClass);
391:
392:                IClass iClass;
393:                try {
394:                    iClass = this .iClassLoader.loadIClass(Descriptor
395:                            .fromClassName(optionalClass.getName()));
396:                } catch (ClassNotFoundException ex) {
397:                    throw new RuntimeException("Loading IClass \""
398:                            + optionalClass.getName() + "\": " + ex);
399:                }
400:                if (iClass == null)
401:                    throw new RuntimeException("Cannot load class \""
402:                            + optionalClass.getName()
403:                            + "\" through the given ClassLoader");
404:
405:                return new Java.SimpleType(location, iClass);
406:            }
407:
408:            /**
409:             * Convert an array of {@link Class}es into an array of{@link Java.Type}s.
410:             */
411:            protected Java.Type[] classesToTypes(Location location,
412:                    Class[] classes) {
413:                Java.Type[] types = new Java.Type[classes.length];
414:                for (int i = 0; i < classes.length; ++i) {
415:                    types[i] = this .classToType(location, classes[i]);
416:                }
417:                return types;
418:            }
419:
420:            /**
421:             * Compile the given compilation unit. (A "compilation unit" is typically the contents
422:             * of a Java<sup>TM</sup> source file.)
423:             * 
424:             * @param compilationUnit The parsed compilation unit
425:             * @param debuggingInformation What kind of debugging information to generate in the class file
426:             * @return The {@link ClassLoader} into which the compiled classes were defined
427:             * @throws CompileException
428:             */
429:            protected final ClassLoader compileToClassLoader(
430:                    Java.CompilationUnit compilationUnit,
431:                    EnumeratorSet debuggingInformation) throws CompileException {
432:                if (SimpleCompiler.DEBUG) {
433:                    UnparseVisitor.unparse(compilationUnit,
434:                            new OutputStreamWriter(System.out));
435:                }
436:
437:                // Compile compilation unit to class files.
438:                ClassFile[] classFiles = new UnitCompiler(compilationUnit,
439:                        this .iClassLoader).compileUnit(debuggingInformation);
440:
441:                // Convert the class files to bytes and store them in a Map.
442:                Map classes = new HashMap(); // String className => byte[] data
443:                for (int i = 0; i < classFiles.length; ++i) {
444:                    ClassFile cf = classFiles[i];
445:                    classes.put(cf.getThisClassName(), cf.toByteArray());
446:                }
447:
448:                // Disassemble all generated classes (for debugging).
449:                if (SimpleCompiler.DEBUG) {
450:                    for (Iterator it = classes.entrySet().iterator(); it
451:                            .hasNext();) {
452:                        Map.Entry me = (Map.Entry) it.next();
453:                        String className = (String) me.getKey();
454:                        byte[] bytecode = (byte[]) me.getValue();
455:                        System.out.println("*** Disassembly of class \""
456:                                + className + "\":");
457:                        try {
458:                            new Disassembler().disasm(new ByteArrayInputStream(
459:                                    bytecode));
460:                            System.out.flush();
461:                        } catch (IOException ex) {
462:                            throw new RuntimeException(
463:                                    "SNO: IOException despite ByteArrayInputStream");
464:                        }
465:                    }
466:                }
467:
468:                // Create a ClassLoader that loads the generated classes.
469:                this .result = new ByteArrayClassLoader(classes, // classes
470:                        this .classLoader // parent
471:                );
472:                return this.result;
473:            }
474:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.