Source Code Cross Referenced for ScriptEvaluator.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:
039:        /**
040:         * A script evaluator that executes a script in Java<sup>TM</sup> bytecode.
041:         * <p>
042:         * The syntax of the script to compile is a sequence of import declarations followed by a
043:         * sequence of statements, as defined in the
044:         * <a href="http://java.sun.com/docs/books/jls/second_edition">Java Language Specification, 2nd
045:         * edition</a>, sections
046:         * <a href="http://java.sun.com/docs/books/jls/second_edition/html/packages.doc.html#70209">7.5</a>
047:         * and
048:         * <a href="http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#101241">14</a>.
049:         * <p>
050:         * Example:
051:         * <pre>
052:         *   import java.text.*;
053:         * 
054:         *   System.out.println("HELLO");
055:         *   System.out.println(new DecimalFormat("####,###.##").format(a));
056:         * </pre>
057:         * (Notice that this expression refers to a parameter "a", as explained below.)
058:         * <p>
059:         * The script may complete abnormally, e.g. through a RETURN statement:
060:         * <pre>
061:         *   if (a == null) {
062:         *       System.out.println("Oops!");
063:         *       return;
064:         *   }
065:         * </pre>
066:         * Optionally, the script may be declared with a non-void return type. In this case, the last
067:         * statement of the script must be a RETURN statement (or a THROW statement), and all RETURN
068:         * statements in the script must return a value with the given type.
069:         * <p>
070:         * The script evaluator is implemented by creating and compiling a temporary compilation unit
071:         * defining one class with one method the body of which consists of the statements of the
072:         * script.
073:         * <p>
074:         * To set up a {@link ScriptEvaluator} object, proceed as follows:
075:         * <ol>
076:         *   <li>
077:         *   Create the {@link ScriptEvaluator} using {@link #ScriptEvaluator()}
078:         *   <li>
079:         *   Configure the {@link ScriptEvaluator} by calling any of the following methods:
080:         *   <ul>
081:         *      <li>{@link #setReturnType(Class)}
082:         *      <li>{@link #setParameters(String[], Class[])}
083:         *      <li>{@link #setThrownExceptions(Class[])}
084:         *      <li>{@link org.codehaus.janino.SimpleCompiler#setParentClassLoader(ClassLoader)}
085:         *      <li>{@link org.codehaus.janino.ClassBodyEvaluator#setDefaultImports(String[])}
086:         *   </ul>
087:         *   <li>
088:         *   Call any of the {@link org.codehaus.janino.Cookable#cook(Scanner)} methods to scan,
089:         *   parse, compile and load the script into the JVM.
090:         * </ol>
091:         * Alternatively, a number of "convenience constructors" exist that execute the steps described
092:         * above instantly.
093:         * <p>
094:         * After the {@link ScriptEvaluator} object is created, the script can be executed as often with
095:         * different parameter values (see {@link #evaluate(Object[])}). This execution is very fast,
096:         * compared to the compilation.
097:         * <p>
098:         * The more elaborate constructors of {@link ScriptEvaluator} also allow for the specification
099:         * of the name of the generated class, the class it extends, the interfaces it implements, the
100:         * name of the method that executes the script, the exceptions that this method is allowed
101:         * to throw, and the {@link ClassLoader} that is used to define the generated
102:         * class and to load classes referenced by the expression. This degree of flexibility is usually
103:         * not required; the most commonly used constructor is
104:         * {@link #ScriptEvaluator(String, Class, String[], Class[])}.
105:         */
106:        public class ScriptEvaluator extends ClassBodyEvaluator {
107:            public static final String DEFAULT_METHOD_NAME = "eval";
108:            public static final String[] ZERO_STRINGS = new String[0];
109:
110:            private boolean staticMethod = true;
111:            private Class returnType = void.class;
112:            private String methodName = ScriptEvaluator.DEFAULT_METHOD_NAME;
113:            private String[] parameterNames = ScriptEvaluator.ZERO_STRINGS;
114:            private Class[] parameterTypes = ClassBodyEvaluator.ZERO_CLASSES;
115:            private Class[] thrownExceptions = ClassBodyEvaluator.ZERO_CLASSES;
116:
117:            private Method method = null; // null=uncooked
118:
119:            /**
120:             * Equivalent to<pre>
121:             * ScriptEvaluator se = new ScriptEvaluator();
122:             * se.cook(script);</pre>
123:             *
124:             * @see #ScriptEvaluator()
125:             * @see Cookable#cook(String)
126:             */
127:            public ScriptEvaluator(String script) throws CompileException,
128:                    Parser.ParseException, Scanner.ScanException {
129:                this .cook(script);
130:            }
131:
132:            /**
133:             * Equivalent to<pre>
134:             * ScriptEvaluator se = new ScriptEvaluator();
135:             * se.setReturnType(returnType);
136:             * se.cook(script);</pre>
137:             *
138:             * @see #ScriptEvaluator()
139:             * @see #setReturnType(Class)
140:             * @see Cookable#cook(String)
141:             */
142:            public ScriptEvaluator(String script, Class returnType)
143:                    throws CompileException, Parser.ParseException,
144:                    Scanner.ScanException {
145:                this .setReturnType(returnType);
146:                this .cook(script);
147:            }
148:
149:            /**
150:             * Equivalent to<pre>
151:             * ScriptEvaluator se = new ScriptEvaluator();
152:             * se.setReturnType(returnType);
153:             * se.setParameters(parameterNames, parameterTypes);
154:             * se.cook(script);</pre>
155:             *
156:             * @see #ScriptEvaluator()
157:             * @see #setReturnType(Class)
158:             * @see #setParameters(String[], Class[])
159:             * @see Cookable#cook(String)
160:             */
161:            public ScriptEvaluator(String script, Class returnType,
162:                    String[] parameterNames, Class[] parameterTypes)
163:                    throws CompileException, Parser.ParseException,
164:                    Scanner.ScanException {
165:                this .setReturnType(returnType);
166:                this .setParameters(parameterNames, parameterTypes);
167:                this .cook(script);
168:            }
169:
170:            /**
171:             * Equivalent to<pre>
172:             * ScriptEvaluator se = new ScriptEvaluator();
173:             * se.setReturnType(returnType);
174:             * se.setParameters(parameterNames, parameterTypes);
175:             * se.setThrownExceptions(thrownExceptions);
176:             * se.cook(script);</pre>
177:             *
178:             * @see #ScriptEvaluator()
179:             * @see #setReturnType(Class)
180:             * @see #setParameters(String[], Class[])
181:             * @see #setThrownExceptions(Class[])
182:             * @see Cookable#cook(String)
183:             */
184:            public ScriptEvaluator(String script, Class returnType,
185:                    String[] parameterNames, Class[] parameterTypes,
186:                    Class[] thrownExceptions) throws CompileException,
187:                    Parser.ParseException, Scanner.ScanException {
188:                this .setReturnType(returnType);
189:                this .setParameters(parameterNames, parameterTypes);
190:                this .setThrownExceptions(thrownExceptions);
191:                this .cook(script);
192:            }
193:
194:            /**
195:             * Equivalent to<pre>
196:             * ScriptEvaluator se = new ScriptEvaluator();
197:             * se.setReturnType(returnType);
198:             * se.setParameters(parameterNames, parameterTypes);
199:             * se.setThrownExceptions(thrownExceptions);
200:             * se.setParentClassLoader(optionalParentClassLoader);
201:             * se.cook(optionalFileName, is);</pre>
202:             *
203:             * @see #ScriptEvaluator()
204:             * @see #setReturnType(Class)
205:             * @see #setParameters(String[], Class[])
206:             * @see #setThrownExceptions(Class[])
207:             * @see SimpleCompiler#setParentClassLoader(ClassLoader)
208:             * @see Cookable#cook(String, InputStream)
209:             */
210:            public ScriptEvaluator(String optionalFileName, InputStream is,
211:                    Class returnType, String[] parameterNames,
212:                    Class[] parameterTypes, Class[] thrownExceptions,
213:                    ClassLoader optionalParentClassLoader // null = use current thread's context class loader
214:            ) throws CompileException, Parser.ParseException,
215:                    Scanner.ScanException, IOException {
216:                this .setReturnType(returnType);
217:                this .setParameters(parameterNames, parameterTypes);
218:                this .setThrownExceptions(thrownExceptions);
219:                this .setParentClassLoader(optionalParentClassLoader);
220:                this .cook(optionalFileName, is);
221:            }
222:
223:            /**
224:             * Equivalent to<pre>
225:             * ScriptEvaluator se = new ScriptEvaluator();
226:             * se.setReturnType(returnType);
227:             * se.setParameters(parameterNames, parameterTypes);
228:             * se.setThrownExceptions(thrownExceptions);
229:             * se.setParentClassLoader(optionalParentClassLoader);
230:             * se.cook(reader);</pre>
231:             *
232:             * @see #ScriptEvaluator()
233:             * @see #setReturnType(Class)
234:             * @see #setParameters(String[], Class[])
235:             * @see #setThrownExceptions(Class[])
236:             * @see SimpleCompiler#setParentClassLoader(ClassLoader)
237:             * @see Cookable#cook(String, Reader)
238:             */
239:            public ScriptEvaluator(String optionalFileName, Reader reader,
240:                    Class returnType, String[] parameterNames,
241:                    Class[] parameterTypes, Class[] thrownExceptions,
242:                    ClassLoader optionalParentClassLoader // null = use current thread's context class loader
243:            ) throws CompileException, Parser.ParseException,
244:                    Scanner.ScanException, IOException {
245:                this .setReturnType(returnType);
246:                this .setParameters(parameterNames, parameterTypes);
247:                this .setThrownExceptions(thrownExceptions);
248:                this .setParentClassLoader(optionalParentClassLoader);
249:                this .cook(optionalFileName, reader);
250:            }
251:
252:            /**
253:             * Equivalent to<pre>
254:             * ScriptEvaluator se = new ScriptEvaluator();
255:             * se.setReturnType(returnType);
256:             * se.setParameters(parameterNames, parameterTypes);
257:             * se.setThrownExceptions(thrownExceptions);
258:             * se.setParentClassLoader(optionalParentClassLoader);
259:             * se.cook(scanner);</pre>
260:             *
261:             * @see #ScriptEvaluator()
262:             * @see #setReturnType(Class)
263:             * @see #setParameters(String[], Class[])
264:             * @see #setThrownExceptions(Class[])
265:             * @see SimpleCompiler#setParentClassLoader(ClassLoader)
266:             * @see Cookable#cook(Scanner)
267:             */
268:            public ScriptEvaluator(Scanner scanner, Class returnType,
269:                    String[] parameterNames, Class[] parameterTypes,
270:                    Class[] thrownExceptions,
271:                    ClassLoader optionalParentClassLoader // null = use current thread's context class loader
272:            ) throws CompileException, Parser.ParseException,
273:                    Scanner.ScanException, IOException {
274:                this .setReturnType(returnType);
275:                this .setParameters(parameterNames, parameterTypes);
276:                this .setThrownExceptions(thrownExceptions);
277:                this .setParentClassLoader(optionalParentClassLoader);
278:                this .cook(scanner);
279:            }
280:
281:            /**
282:             * Equivalent to<pre>
283:             * ScriptEvaluator se = new ScriptEvaluator();
284:             * se.setExtendedType(optionalExtendedType);
285:             * se.setImplementedTypes(implementedTypes);
286:             * se.setReturnType(returnType);
287:             * se.setParameters(parameterNames, parameterTypes);
288:             * se.setThrownExceptions(thrownExceptions);
289:             * se.setParentClassLoader(optionalParentClassLoader);
290:             * se.cook(scanner);</pre>
291:             *
292:             * @see #ScriptEvaluator()
293:             * @see ClassBodyEvaluator#setExtendedType(Class)
294:             * @see ClassBodyEvaluator#setImplementedTypes(Class[])
295:             * @see #setReturnType(Class)
296:             * @see #setParameters(String[], Class[])
297:             * @see #setThrownExceptions(Class[])
298:             * @see SimpleCompiler#setParentClassLoader(ClassLoader)
299:             * @see Cookable#cook(Scanner)
300:             */
301:            public ScriptEvaluator(Scanner scanner, Class optionalExtendedType,
302:                    Class[] implementedTypes, Class returnType,
303:                    String[] parameterNames, Class[] parameterTypes,
304:                    Class[] thrownExceptions,
305:                    ClassLoader optionalParentClassLoader // null = use current thread's context class loader
306:            ) throws CompileException, Parser.ParseException,
307:                    Scanner.ScanException, IOException {
308:                this .setExtendedType(optionalExtendedType);
309:                this .setImplementedTypes(implementedTypes);
310:                this .setReturnType(returnType);
311:                this .setParameters(parameterNames, parameterTypes);
312:                this .setThrownExceptions(thrownExceptions);
313:                this .setParentClassLoader(optionalParentClassLoader);
314:                this .cook(scanner);
315:            }
316:
317:            /**
318:             * Equivalent to<pre>
319:             * ScriptEvaluator se = new ScriptEvaluator();
320:             * se.setClassName(className);
321:             * se.setExtendedType(optionalExtendedType);
322:             * se.setImplementedTypes(implementedTypes);
323:             * se.setStaticMethod(staticMethod);
324:             * se.setReturnType(returnType);
325:             * se.setMethodName(methodName);
326:             * se.setParameters(parameterNames, parameterTypes);
327:             * se.setThrownExceptions(thrownExceptions);
328:             * se.setParentClassLoader(optionalParentClassLoader);
329:             * se.cook(scanner);</pre>
330:             *
331:             * @see #ScriptEvaluator()
332:             * @see ClassBodyEvaluator#setClassName(String)
333:             * @see ClassBodyEvaluator#setExtendedType(Class)
334:             * @see ClassBodyEvaluator#setImplementedTypes(Class[])
335:             * @see #setStaticMethod(boolean)
336:             * @see #setReturnType(Class)
337:             * @see #setMethodName(String)
338:             * @see #setParameters(String[], Class[])
339:             * @see #setThrownExceptions(Class[])
340:             * @see SimpleCompiler#setParentClassLoader(ClassLoader)
341:             * @see Cookable#cook(Scanner)
342:             */
343:            public ScriptEvaluator(Scanner scanner, String className,
344:                    Class optionalExtendedType, Class[] implementedTypes,
345:                    boolean staticMethod, Class returnType, String methodName,
346:                    String[] parameterNames, Class[] parameterTypes,
347:                    Class[] thrownExceptions,
348:                    ClassLoader optionalParentClassLoader // null = use current thread's context class loader
349:            ) throws Scanner.ScanException, Parser.ParseException,
350:                    CompileException, IOException {
351:                this .setClassName(className);
352:                this .setExtendedType(optionalExtendedType);
353:                this .setImplementedTypes(implementedTypes);
354:                this .setStaticMethod(staticMethod);
355:                this .setReturnType(returnType);
356:                this .setMethodName(methodName);
357:                this .setParameters(parameterNames, parameterTypes);
358:                this .setThrownExceptions(thrownExceptions);
359:                this .setParentClassLoader(optionalParentClassLoader);
360:                this .cook(scanner);
361:            }
362:
363:            public ScriptEvaluator() {
364:            }
365:
366:            /**
367:             * Define whether the generated method should be STATIC or not. Defaults to <code>true</code>.
368:             */
369:            public void setStaticMethod(boolean staticMethod) {
370:                this .staticMethod = staticMethod;
371:            }
372:
373:            /**
374:             * Define the return type of the generated method. Defaults to <code>void.class</code>.
375:             */
376:            public void setReturnType(Class returnType) {
377:                this .returnType = returnType;
378:            }
379:
380:            /**
381:             * Define the name of the generated method. Defaults to {@link #DEFAULT_METHOD_NAME}.
382:             */
383:            public void setMethodName(String methodName) {
384:                this .methodName = methodName;
385:            }
386:
387:            /**
388:             * Define the names and types of the parameters of the generated method.
389:             */
390:            public void setParameters(String[] parameterNames,
391:                    Class[] parameterTypes) {
392:                if (parameterNames.length != parameterTypes.length)
393:                    throw new IllegalArgumentException(
394:                            "Parameter names and types counts do not match");
395:                this .parameterNames = parameterNames;
396:                this .parameterTypes = parameterTypes;
397:            }
398:
399:            /**
400:             * Define the exceptions that the generated method may throw.
401:             */
402:            public void setThrownExceptions(Class[] thrownExceptions) {
403:                if (thrownExceptions == null)
404:                    throw new NullPointerException(
405:                            "Zero thrown exceptions must be specified as \"new Class[0]\", not \"null\"");
406:                this .thrownExceptions = thrownExceptions;
407:            }
408:
409:            protected void internalCook(Scanner scanner)
410:                    throws CompileException, Parser.ParseException,
411:                    Scanner.ScanException, IOException {
412:                Java.CompilationUnit compilationUnit = this 
413:                        .makeCompilationUnit(scanner);
414:
415:                // Create class, method and block.
416:                Java.Block block = this .addClassMethodBlockDeclaration(scanner
417:                        .location(), // location
418:                        compilationUnit, // compilationUnit
419:                        this .returnType // returnType
420:                        );
421:
422:                // Parse block statements.
423:                Parser parser = new Parser(scanner);
424:                while (!scanner.peek().isEOF()) {
425:                    block.addStatement(parser.parseBlockStatement());
426:                }
427:
428:                this .compileToMethod(compilationUnit);
429:            }
430:
431:            protected void compileToMethod(Java.CompilationUnit compilationUnit)
432:                    throws CompileException {
433:
434:                // Compile and load the compilation unit.
435:                Class c = this .compileToClass(compilationUnit, // compilationUnit
436:                        DebuggingInformation.DEFAULT_DEBUGGING_INFORMATION, // debuggingInformation
437:                        this .className // className
438:                        );
439:
440:                // Find the script method by name.
441:                try {
442:                    this .method = c.getMethod(this .methodName,
443:                            this .parameterTypes);
444:                } catch (NoSuchMethodException ex) {
445:                    throw new RuntimeException(
446:                            "SNO: Loaded class does not declare method \""
447:                                    + this .methodName + "\"");
448:                }
449:            }
450:
451:            /**
452:             * To the given {@link Java.CompilationUnit}, add
453:             * <ul>
454:             *   <li>A package member class declaration with the given name, superclass and interfaces
455:             *   <li>A public method declaration with the given return type, name, parameter
456:             *       names and values and thrown exceptions
457:             *   <li>A block 
458:             * </ul> 
459:             * @param location
460:             * @param compilationUnit
461:             * @param className
462:             * @param optionalExtendedType (null == {@link Object})
463:             * @param implementedTypes
464:             * @param staticMethod Whether the method should be declared "static"
465:             * @param returnType Return type of the declared method
466:             * @param methodName
467:             * @param parameterNames
468:             * @param parameterTypes
469:             * @param thrownExceptions
470:             * @return The created {@link Java.Block} object
471:             * @throws Parser.ParseException
472:             */
473:            protected Java.Block addClassMethodBlockDeclaration(
474:                    Location location, Java.CompilationUnit compilationUnit,
475:                    Class returnType) throws Parser.ParseException {
476:                if (this .parameterNames.length != this .parameterTypes.length)
477:                    throw new RuntimeException(
478:                            "Lengths of \"parameterNames\" and \"parameterTypes\" do not match");
479:
480:                // Add class declaration.
481:                Java.ClassDeclaration cd = this 
482:                        .addPackageMemberClassDeclaration(location,
483:                                compilationUnit);
484:
485:                // Add method declaration.
486:                Java.Block b = new Java.Block(location);
487:                Java.FunctionDeclarator.FormalParameter[] fps = new Java.FunctionDeclarator.FormalParameter[this .parameterNames.length];
488:                for (int i = 0; i < fps.length; ++i) {
489:                    fps[i] = new Java.FunctionDeclarator.FormalParameter(
490:                            location, // location
491:                            true, // finaL
492:                            this .classToType(location, this .parameterTypes[i]), // type
493:                            this .parameterNames[i] // name
494:                    );
495:                }
496:                Java.MethodDeclarator md = new Java.MethodDeclarator(location, // location
497:                        null, // optionalDocComment
498:                        ( // modifiers
499:                        this .staticMethod ? (short) (Mod.PUBLIC | Mod.STATIC)
500:                                : (short) Mod.PUBLIC), this .classToType(
501:                                location, returnType), // type
502:                        this .methodName, // name
503:                        fps, // formalParameters
504:                        this .classesToTypes(location, this .thrownExceptions), // thrownExceptions
505:                        b // optionalBody
506:                );
507:                cd.addDeclaredMethod(md);
508:
509:                return b;
510:            }
511:
512:            /**
513:             * Simplified version of
514:             * {@link #createFastScriptEvaluator(Scanner, Class, String[], ClassLoader)}.
515:             * 
516:             * @param script Contains the sequence of script tokens
517:             * @param interfaceToImplement Must declare exactly the one method that defines the expression's signature
518:             * @param parameterNames The expression references the parameters through these names
519:             * @return an object that implements the given interface and extends the <code>optionalExtendedType</code>
520:             */
521:            public static Object createFastScriptEvaluator(String script,
522:                    Class interfaceToImplement, String[] parameterNames)
523:                    throws CompileException, Parser.ParseException,
524:                    Scanner.ScanException {
525:                ScriptEvaluator se = new ScriptEvaluator();
526:                return ScriptEvaluator.createFastEvaluator(se, script,
527:                        parameterNames, interfaceToImplement);
528:            }
529:
530:            /**
531:             * If the parameter and return types of the expression are known at compile time,
532:             * then a "fast" script evaluator can be instantiated through this method.
533:             * <p>
534:             * Script evaluation is faster than through {@link #evaluate(Object[])}, because
535:             * it is not done through reflection but through direct method invocation.
536:             * <p>
537:             * Example:
538:             * <pre>
539:             * public interface Foo {
540:             *     int bar(int a, int b);
541:             * }
542:             * ...
543:             * Foo f = (Foo) ScriptEvaluator.createFastScriptEvaluator(
544:             *     new Scanner(null, new StringReader("return a + b;")),
545:             *     Foo.class,
546:             *     new String[] { "a", "b" },
547:             *     (ClassLoader) null          // Use current thread's context class loader
548:             * );
549:             * System.out.println("1 + 2 = " + f.bar(1, 2));
550:             * </pre>
551:             * Notice: The <code>interfaceToImplement</code> must either be declared <code>public</code>,
552:             * or with package scope in the root package (i.e. "no" package).
553:             * 
554:             * @param scanner Source of script tokens
555:             * @param interfaceToImplement Must declare exactly one method
556:             * @param parameterNames
557:             * @param optionalParentClassLoader
558:             * @return an object that implements the given interface
559:             */
560:            public static Object createFastScriptEvaluator(Scanner scanner,
561:                    Class interfaceToImplement, String[] parameterNames,
562:                    ClassLoader optionalParentClassLoader)
563:                    throws CompileException, Parser.ParseException,
564:                    Scanner.ScanException, IOException {
565:                ScriptEvaluator se = new ScriptEvaluator();
566:                se.setParentClassLoader(optionalParentClassLoader);
567:                return ScriptEvaluator.createFastEvaluator(se, scanner,
568:                        parameterNames, interfaceToImplement);
569:            }
570:
571:            /**
572:             * Like {@link #createFastScriptEvaluator(Scanner, Class, String[], ClassLoader)},
573:             * but gives you more control over the generated class (rarely needed in practice).
574:             * <p> 
575:             * Notice: The <code>interfaceToImplement</code> must either be declared <code>public</code>,
576:             * or with package scope in the same package as <code>className</code>.
577:             * 
578:             * @param scanner                   Source of script tokens
579:             * @param className                 Name of generated class
580:             * @param optionalExtendedType      Class to extend
581:             * @param interfaceToImplement      Must declare exactly the one method that defines the expression's signature
582:             * @param parameterNames            The expression references the parameters through these names
583:             * @param optionalParentClassLoader Used to load referenced classes, defaults to the current thread's "context class loader"
584:             * @return an object that implements the given interface and extends the <code>optionalExtendedType</code>
585:             */
586:            public static Object createFastScriptEvaluator(Scanner scanner,
587:                    String className, Class optionalExtendedType,
588:                    Class interfaceToImplement, String[] parameterNames,
589:                    ClassLoader optionalParentClassLoader)
590:                    throws CompileException, Parser.ParseException,
591:                    Scanner.ScanException, IOException {
592:                ScriptEvaluator se = new ScriptEvaluator();
593:                se.setClassName(className);
594:                se.setExtendedType(optionalExtendedType);
595:                se.setParentClassLoader(optionalParentClassLoader);
596:                return ScriptEvaluator.createFastEvaluator(se, scanner,
597:                        parameterNames, interfaceToImplement);
598:            }
599:
600:            public static Object createFastScriptEvaluator(Scanner scanner,
601:                    String[] optionalDefaultImports, String className,
602:                    Class optionalExtendedType, Class interfaceToImplement,
603:                    String[] parameterNames,
604:                    ClassLoader optionalParentClassLoader)
605:                    throws CompileException, Parser.ParseException,
606:                    Scanner.ScanException, IOException {
607:                ScriptEvaluator se = new ScriptEvaluator();
608:                se.setClassName(className);
609:                se.setExtendedType(optionalExtendedType);
610:                se.setDefaultImports(optionalDefaultImports);
611:                se.setParentClassLoader(optionalParentClassLoader);
612:                return ScriptEvaluator.createFastEvaluator(se, scanner,
613:                        parameterNames, interfaceToImplement);
614:            }
615:
616:            public static Object createFastEvaluator(ScriptEvaluator se,
617:                    String s, String[] parameterNames,
618:                    Class interfaceToImplement) throws CompileException,
619:                    Parser.ParseException, Scanner.ScanException {
620:                try {
621:                    return ScriptEvaluator.createFastEvaluator(se, new Scanner(
622:                            null, new StringReader(s)), parameterNames,
623:                            interfaceToImplement);
624:                } catch (IOException ex) {
625:                    throw new RuntimeException(
626:                            "IOException despite StringReader");
627:                }
628:            }
629:
630:            public static Object createFastEvaluator(ScriptEvaluator se,
631:                    Scanner scanner, String[] parameterNames,
632:                    Class interfaceToImplement) throws CompileException,
633:                    Parser.ParseException, Scanner.ScanException, IOException {
634:                if (!interfaceToImplement.isInterface())
635:                    throw new RuntimeException("\"" + interfaceToImplement
636:                            + "\" is not an interface");
637:
638:                Method[] methods = interfaceToImplement.getDeclaredMethods();
639:                if (methods.length != 1)
640:                    throw new RuntimeException("Interface \""
641:                            + interfaceToImplement
642:                            + "\" must declare exactly one method");
643:                Method methodToImplement = methods[0];
644:
645:                se.setImplementedTypes(new Class[] { interfaceToImplement });
646:                se.setStaticMethod(false);
647:                se.setReturnType(methodToImplement.getReturnType());
648:                se.setMethodName(methodToImplement.getName());
649:                se.setParameters(parameterNames, methodToImplement
650:                        .getParameterTypes());
651:                se.setThrownExceptions(methodToImplement.getExceptionTypes());
652:                se.cook(scanner);
653:                Class c = se.getMethod().getDeclaringClass();
654:                try {
655:                    return c.newInstance();
656:                } catch (InstantiationException e) {
657:                    // SNO - Declared class is always non-abstract.
658:                    throw new RuntimeException(e.toString());
659:                } catch (IllegalAccessException e) {
660:                    // SNO - interface methods are always PUBLIC.
661:                    throw new RuntimeException(e.toString());
662:                }
663:            }
664:
665:            /**
666:             * Calls the generated method with concrete parameter values.
667:             * <p>
668:             * Each parameter value must have the same type as specified through
669:             * the "parameterTypes" parameter of
670:             * {@link #setParameters(String[], Class[])}.
671:             * <p>
672:             * Parameters of primitive type must passed with their wrapper class
673:             * objects.
674:             * <p>
675:             * The object returned has the class as specified through
676:             * {@link #setReturnType(Class)}.
677:             * <p>
678:             * This method is thread-safe.
679:             *
680:             * @param parameterValues The concrete parameter values.
681:             */
682:            public Object evaluate(Object[] parameterValues)
683:                    throws InvocationTargetException {
684:                if (this .method == null)
685:                    throw new IllegalStateException(
686:                            "Must only be called after \"cook()\"");
687:                try {
688:                    return this .method.invoke(null, parameterValues);
689:                } catch (IllegalAccessException ex) {
690:                    throw new RuntimeException(ex.toString());
691:                }
692:            }
693:
694:            /**
695:             * Returns the loaded {@link java.lang.reflect.Method}.
696:             * <p>
697:             * This method must only be called after {@link #cook(Scanner)}.
698:             * <p>
699:             * This method must not be called for instances of derived classes.
700:             */
701:            public Method getMethod() {
702:                if (this .method == null)
703:                    throw new IllegalStateException(
704:                            "Must only be called after \"cook()\"");
705:                return this.method;
706:            }
707:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.