Source Code Cross Referenced for Expression.java in  » Scripting » InstantJ » instantj » expression » 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 » InstantJ » instantj.expression 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * InstantJ
003:         * 
004:         * Copyright (C) 2002 Nils Meier
005:         * 
006:         * This library is free software; you can redistribute it and/or
007:         * modify it under the terms of the GNU Lesser General Public
008:         * License as published by the Free Software Foundation; either
009:         * version 2.1 of the License, or (at your option) any later version.
010:         * 
011:         * This library is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         * Lesser General Public License for more details.
015:         * 
016:         */package instantj.expression;
017:
018:        import instantj.compile.CompilationFailedException;
019:        import instantj.compile.CompiledClass;
020:        import instantj.compile.Compiler;
021:        import instantj.compile.Source;
022:        import instantj.reflect.IllegalPropertyException;
023:        import instantj.reflect.InaccessiblePropertyException;
024:        import instantj.reflect.ReflectAccess;
025:
026:        import java.io.File;
027:        import java.io.FileOutputStream;
028:        import java.io.IOException;
029:        import java.io.InputStream;
030:        import java.io.InputStreamReader;
031:        import java.io.PrintWriter;
032:        import java.io.Serializable;
033:        import java.util.ArrayList;
034:        import java.util.Arrays;
035:        import java.util.Collection;
036:        import java.util.HashMap;
037:        import java.util.Iterator;
038:        import java.util.Map;
039:
040:        /**
041:         * <p>
042:         * An Expression is a piece of Java-code that evaluates to a result
043:         * of a primitive- or Object-type. Therefor it doesn't have any
044:         * return-statements and does not end with ';'. Think of an expression
045:         * as something you can assign to a variable like this
046:         * <pre>
047:         *   Object foo = <font color="red">theExpression</font>;
048:         * </pre>
049:         * (Note that <i>Object foo =</i> and <i>;</i> are NOT part of the expression).
050:         * Examples for expression are
051:         * <pre>
052:         *   "Hello World"
053:         *   account.balance - 100
054:         *   2 * Math.PI
055:         *   count--; count&lt;0
056:         * </pre>
057:         * The last one is treated a little bit different - this expression consists
058:         * of an instruction <i>count--;</i> and the end-result <i>count&lt;0</i>.
059:         * During evaluation the instruction(s) is/are executed first and the last
060:         * piece of the expression is returned as the result. 
061:         * </p>
062:         *
063:         * <p>
064:         * A java-expression can evaluate to a Object- or primitive-type. In
065:         * the latter case the evaluation of the Expression-object will wrap 
066:         * the primitive result in a Java-type (e.g. Integer).
067:         * </p>
068:         *
069:         * <p>
070:         * This type not only wraps the expression's body but alos its environment
071:         * properties. The properties are kept in a map of name/Class that keeps track
072:         * of those the expression can use.(e.g. String.class, Account.class or 
073:         * Integer.TYPE). The expression can reference properties in its environment 
074:         * as local variables (see above).
075:         * </p>
076:         * 
077:         * <p>
078:         * Once you have an instance of an expression you can evaluate it in the
079:         * environment of property values that you provide. The values are mapped
080:         * to the property-names and assigned to the expression's local variables 
081:         * before execution.
082:         * </p>
083:         *
084:         * <p>
085:         * Example 1:
086:         * <pre>
087:         *  // Our expression body
088:         *  String body = " 3*4 ";
089:         *
090:         *  // Creating the Expression
091:         *  Expression expression = new Expression(body);
092:         *  
093:         *  // Evaluate it
094:         *  Object result = expression.evaluate();
095:         * </pre>
096:         * The result of this expression is
097:         * <blockquote>
098:         * (java.lang.Integer) 12
099:         * </blockquote>
100:         * <font size=-1>Note: there's no exception-handling in this snippet</font>
101:         * </p>
102:         * 
103:         * <p>
104:         * Example 2:
105:         * <pre>
106:         *  // The properties we want to use inside the expression
107:         *  Hashtable properties = new Hashtable();
108:         *  properties.put("count", Integer.TYPE);
109:         *  properties.put("msg"  , String.class);
110:         *
111:         *  // Our expression body
112:         *  String body = " count++; msg+new java.util.Date() ";
113:         *
114:         *  // Creating the Expression
115:         *  Expression expression = new Expression(body,properties);
116:         *
117:         *  // The values we give to the evaluation	
118:         *  Map values = new HashMap();
119:         *  values.put("count", new Integer(3));
120:         *  values.put("msg"  , "Guybrush was here on " );
121:         *
122:         *  // Evaluate it
123:         *  Object result = expression.getInstance(values).evaluate();
124:         * </pre>
125:         * The result of this expression is
126:         * <blockquote>
127:         * (java.lang.String) Guybrush was here on Dec 17 11:33:31 EST 2000 
128:         * </blockquote>
129:         * As an alternative to passing a value map into getInstance() you
130:         * can also provide the values for properties programmatically:
131:         * <pre>
132:         *  // Evaluate it
133:         *  Object result = expression.getInstance().set("count", new Integer(3)).set("msg", "Guybrush was here on").evaluate();
134:         * </pre>
135:         * <font size=-1>Note: there's no exception-handling in this snippet; primitive-types
136:         * have to wrapped when provided; the time varies&nbsp;:)</font>
137:         * </p> 
138:         *
139:         * @author <A href="mailto:nils@meiers.net">Nils Meier</A>
140:         */
141:        public class Expression implements  Serializable {
142:
143:            /** the default packages that will be imported for the expression */
144:            private static Collection defaultImports = Arrays
145:                    .asList(new Object[] { "java.text.*", "java.util.*",
146:                            "java.io.*", "java.net.*" });
147:
148:            /** a VM flag that will turn on output of generated expressions in specified directory */
149:            public final static String PARAM_EXPRESSION_DIR = "instantj.expression.output";
150:
151:            /** the directory we store expressions into */
152:            private final static String expressionDir = System
153:                    .getProperty(PARAM_EXPRESSION_DIR);
154:
155:            /** internal enumeration of generated expressions */
156:            private static long count = 0;
157:
158:            /** the properties we've been told to prepare for the expression */
159:            private Map properties;
160:
161:            /** the compiled class for the instance of the expression */
162:            private CompiledClass compiled;
163:
164:            /**
165:             * Constructor for de-serialization
166:             */
167:            protected Expression() {
168:            }
169:
170:            /**
171:             * Constructor for a simple expression without properties.
172:             * For more information about what an expression is, look at the
173:             * {@link Expression class description}
174:             *
175:             * @param body the expression Java body
176:             * @exception CompilationFailedException when the expression couldn't be compiled
177:             */
178:            public Expression(String body) throws CompilationFailedException {
179:                this (body, new HashMap());
180:            }
181:
182:            /**
183:             * Constructor for an expression with properties.
184:             * For more information about what an expression is, look at the
185:             * {@link Expression class description}
186:             *
187:             * @param body the expression body (Java)
188:             * @param properties the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
189:             * @exception CompilationFailedException when the expression couldn't be compiled
190:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
191:             */
192:            public Expression(String body, Map properties)
193:                    throws CompilationFailedException {
194:                this (body, properties, new ArrayList());
195:            }
196:
197:            /**
198:             * Constructor for an expression with properties.
199:             * For more information about what an expression is, look at the
200:             * {@link Expression class description}
201:             *
202:             * @param body the expression body (Java)
203:             * @param props the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
204:             * @param imports imports to use (e.g java.util.*, java.sql.*)
205:             * @exception CompilationFailedException when the expression couldn't be compiled
206:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
207:             */
208:            public Expression(String body, Map props, Collection imports)
209:                    throws CompilationFailedException {
210:                this (body, props, imports, null);
211:            }
212:
213:            /**
214:             * Constructor for an expression with properties and a library.
215:             * For more information about what an expression is, look at the
216:             * {@link Expression class description}
217:             *
218:             * @param body the expression body (Java)
219:             * @param props the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
220:             * @param imports imports to use (e.g java.util.*, java.sql.*)
221:             * @param library of CompiledSources to use
222:             * @exception CompilationFailedException when the expression couldn't be compiled
223:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
224:             */
225:            public Expression(String body, Map props, Collection imports,
226:                    Collection library) throws CompilationFailedException {
227:                init(body, props, imports, library);
228:            }
229:
230:            /**
231:             * Initialization
232:             *
233:             * @param body the expression body (Java)
234:             * @param props the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
235:             * @param imports imports to use
236:             * @exception CompilationFailedException when the expression couldn't be compiled
237:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
238:             */
239:            private void init(String body, Map props, Collection imports,
240:                    Collection library) throws CompilationFailedException {
241:
242:                // Do we have imports or will we fall back to the defaults?
243:                if (imports == null || imports.isEmpty()) {
244:                    imports = defaultImports;
245:                }
246:
247:                // Remember the properties
248:                properties = new HashMap(props.size());
249:                Iterator ps = props.keySet().iterator();
250:                while (ps.hasNext()) {
251:
252:                    // Here's the property name and type
253:                    String p = (String) ps.next();
254:                    Object c = props.get(p);
255:
256:                    // .. might be a type or a type-name
257:                    if (!(c instanceof  Class)) {
258:                        if (!(c instanceof  String)) {
259:                            throw new IllegalArgumentException(
260:                                    "props has to map String to type (java.lang.Class) or type-name (java.lang.String)");
261:                        }
262:                        c = ReflectAccess.getInstance().calcClassFromName(
263:                                (String) c);
264:                    }
265:                    properties.put(p, c);
266:                }
267:
268:                // increase internal counter
269:                count++;
270:
271:                // Generate the well known source of the Expression
272:                Source s = generateSource(body, properties, imports);
273:
274:                // Compile (for now only to byte-code)
275:                compiled = Compiler.compile(s, true, new ArrayList(), library);
276:
277:                // Done for now
278:            }
279:
280:            /**
281:             * Constructor for a simple expression without properties.
282:             * For more information about what an expression is, look at the
283:             * {@link Expression class description}
284:             *
285:             * @param body the expression's body (Java)
286:             * @exception CompilationFailedException when the expression couldn't be compiled
287:             */
288:            public Expression(InputStream body)
289:                    throws CompilationFailedException, IOException {
290:                this (body, new HashMap());
291:            }
292:
293:            /**
294:             * Constructor for an expression with properties.
295:             * For more information about what an expression is, look at the
296:             * {@link Expression class description}
297:             *
298:             * @param body the expression body (Java)
299:             * @param properties the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
300:             * @exception CompilationFailedException when the expression couldn't be compiled
301:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
302:             */
303:            public Expression(InputStream body, Map properties)
304:                    throws CompilationFailedException, IOException {
305:                this (body, properties, new ArrayList());
306:            }
307:
308:            /**
309:             * Constructor for an expression with properties.
310:             * For more information about what an expression is, look at the
311:             * {@link Expression class description}
312:             *
313:             * @param body the expression body (Java)
314:             * @param properties the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
315:             * @param imports imports to use
316:             * @exception CompilationFailedException when the expression couldn't be compiled
317:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
318:             */
319:            public Expression(InputStream body, Map properties,
320:                    Collection imports) throws CompilationFailedException,
321:                    IOException {
322:                this (body, properties, imports, null);
323:            }
324:
325:            /**
326:             * Constructor for an expression with properties.
327:             * For more information about what an expression is, look at the
328:             * {@link Expression class description}
329:             *
330:             * @param body the expression body (Java)
331:             * @param properties the property-names mapped to types (java.lang.Class or java.lang.String). These will be available to the evaluated expression.
332:             * @param imports imports to use
333:             * @exception CompilationFailedException when the expression couldn't be compiled
334:             * @exception IllegalArgumentException when passed Hashtable does not map names (String) to types (Class)
335:             */
336:            public Expression(InputStream body, Map properties,
337:                    Collection imports, Collection library)
338:                    throws CompilationFailedException, IOException {
339:                init(load(body), properties, imports, library);
340:            }
341:
342:            /**
343:             * Helper that loads text from given InputStream
344:             */
345:            private static String load(InputStream in) throws IOException {
346:
347:                InputStreamReader reader = new InputStreamReader(in);
348:
349:                // We read from in
350:                char[] buffer = new char[4096];
351:                int length = reader.read(buffer, 0, buffer.length);
352:
353:                // Done
354:                return new String(buffer, 0, length);
355:            }
356:
357:            /**
358:             * Returns an instance of the expression for thread-private use
359:             */
360:            public ExpressionInstance getInstance() {
361:
362:                try {
363:                    return (ExpressionInstance) compiled.getType()
364:                            .newInstance();
365:                } catch (Throwable t) {
366:                    throw new RuntimeException(
367:                            "Unexpected failure while creating ExpressionInstance");
368:                }
369:            }
370:
371:            /**
372:             * Returns an ExpressionInstance with its properties' preset to values
373:             * in given context. 
374:             *
375:             * @param context a context for the evaluation of the expression. It
376:             *         maps property-names to -values. All properties specified in
377:             *         the expression's constructor will be preset with values from
378:             *         the map if possible.
379:             *         Either provide values of according property-type or values 
380:             *         that can be used in a one-argument-constructor of the according 
381:             *         property-type.
382:             * @exception IllegalPropertyException when a property doesn't match the expression's properties
383:             * @return the result
384:             */
385:            public ExpressionInstance getInstance(Map context)
386:                    throws IllegalPropertyException {
387:
388:                // Create a new Expression
389:                ExpressionInstance instance = getInstance();
390:
391:                // Prepare the values by looking at what properties where 
392:                // specified in the constructor
393:                try {
394:                    Iterator propertyKeys = properties.keySet().iterator();
395:                    while (propertyKeys.hasNext()) {
396:                        String p = (String) propertyKeys.next();
397:                        Object v = context.get(p);
398:
399:                        instance.set(p, v);
400:                    }
401:                } catch (InaccessiblePropertyException e) {
402:                    // ignored
403:                }
404:
405:                // Done
406:                return instance;
407:
408:            }
409:
410:            /**
411:             * Creates the source for given expression classname, body & properties
412:             */
413:            private Source generateSource(String body, Map properties,
414:                    Collection imports) {
415:
416:                // Create a memory writing destination
417:                StringBuffer buffer = new StringBuffer(4096);
418:
419:                // .. and the source comes here
420:                generateSourceHeader(buffer, imports);
421:                generateSourceFields(buffer, properties);
422:                generateSourceBody(buffer, body);
423:                generateSourceFooter(buffer);
424:
425:                // Debugging
426:                debug(buffer.toString());
427:
428:                // Done
429:                return new Source(buffer.toString());
430:            }
431:
432:            /**
433:             * Creates the source's header
434:             */
435:            private void generateSourceHeader(StringBuffer buffer,
436:                    Collection imports) {
437:
438:                // Here comes the class
439:                Iterator is = imports.iterator();
440:                while (is.hasNext()) {
441:                    buffer.append("import ");
442:                    buffer.append(is.next().toString());
443:                    buffer.append(";");
444:                }
445:
446:                buffer.append("public class Expression extends "
447:                        + ExpressionInstance.class.getName() + "{");
448:
449:                // Done    
450:            }
451:
452:            /**
453:             * Creates the source's members
454:             */
455:            private void generateSourceFields(StringBuffer buffer,
456:                    Map properties) {
457:
458:                // Then the fields
459:                try {
460:                    Iterator ps = properties.keySet().iterator();
461:                    while (ps.hasNext()) {
462:                        String name = (String) ps.next();
463:                        Class type = (Class) properties.get(name);
464:                        buffer.append("public " + type.getName() + " " + name
465:                                + ";");
466:                    }
467:                } catch (ClassCastException clastcastexception) {
468:                    throw new IllegalArgumentException(
469:                            "Mappings in properties have to be of String/Class");
470:                }
471:
472:                // Done    
473:            }
474:
475:            /**
476:             * Creastes the source's methods
477:             */
478:            private void generateSourceBody(StringBuffer buffer, String body) {
479:
480:                // And the evaluation method
481:                buffer.append("protected Object internalEvaluate(){");
482:
483:                // .. instruction lines	
484:                // Note: this is hard to figure out without lots of knowledge
485:                // about the expression syntax :( I've tried to search for
486:                // ';' AND '}' to catch the case where the evaluatable comes
487:                // after a code-block (1) - in that case placing objectify
488:                // behind works nice. But in case (2) objectify has to be placed
489:                // before that :(
490:                //
491:                // (1)
492:                //   if (true) { System.out("Foo"); } "Hello World"
493:                //  ->                             ^^^
494:                //   if (true) { System.out("Foo"); } objectify("Hello World");
495:                //
496:                // (2)
497:                //   new Object[]{ "a", "b", "c" }
498:                //  ->                          ^^^
499:                //   objectify( new Object[]{ "a", "b", "c" } );
500:                //
501:                // For now we require that '}' in instructions are closed off
502:                // with ';'
503:                int instructions = body.lastIndexOf(';');
504:                if (instructions >= 0) {
505:                    buffer.append(body.substring(0, instructions + 1));
506:                    body = body.substring(instructions + 1);
507:                }
508:                // .. and the (last and final) expression which is 'objectified'
509:                buffer.append("return objectify(" + body + ");}");
510:
511:                // Done
512:            }
513:
514:            /**
515:             * Creates the source's footer
516:             */
517:            private void generateSourceFooter(StringBuffer buffer) {
518:                // Simple!
519:                buffer.append('}');
520:                // Done    
521:            }
522:
523:            /**
524:             * A helper that debugs the ready-to-use expression's source
525:             */
526:            private void debug(String source) {
527:
528:                // Anything to do?    
529:                if (expressionDir == null) {
530:                    return;
531:                }
532:
533:                // Write it
534:                try {
535:
536:                    File file = File.createTempFile("Expression", ".java",
537:                            new File(expressionDir));
538:                    PrintWriter out = new PrintWriter(
539:                            new FileOutputStream(file));
540:                    out.print(source.toString());
541:                    out.close();
542:
543:                } catch (IOException e) {
544:                }
545:
546:                // Done
547:            }
548:
549:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.