📄 netrexxengine.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.netrexx;import java.io.File;import java.io.FileOutputStream;import java.io.FilenameFilter;import java.io.PrintWriter;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.Hashtable;import java.util.Vector;import org.apache.bsf.BSFDeclaredBean;import org.apache.bsf.BSFException;import org.apache.bsf.BSFManager;import org.apache.bsf.util.BSFEngineImpl;import org.apache.bsf.util.BSFFunctions;import org.apache.bsf.util.EngineUtils;import org.apache.bsf.util.MethodUtils;import org.apache.bsf.util.StringUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;/** * This is the interface to NetRexx from the * Bean Scripting Framework. * <p> * The NetRexx code must be written script-style, without a "class" or * "properties" section preceeding the executable code. The NetRexxEngine will * generate a prefix for this code: * <pre> * <code> * class $$CLASSNAME$$; * method BSFNetRexxEngineEntry(bsf=org.apache.bsf.BSFManager) public static; * </code> * </pre> * $$CLASSNAME$$ will be replaced by a generated classname of the form * BSFNetRexx*, 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 -- BSFNetRexxEngine will * replace it with the generated name of the class before the NetRexx code * is compiled. * <p> * If you need to use full NetRexx functionality, we recommend that your * NetRexx script define and invoke a "minor class", with or without the * "dependent" keyword as suits your needs. You'll have to use $$CLASSNAME$$ * in naming the minor class, since the name of the main class is synthesized; * for example, to create the minor class "bar" you'd write * "class $$CLASSNAME$$.Bar". * <p> * <h2>Hazards:</h2> * <p> * Since NetRexx 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; we * hash against the script string to find the class for it. * <p> * Minor-class .class files are now being deleted after the major class loads. * This coould potentially cause problems. * * @author Joe Kesselman * @author Sanjiva Weerawarana */public class NetRexxEngine extends BSFEngineImpl{ BSFFunctions mgrfuncs; 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. * * I've made the offset static, due to concerns about reuse/reentrancy * of the NetRexx engine. */ private static int uniqueFileOffset=0; 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; } } // rexxclass used to be an instance variable, on the theory that // each NetRexxEngine was an instance of a specific script. // BSF is currently reusing Engines, so caching the class // no longer makes sense. // Class rexxclass; /** * Constructor. */ public NetRexxEngine () { /* The following line is intended to cause the constructor to throw a NoClassDefFoundError if the NetRexxC.zip dependency is not resolved. If this line was not here, the problem would not surface until the actual processing of a script. We want to know all is well at the time the engine is instantiated, not when we attempt to process a script. */ new netrexx.lang.BadArgumentException(); } /** * Return an object from an extension. * @param object object from which to call our static method * @param method The name of the method to call. * @param args an array of arguments to be * passed to the extension, which may be either * Vectors of Nodes, or Strings. */ public Object call (Object object, String method, Object[] args) throws BSFException { throw new BSFException(BSFException.REASON_UNSUPPORTED_FEATURE, "NetRexx doesn't currently support call()", null); } /** * Invoke a static method. * @param rexxclass Class to invoke the method against * @param method The name of the method to call. * @param args an array of arguments to be * passed to the extension, which may be either * Vectors of Nodes, or Strings. */ Object callStatic(Class rexxclass, String method, Object[] args) throws BSFException { //***** ISSUE: Currently supports only static methods Object retval = null; try { if (rexxclass != 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(rexxclass, method, argtypes); retval=m.invoke(null,args); } else { logger.error("NetRexxEngine: ERROR: rexxclass==null!"); } } catch(Exception e) { e.printStackTrace (); if (e instanceof InvocationTargetException) { Throwable t = ((InvocationTargetException)e).getTargetException (); t.printStackTrace (); } throw new BSFException (BSFException.REASON_IO_ERROR, e.getMessage (), e); } return retval; } public void declareBean (BSFDeclaredBean bean) throws BSFException {} /** * Override impl of execute. In NetRexx, methods which do not wish * to return a value should be invoked via exec, which will cause them * to be generated without the "returns" clause. * Those which wish to return a value should call eval instead. * which will add "returns java.lang.Object" to the header. * * Note: It would be nice to have the "real" return type avaialable, so * we could do something more type-safe than Object, and so we could * return primitive types without having to enclose them in their * object wrappers. BSF does not currently support that concept. */ public Object eval (String source, int lineNo, int columnNo, Object script) throws BSFException { return execEvalShared(source, lineNo, columnNo, script,true); } /** * Override impl of execute. In NetRexx, methods which do not wish * to return a value should be invoked via exec, which will cause them * to be generated without the "returns" clause. * Those which wish to return a value should call eval instead. * which will add "returns java.lang.Object" to the header. */ public void exec (String source, int lineNo, int columnNo, Object script) throws BSFException { execEvalShared(source, lineNo, columnNo, script,false); } /** * This is shared code for the exec() and eval() operations. It will * evaluate a string containing a NetRexx method body -- which may be * as simple as a single return statement. * It should store the "bsf" handle where the * script can get to it, for callback purposes. * <p> * Note that NetRexx compilation imposes serious overhead -- 11 seconds for * the first compile, about 3 thereafter -- but in exchange you get * Java-like speeds 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 the compilers to protect it. */ public Object execEvalShared (String source, int lineNo, int columnNo, Object oscript,boolean returnsObject) throws BSFException {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -