-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Applied.
Thanks,
Sanka
Kev Jackson wrote:
> Hi,
>
> Another one: - change style to Java style (braces, spacing general
> layout) - remove extra lines
>
> For this one the code makes use of a tempdir specified as "." -
> wouldn't it make sense to use java.io.tmpdir? If the generated
> files were created in a subdirectory of the real tmpdir, then it
> would be possible to simply rmdir after instead of using the much
> more complicated Filter code.
>
> Kev
>
> ----------------------------------------------------------------------
>
>
> Index: .
> ===================================================================
> --- . (revision 438751) +++ . (working copy) @@ -81,291 +81,272 @@
> * <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,endpoint; -
> if((startpoint=script.indexOf(placeholder))>=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=internal_call(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[]
> minor_classfiles= - 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<minor_classfiles.length;++i) - { - file=new
> File(minor_classfiles[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 internal_call
> (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; - } +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; + } }
>
>
> ----------------------------------------------------------------------
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED] For
> additional commands, e-mail: [EMAIL PROTECTED]
- --
Sanka Samaranayake
WSO2 Inc.
T:+94-77-3506382 F:+94-11-2424304
http://sankas.blogspot.com/
http://www.wso2.net/
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2.1 (GNU/Linux)
iD8DBQFE+dRq/Hd0ETKdgNIRAmjMAJ4kVRwsfhC64A4SiXo41uxoU5h7qQCfb3oB
+bnId39GGWmi/PkuW2lkgOY=
=6Ehm
-----END PGP SIGNATURE-----
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]