⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 javaengine.java

📁 Bean Scripting Framework (BSF)为在java应用中使用脚本语言
💻 JAVA
字号:
/* * Copyright 2004,2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.bsf.engines.java;import java.io.File;import java.io.FileOutputStream;import java.io.FilenameFilter;import java.lang.reflect.Method;import java.util.Hashtable;import java.util.Vector;import org.apache.bsf.BSFException;import org.apache.bsf.BSFManager;import org.apache.bsf.util.BSFEngineImpl;import org.apache.bsf.util.CodeBuffer;import org.apache.bsf.util.EngineUtils;import org.apache.bsf.util.JavaUtils;import org.apache.bsf.util.MethodUtils;import org.apache.bsf.util.ObjInfo;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * This is the interface to Java from the * Bean Scripting Framework. * <p> * The Java code must be written script-style -- that is, just the body of * the function, without class or method headers or footers. * The JavaEngine will generate those via a "boilerplate" wrapper: * <pre> * <code> * import java.lang.*; * import java.util.*; * public class $$CLASSNAME$$ { *   static public Object BSFJavaEngineEntry(org.apache.bsf.BSFManager bsf) { *     // Your code will be placed here *   } * } * </code> * </pre> * $$CLASSNAME$$ will be replaced by a generated classname of the form * BSFJava*, and the bsf parameter can be used to retrieve application * objects registered with the Bean Scripting Framework. * <p> * If you use the placeholder string $$CLASSNAME$$ elsewhere * in your script -- including within text strings -- BSFJavaEngine will * replace it with the generated name of the class before the Java code * is compiled. * <p> * <h2>Hazards:</h2> * <p> * NOTE that it is your responsibility to convert the code into an acceptable * Java string. If you're invoking the JavaEngine directly (as in the * JSPLikeInJava example) that means \"quoting\" characters that would * otherwise cause trouble. * <p> * ALSO NOTE that it is your responsibility to return an object, or null in * lieu thereof! * <p> * Since the code has to be compiled to a Java classfile, invoking it involves * a fair amount of computation to load and execute the compiler. We are * currently making an attempt to manage that by caching the class * after it has been loaded, but the indexing is fairly primitive. It has * been suggested that the Bean Scripting Framework may want to support * preload-and-name-script and execute-preloaded-script-by-name options to * provide better control over when and how much overhead occurs. * <p> * @author Joe Kesselman */public class JavaEngine extends BSFEngineImpl {    Class javaclass = null;    static Hashtable codeToClass = new Hashtable();    static String serializeCompilation = "";    static String placeholder = "$$CLASSNAME$$";    String minorPrefix;            private Log logger = LogFactory.getLog(this.getClass().getName());        /**     * Create a scratchfile, open it for writing, return its name.     * Relies on the filesystem to provide us with uniqueness testing.     * NOTE THAT uniqueFileOffset continues to count; we don't want to     * risk reusing a classname we have previously loaded in this session     * even if the classfile has been deleted.     */    private int uniqueFileOffset = -1;        private class GeneratedFile {        File file = null;        FileOutputStream fos = null;        String className = null;        GeneratedFile(File file, FileOutputStream fos, String className) {            this.file = file;            this.fos = fos;            this.className = className;        }    }        /**     * Constructor.     */    public JavaEngine () {        // Do compilation-possible check here??????????????    }        public Object call (Object object, String method, Object[] args)     throws BSFException    {        throw new BSFException (BSFException.REASON_UNSUPPORTED_FEATURE,        "call() is not currently supported by JavaEngine");    }        public void compileScript (String source, int lineNo, int columnNo,            Object script, CodeBuffer cb) throws BSFException {        ObjInfo oldRet = cb.getFinalServiceMethodStatement ();                if (oldRet != null && oldRet.isExecutable ()) {            cb.addServiceMethodStatement (oldRet.objName + ";");        }                cb.addServiceMethodStatement (script.toString ());        cb.setFinalServiceMethodStatement (null);    }        /**     * This is used by an application to evaluate a string containing     * some expression. It should store the "bsf" handle where the     * script can get to it, for callback purposes.     * <p>     * Note that Java compilation imposes serious overhead,     * but in exchange you get full Java performance     * once the classes have been created (minus the cache lookup cost).     * <p>     * Nobody knows whether javac is threadsafe.     * I'm going to serialize access to protect it.     * <p>     * There is no published API for invoking javac as a class. There's a trick     * that seems to work for Java 1.1.x, but it stopped working in Java 1.2.     * We will attempt to use it, then if necessary fall back on invoking     * javac via the command line.     */    public Object eval (String source, int lineNo, int columnNo,             Object oscript) throws BSFException            {        Object retval = null;        String classname = null;        GeneratedFile gf = null;                String basescript = oscript.toString();        String script = basescript;	// May be altered by $$CLASSNAME$$ expansion                try {            // Do we already have a class exactly matching this code?            javaclass = (Class)codeToClass.get(basescript);                        if(javaclass != null) {                classname=javaclass.getName();            } else {                gf = openUniqueFile(tempDir, "BSFJava",".java");                if( gf == null) {                    throw new BSFException("couldn't create JavaEngine scratchfile");                }                // Obtain classname                classname = gf.className;                                // Write the kluge header to the file.                gf.fos.write(("import java.lang.*;"+                        "import java.util.*;"+                        "public class "+classname+" {\n" +                "  static public Object BSFJavaEngineEntry(org.apache.bsf.BSFManager bsf) {\n")                .getBytes());                                // Edit the script to replace placeholder with the generated                // classname. Note that this occurs _after_ the cache was checked!                int startpoint = script.indexOf(placeholder);                int endpoint;                if(startpoint >= 0) {                    StringBuffer changed = new StringBuffer();                    for(; startpoint >=0; startpoint = script.indexOf(placeholder,startpoint)) {                        changed.setLength(0);	// Reset for 2nd pass or later                        if(startpoint > 0) {                            changed.append(script.substring(0,startpoint));                        }                        changed.append(classname);                        endpoint = startpoint+placeholder.length();                        if(endpoint < script.length()) {                            changed.append(script.substring(endpoint));                        }                        script = changed.toString();                    }                }                                // MJD - debug//              BSFDeclaredBean tempBean;//              String          className;//              //              for (int i = 0; i < declaredBeans.size (); i++) {//              tempBean  = (BSFDeclaredBean) declaredBeans.elementAt (i);//              className = StringUtils.getClassName (tempBean.bean.getClass ());//              //              gf.fos.write ((className + " " +//              tempBean.name + " = (" + className +//              ")bsf.lookupBean(\"" +//              tempBean.name + "\");").getBytes ());//              }                // MJD - debug                                // Copy the input to the file.                // Assumes all available -- probably mistake, but same as other engines.                gf.fos.write(script.getBytes());                // Close the method and class                gf.fos.write(("\n  }\n}\n").getBytes());                gf.fos.close();                                // Compile through Java to .class file                // May not be threadsafe. Serialize access on static object:                synchronized(serializeCompilation) {                    JavaUtils.JDKcompile(gf.file.getPath(), classPath);                }                                // Load class.                javaclass = EngineUtils.loadClass(mgr, classname);                                // Stash class for reuse                codeToClass.put(basescript, javaclass);            }                        Object[] callArgs = {mgr};                  retval = internalCall(this,"BSFJavaEngineEntry",callArgs);        }                        catch(Exception e) {            e.printStackTrace ();            throw new BSFException (BSFException.REASON_IO_ERROR, e.getMessage ());        } finally {            // Cleanup: delete the .java and .class files            //          if(gf!=null && gf.file!=null && gf.file.exists())//          gf.file.delete();  // .java file                                    if(classname!=null) {                // Generated class                File file = new File(tempDir+File.separatorChar+classname+".class");//              if(file.exists())//              file.delete();                                // Search for and clean up minor classes, classname$xxx.class                file = new File(tempDir);  // ***** Is this required?                minorPrefix = classname+"$"; // Indirect arg to filter                String[] minorClassfiles = file.list(new FilenameFilter()                            {                        // Starts with classname$ and ends with .class                        public boolean accept(File dir,String name) {                            return                            (0 == name.indexOf(minorPrefix))                            &&                            (name.lastIndexOf(".class") == name.length()-6);                        }                            });                for(int i = 0; i < minorClassfiles.length; ++i) {                    file = new File(minorClassfiles[i]);//                  file.delete();                }            }        }        return retval;    }        public void initialize (BSFManager mgr, String lang,            Vector declaredBeans) throws BSFException {        super.initialize (mgr, lang, declaredBeans);    }    /**     * Return an object from an extension.     * @param object Object on which to make the internal_call (ignored).     * @param method The name of the method to internal_call.     * @param args an array of arguments to be     * passed to the extension, which may be either     * Vectors of Nodes, or Strings.     */    Object internalCall (Object object, String method, Object[] args)     throws BSFException    {        //***** ISSUE: Only static methods are currently supported        Object retval = null;        try {            if(javaclass != null) {                //***** This should call the lookup used in BML, for typesafety                Class[] argtypes = new Class[args.length];                for(int i=0; i<args.length; ++i) {                    argtypes[i]=args[i].getClass();                }                Method m = MethodUtils.getMethod(javaclass, method, argtypes);                retval = m.invoke(null, args);            }        }        catch(Exception e) {            throw new BSFException (BSFException.REASON_IO_ERROR, e.getMessage ());        }        return retval;    }        private GeneratedFile openUniqueFile(String directory,String prefix,String suffix) {        File file = null;        FileOutputStream fos = null;        int max = 1000;		// Don't try forever        GeneratedFile gf = null;        int i;        String className = null;        for(i=max,++uniqueFileOffset; fos==null && i>0;--i,++uniqueFileOffset) {            // Probably a timing hazard here... ***************            try {                className = prefix+uniqueFileOffset;                file = new File(directory+File.separatorChar+className+suffix);                if(file != null && !file.exists()) {                    fos = new FileOutputStream(file);                }            }            catch(Exception e) {                // File could not be opened for write, or Security Exception                // was thrown. If someone else created the file before we could                // open it, that's probably a threading conflict and we don't                // bother reporting it.                if(!file.exists()) {                    logger.error("openUniqueFile: unexpected ", e);                }            }        }        if(fos==null) {            logger.error("openUniqueFile: Failed "+max+"attempts.");        } else {            gf = new GeneratedFile(file,fos,className);        }        return gf;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -