Source Code Cross Referenced for JavaEngine.java in  » Scripting » bsf-2.4.0 » org » apache » bsf » engines » java » 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 » bsf 2.4.0 » org.apache.bsf.engines.java 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2004,2004 The Apache Software Foundation.
003:         * 
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         * 
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         * 
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.apache.bsf.engines.java;
018:
019:        import java.io.File;
020:        import java.io.FileOutputStream;
021:        import java.io.FilenameFilter;
022:        import java.lang.reflect.Method;
023:        import java.util.Hashtable;
024:        import java.util.Vector;
025:
026:        import org.apache.bsf.BSFException;
027:        import org.apache.bsf.BSFManager;
028:        import org.apache.bsf.util.BSFEngineImpl;
029:        import org.apache.bsf.util.CodeBuffer;
030:        import org.apache.bsf.util.EngineUtils;
031:        import org.apache.bsf.util.JavaUtils;
032:        import org.apache.bsf.util.MethodUtils;
033:        import org.apache.bsf.util.ObjInfo;
034:        import org.apache.commons.logging.Log;
035:        import org.apache.commons.logging.LogFactory;
036:
037:        /**
038:         * This is the interface to Java from the
039:         * Bean Scripting Framework.
040:         * <p>
041:         * The Java code must be written script-style -- that is, just the body of
042:         * the function, without class or method headers or footers.
043:         * The JavaEngine will generate those via a "boilerplate" wrapper:
044:         * <pre>
045:         * <code>
046:         * import java.lang.*;
047:         * import java.util.*;
048:         * public class $$CLASSNAME$$ {
049:         *   static public Object BSFJavaEngineEntry(org.apache.bsf.BSFManager bsf) {
050:         *     // Your code will be placed here
051:         *   }
052:         * }
053:         * </code>
054:         * </pre>
055:         * $$CLASSNAME$$ will be replaced by a generated classname of the form
056:         * BSFJava*, and the bsf parameter can be used to retrieve application
057:         * objects registered with the Bean Scripting Framework.
058:         * <p>
059:         * If you use the placeholder string $$CLASSNAME$$ elsewhere
060:         * in your script -- including within text strings -- BSFJavaEngine will
061:         * replace it with the generated name of the class before the Java code
062:         * is compiled.
063:         * <p>
064:         * <h2>Hazards:</h2>
065:         * <p>
066:         * NOTE that it is your responsibility to convert the code into an acceptable
067:         * Java string. If you're invoking the JavaEngine directly (as in the
068:         * JSPLikeInJava example) that means \"quoting\" characters that would
069:         * otherwise cause trouble.
070:         * <p>
071:         * ALSO NOTE that it is your responsibility to return an object, or null in
072:         * lieu thereof!
073:         * <p>
074:         * Since the code has to be compiled to a Java classfile, invoking it involves
075:         * a fair amount of computation to load and execute the compiler. We are
076:         * currently making an attempt to manage that by caching the class
077:         * after it has been loaded, but the indexing is fairly primitive. It has
078:         * been suggested that the Bean Scripting Framework may want to support
079:         * preload-and-name-script and execute-preloaded-script-by-name options to
080:         * provide better control over when and how much overhead occurs.
081:         * <p>
082:         * @author Joe Kesselman
083:         */
084:        public class JavaEngine extends BSFEngineImpl {
085:            Class javaclass = null;
086:            static Hashtable codeToClass = new Hashtable();
087:            static String serializeCompilation = "";
088:            static String placeholder = "$$CLASSNAME$$";
089:            String minorPrefix;
090:
091:            private Log logger = LogFactory.getLog(this .getClass().getName());
092:
093:            /**
094:             * Create a scratchfile, open it for writing, return its name.
095:             * Relies on the filesystem to provide us with uniqueness testing.
096:             * NOTE THAT uniqueFileOffset continues to count; we don't want to
097:             * risk reusing a classname we have previously loaded in this session
098:             * even if the classfile has been deleted.
099:             */
100:            private int uniqueFileOffset = -1;
101:
102:            private class GeneratedFile {
103:                File file = null;
104:                FileOutputStream fos = null;
105:                String className = null;
106:
107:                GeneratedFile(File file, FileOutputStream fos, String className) {
108:                    this .file = file;
109:                    this .fos = fos;
110:                    this .className = className;
111:                }
112:            }
113:
114:            /**
115:             * Constructor.
116:             */
117:            public JavaEngine() {
118:                // Do compilation-possible check here??????????????
119:            }
120:
121:            public Object call(Object object, String method, Object[] args)
122:                    throws BSFException {
123:                throw new BSFException(BSFException.REASON_UNSUPPORTED_FEATURE,
124:                        "call() is not currently supported by JavaEngine");
125:            }
126:
127:            public void compileScript(String source, int lineNo, int columnNo,
128:                    Object script, CodeBuffer cb) throws BSFException {
129:                ObjInfo oldRet = cb.getFinalServiceMethodStatement();
130:
131:                if (oldRet != null && oldRet.isExecutable()) {
132:                    cb.addServiceMethodStatement(oldRet.objName + ";");
133:                }
134:
135:                cb.addServiceMethodStatement(script.toString());
136:                cb.setFinalServiceMethodStatement(null);
137:            }
138:
139:            /**
140:             * This is used by an application to evaluate a string containing
141:             * some expression. It should store the "bsf" handle where the
142:             * script can get to it, for callback purposes.
143:             * <p>
144:             * Note that Java compilation imposes serious overhead,
145:             * but in exchange you get full Java performance
146:             * once the classes have been created (minus the cache lookup cost).
147:             * <p>
148:             * Nobody knows whether javac is threadsafe.
149:             * I'm going to serialize access to protect it.
150:             * <p>
151:             * There is no published API for invoking javac as a class. There's a trick
152:             * that seems to work for Java 1.1.x, but it stopped working in Java 1.2.
153:             * We will attempt to use it, then if necessary fall back on invoking
154:             * javac via the command line.
155:             */
156:            public Object eval(String source, int lineNo, int columnNo,
157:                    Object oscript) throws BSFException {
158:                Object retval = null;
159:                String classname = null;
160:                GeneratedFile gf = null;
161:
162:                String basescript = oscript.toString();
163:                String script = basescript; // May be altered by $$CLASSNAME$$ expansion
164:
165:                try {
166:                    // Do we already have a class exactly matching this code?
167:                    javaclass = (Class) codeToClass.get(basescript);
168:
169:                    if (javaclass != null) {
170:                        classname = javaclass.getName();
171:                    } else {
172:                        gf = openUniqueFile(tempDir, "BSFJava", ".java");
173:                        if (gf == null) {
174:                            throw new BSFException(
175:                                    "couldn't create JavaEngine scratchfile");
176:                        }
177:                        // Obtain classname
178:                        classname = gf.className;
179:
180:                        // Write the kluge header to the file.
181:                        gf.fos
182:                                .write(("import java.lang.*;"
183:                                        + "import java.util.*;"
184:                                        + "public class " + classname + " {\n" + "  static public Object BSFJavaEngineEntry(org.apache.bsf.BSFManager bsf) {\n")
185:                                        .getBytes());
186:
187:                        // Edit the script to replace placeholder with the generated
188:                        // classname. Note that this occurs _after_ the cache was checked!
189:                        int startpoint = script.indexOf(placeholder);
190:                        int endpoint;
191:                        if (startpoint >= 0) {
192:                            StringBuffer changed = new StringBuffer();
193:                            for (; startpoint >= 0; startpoint = script
194:                                    .indexOf(placeholder, startpoint)) {
195:                                changed.setLength(0); // Reset for 2nd pass or later
196:                                if (startpoint > 0) {
197:                                    changed.append(script.substring(0,
198:                                            startpoint));
199:                                }
200:                                changed.append(classname);
201:                                endpoint = startpoint + placeholder.length();
202:                                if (endpoint < script.length()) {
203:                                    changed.append(script.substring(endpoint));
204:                                }
205:                                script = changed.toString();
206:                            }
207:                        }
208:
209:                        // MJD - debug
210:                        //              BSFDeclaredBean tempBean;
211:                        //              String          className;
212:                        //              
213:                        //              for (int i = 0; i < declaredBeans.size (); i++) {
214:                        //              tempBean  = (BSFDeclaredBean) declaredBeans.elementAt (i);
215:                        //              className = StringUtils.getClassName (tempBean.bean.getClass ());
216:                        //              
217:                        //              gf.fos.write ((className + " " +
218:                        //              tempBean.name + " = (" + className +
219:                        //              ")bsf.lookupBean(\"" +
220:                        //              tempBean.name + "\");").getBytes ());
221:                        //              }
222:                        // MJD - debug
223:
224:                        // Copy the input to the file.
225:                        // Assumes all available -- probably mistake, but same as other engines.
226:                        gf.fos.write(script.getBytes());
227:                        // Close the method and class
228:                        gf.fos.write(("\n  }\n}\n").getBytes());
229:                        gf.fos.close();
230:
231:                        // Compile through Java to .class file
232:                        // May not be threadsafe. Serialize access on static object:
233:                        synchronized (serializeCompilation) {
234:                            JavaUtils.JDKcompile(gf.file.getPath(), classPath);
235:                        }
236:
237:                        // Load class.
238:                        javaclass = EngineUtils.loadClass(mgr, classname);
239:
240:                        // Stash class for reuse
241:                        codeToClass.put(basescript, javaclass);
242:                    }
243:
244:                    Object[] callArgs = { mgr };
245:                    retval = internalCall(this , "BSFJavaEngineEntry", callArgs);
246:                }
247:
248:                catch (Exception e) {
249:                    e.printStackTrace();
250:                    throw new BSFException(BSFException.REASON_IO_ERROR, e
251:                            .getMessage());
252:                } finally {
253:                    // Cleanup: delete the .java and .class files
254:
255:                    //          if(gf!=null && gf.file!=null && gf.file.exists())
256:                    //          gf.file.delete();  // .java file
257:
258:                    if (classname != null) {
259:                        // Generated class
260:                        File file = new File(tempDir + File.separatorChar
261:                                + classname + ".class");
262:                        //              if(file.exists())
263:                        //              file.delete();
264:
265:                        // Search for and clean up minor classes, classname$xxx.class
266:                        file = new File(tempDir); // ***** Is this required?
267:                        minorPrefix = classname + "$"; // Indirect arg to filter
268:                        String[] minorClassfiles = file
269:                                .list(new FilenameFilter() {
270:                                    // Starts with classname$ and ends with .class
271:                                    public boolean accept(File dir, String name) {
272:                                        return (0 == name.indexOf(minorPrefix))
273:                                                && (name.lastIndexOf(".class") == name
274:                                                        .length() - 6);
275:                                    }
276:                                });
277:                        for (int i = 0; i < minorClassfiles.length; ++i) {
278:                            file = new File(minorClassfiles[i]);
279:                            //                  file.delete();
280:                        }
281:                    }
282:                }
283:                return retval;
284:            }
285:
286:            public void initialize(BSFManager mgr, String lang,
287:                    Vector declaredBeans) throws BSFException {
288:                super .initialize(mgr, lang, declaredBeans);
289:            }
290:
291:            /**
292:             * Return an object from an extension.
293:             * @param object Object on which to make the internal_call (ignored).
294:             * @param method The name of the method to internal_call.
295:             * @param args an array of arguments to be
296:             * passed to the extension, which may be either
297:             * Vectors of Nodes, or Strings.
298:             */
299:            Object internalCall(Object object, String method, Object[] args)
300:                    throws BSFException {
301:                //***** ISSUE: Only static methods are currently supported
302:                Object retval = null;
303:                try {
304:                    if (javaclass != null) {
305:                        //***** This should call the lookup used in BML, for typesafety
306:                        Class[] argtypes = new Class[args.length];
307:                        for (int i = 0; i < args.length; ++i) {
308:                            argtypes[i] = args[i].getClass();
309:                        }
310:                        Method m = MethodUtils.getMethod(javaclass, method,
311:                                argtypes);
312:                        retval = m.invoke(null, args);
313:                    }
314:                } catch (Exception e) {
315:                    throw new BSFException(BSFException.REASON_IO_ERROR, e
316:                            .getMessage());
317:                }
318:                return retval;
319:            }
320:
321:            private GeneratedFile openUniqueFile(String directory,
322:                    String prefix, String suffix) {
323:                File file = null;
324:                FileOutputStream fos = null;
325:                int max = 1000; // Don't try forever
326:                GeneratedFile gf = null;
327:                int i;
328:                String className = null;
329:                for (i = max, ++uniqueFileOffset; fos == null && i > 0; --i, ++uniqueFileOffset) {
330:                    // Probably a timing hazard here... ***************
331:                    try {
332:                        className = prefix + uniqueFileOffset;
333:                        file = new File(directory + File.separatorChar
334:                                + className + suffix);
335:                        if (file != null && !file.exists()) {
336:                            fos = new FileOutputStream(file);
337:                        }
338:                    } catch (Exception e) {
339:                        // File could not be opened for write, or Security Exception
340:                        // was thrown. If someone else created the file before we could
341:                        // open it, that's probably a threading conflict and we don't
342:                        // bother reporting it.
343:                        if (!file.exists()) {
344:                            logger.error("openUniqueFile: unexpected ", e);
345:                        }
346:                    }
347:                }
348:                if (fos == null) {
349:                    logger.error("openUniqueFile: Failed " + max + "attempts.");
350:                } else {
351:                    gf = new GeneratedFile(file, fos, className);
352:                }
353:                return gf;
354:            }
355:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.