You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bsf-dev@jakarta.apache.org by sa...@apache.org on 2006/09/02 20:13:31 UTC

svn commit: r439627 - in /jakarta/bsf/trunk: build.xml src/org/apache/bsf/BSFManager.java src/org/apache/bsf/Main.java src/org/apache/bsf/engines/java/JavaEngine.java

Author: sanka
Date: Sat Sep  2 11:13:30 2006
New Revision: 439627

URL: http://svn.apache.org/viewvc?rev=439627&view=rev
Log:
Applied the set of patches sent by Kev Jackson. Many thanks Kev ..

Modified:
    jakarta/bsf/trunk/build.xml
    jakarta/bsf/trunk/src/org/apache/bsf/BSFManager.java
    jakarta/bsf/trunk/src/org/apache/bsf/Main.java
    jakarta/bsf/trunk/src/org/apache/bsf/engines/java/JavaEngine.java

Modified: jakarta/bsf/trunk/build.xml
URL: http://svn.apache.org/viewvc/jakarta/bsf/trunk/build.xml?rev=439627&r1=439626&r2=439627&view=diff
==============================================================================
--- jakarta/bsf/trunk/build.xml (original)
+++ jakarta/bsf/trunk/build.xml Sat Sep  2 11:13:30 2006
@@ -62,7 +62,7 @@
 	<!-- =================================================================== -->
 	<patternset id="java.source.files">
 		<!-- Optionally includes engines based on dependencies being present -->
-		<!-- FIXME: Exclude the first three, temporarily -->
+
 
 		<include name="**/bsf/*.java" />
 		<include name="**/util/**/*.java" />
@@ -179,7 +179,7 @@
 		<antcall target="checkJython" />
 		<antcall target="checkNetRexx" />
 		<antcall target="checkRhino" />
-		<!--<echo message="Warning: Rhino dependencies were not resolved." unless="rhino.present"/>-->
+
 		<antcall target="checkXalan" />
 		<antcall target="checkJUnit" />
 	</target>
@@ -196,9 +196,11 @@
 		<mkdir dir="${build.dest}"/>
 		<javac srcdir="${src.dir}" destdir="${build.dest}" debug="${project.debug}" deprecation="${project.deprecation}">
 			<classpath>
-				<fileset dir="lib"><include name="*.jar"/></fileset>
+				<fileset dir="lib">
+					<include name="*.jar"/>
+				</fileset>
 			</classpath>
-			<patternset refid="java.source.files"></patternset>			
+			<patternset refid="java.source.files"/>
 		</javac>
 	</target>
 
@@ -252,11 +254,11 @@
 			<classpath refid="anakia.classpath" />
 		</taskdef>
 
-		<anakia basedir="${site.src}" destdir="${site.dest}/" extension=".html" style="./site.vsl" projectFile="${site.projectFile}" excludes="**/stylesheets/** faq.xml" includes="**/*.xml" lastModifiedCheck="true" templatePath="${templ.path}" velocityPropertiesFile="${velocity.props}">
-		</anakia>
+		<anakia basedir="${site.src}" destdir="${site.dest}/" extension=".html" style="./site.vsl" projectFile="${site.projectFile}" excludes="**/stylesheets/** faq.xml" includes="**/*.xml" lastModifiedCheck="true" templatePath="${templ.path}" velocityPropertiesFile="${velocity.props}"/>
+
+
+		<anakia basedir="${site.src}" destdir="${site.dest}/" extension=".html" style="./faq.vsl" projectFile="${site.projectFile}" includes="faq.xml" lastModifiedCheck="true" templatePath="${templ.path}" velocityPropertiesFile="${velocity.props}"/>
 
-		<anakia basedir="${site.src}" destdir="${site.dest}/" extension=".html" style="./faq.vsl" projectFile="${site.projectFile}" includes="faq.xml" lastModifiedCheck="true" templatePath="${templ.path}" velocityPropertiesFile="${velocity.props}">
-		</anakia>
 
 		<copy todir="${site.dest}/images" filtering="no">
 			<fileset dir="${site.src}/images">
@@ -370,4 +372,4 @@
 	</target>
 
 	<target name="all" depends="build-site, dist" />
-</project>
+</project>
\ No newline at end of file

Modified: jakarta/bsf/trunk/src/org/apache/bsf/BSFManager.java
URL: http://svn.apache.org/viewvc/jakarta/bsf/trunk/src/org/apache/bsf/BSFManager.java?rev=439627&r1=439626&r2=439627&view=diff
==============================================================================
--- jakarta/bsf/trunk/src/org/apache/bsf/BSFManager.java (original)
+++ jakarta/bsf/trunk/src/org/apache/bsf/BSFManager.java Sat Sep  2 11:13:30 2006
@@ -25,6 +25,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.MissingResourceException;
 import java.util.NoSuchElementException;
 import java.util.Properties;
@@ -114,16 +115,17 @@
                 Properties p = new Properties();
                 p.load(is);
 
-                Enumeration keys = p.propertyNames();
-                while (keys.hasMoreElements()) {
+                for (Enumeration keys = p.propertyNames(); keys.hasMoreElements();) {
+
                     String key = (String) keys.nextElement();
                     String value = p.getProperty(key);
+                    String className = value.substring(0, value.indexOf(","));
+
+
 
-                    StringTokenizer tokens = new StringTokenizer(value, ",");
-                    String className = (String) tokens.nextToken();
 
                     // get the extensions for this language
-                    String exts = (String) tokens.nextToken();
+                    String exts = value.substring(value.indexOf(",")+1, value.length());
                     StringTokenizer st = new StringTokenizer(exts, "|");
                     String[] extensions = new String[st.countTokens()];
                     for (int i = 0; st.hasMoreTokens(); i++) {
@@ -133,16 +135,16 @@
                     registerScriptingEngine(key, className, extensions);
                 }
             }
-        }
-        catch (IOException ex) {
+        } catch (IOException ex) {
+
             ex.printStackTrace();
             System.err.println("Error reading Languages file " + ex);
-        }
-        catch (NoSuchElementException nsee) {
+        } catch (NoSuchElementException nsee) {
+
             nsee.printStackTrace();
             System.err.println("Syntax error in Languages resource bundle");
-        }
-        catch (MissingResourceException mre) {
+        } catch (MissingResourceException mre) {
+
             mre.printStackTrace();
             System.err.println("Initialization error: " + mre.toString());
         }
@@ -163,8 +165,8 @@
          *      &quot;dd&quot; two digit day.
      * @since 2006-01-17
      */
-    public static String getVersion()
-    {
+    public static String getVersion() {
+
         return version;
     }
 
@@ -210,8 +212,8 @@
                         }
                     });
             result = resultf;
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception: ", prive);
             throw (BSFException) prive.getException();
         }
@@ -263,8 +265,8 @@
                         return null;
                     }
                 });
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception :", prive);
             throw (BSFException) prive.getException();
         }
@@ -306,8 +308,8 @@
                         return null;
                     }
                 });
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception :", prive);
             throw (BSFException) prive.getException();
         }
@@ -350,8 +352,8 @@
                         return null;
                     }
                 });
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception :", prive);
             throw (BSFException) prive.getException();
         }
@@ -439,8 +441,8 @@
                         }
                     });
             result = resultf;
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception: ", prive);
             throw (BSFException) prive.getException();
         }
@@ -487,8 +489,8 @@
                         return null;
                     }
                 });
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception :", prive);
             throw (BSFException) prive.getException();
         }
@@ -527,8 +529,8 @@
                         return null;
                     }
                 });
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	logger.error("Exception :", prive);
             throw (BSFException) prive.getException();
         }
@@ -550,8 +552,8 @@
         if (classPath == null) {
             try {
                 classPath = System.getProperty("java.class.path");
-            }
-            catch (Throwable t) {
+            } catch (Throwable t) {
+
             	logger.debug("Exception :", t);
                 // prolly a security exception .. so no can do
             }
@@ -577,8 +579,9 @@
 
         if (dotIndex != -1) {
             String extn = fileName.substring(dotIndex + 1);
-            String langval = (String) extn2Lang.get(extn), lang = null;
-            int index = 0, loops = 0;
+            String langval = (String) extn2Lang.get(extn);
+            String lang = null;
+            int index, loops = 0;
 
             if (langval != null) {
                 while ((index = langval.indexOf(":", 0)) != -1) {
@@ -594,8 +597,8 @@
                         String engineName =
                             (String) registeredEngines.get(lang);
                         Class.forName(engineName);
-                    }
-                    catch (ClassNotFoundException cnfe) {
+                    } catch (ClassNotFoundException cnfe) {
+
                         // Bummer.
                         lang = langval;
                         continue;
@@ -604,7 +607,7 @@
                     // Got past that? Good.
                     break;
                 }
-                if (loops == 0) lang = langval;
+                if (loops == 0) { lang = langval; }
             }
 
             if (lang != null && lang != "") {
@@ -700,12 +703,12 @@
             loadedEngines.put(lang, eng);
             pcs.addPropertyChangeListener(eng);
             return eng;
-        }
-        catch (PrivilegedActionException prive) {
+        } catch (PrivilegedActionException prive) {
+
         	    logger.error("Exception :", prive);
                 throw (BSFException) prive.getException();
-        }
-        catch (Throwable t) {
+        } catch (Throwable t) {
+
         	logger.error("Exception :", t);
             throw new BSFException(BSFException.REASON_OTHER_ERROR,
                                    "unable to load language: " + lang,
@@ -726,8 +729,8 @@
 
         try {
             return ((BSFDeclaredBean)objectRegistry.lookup(beanName)).bean;
-        }
-        catch (IllegalArgumentException e) {
+        } catch (IllegalArgumentException e) {
+
         	logger.debug("Exception :", e);
             return null;
         }
@@ -747,8 +750,8 @@
 
         if(bean == null) {
             tempBean = new BSFDeclaredBean(beanName, null, null);
-        }
-        else {
+        } else {
+
             tempBean = new BSFDeclaredBean(beanName, bean, bean.getClass());
         }
         objectRegistry.register(beanName, tempBean);
@@ -871,8 +874,8 @@
 
         BSFDeclaredBean tempBean = null;
         boolean found = false;
-        for (int i = 0; i < declaredBeans.size(); i++) {
-            tempBean = (BSFDeclaredBean) declaredBeans.elementAt(i);
+        for (Iterator i = declaredBeans.iterator(); i.hasNext();) {
+            tempBean = (BSFDeclaredBean) i.next();
             if (tempBean.name.equals(beanName)) {
             	found = true;
                 break;
@@ -900,4 +903,4 @@
 
         objectRegistry.unregister(beanName);
     }
-}
+}
\ No newline at end of file

Modified: jakarta/bsf/trunk/src/org/apache/bsf/Main.java
URL: http://svn.apache.org/viewvc/jakarta/bsf/trunk/src/org/apache/bsf/Main.java?rev=439627&r1=439626&r2=439627&view=diff
==============================================================================
--- jakarta/bsf/trunk/src/org/apache/bsf/Main.java (original)
+++ jakarta/bsf/trunk/src/org/apache/bsf/Main.java Sat Sep  2 11:13:30 2006
@@ -92,7 +92,7 @@
 				in = new FileReader(inFileName);
 			} else {
 				in = new InputStreamReader(System.in);
-				inFileName = "<STDIN>";
+				inFileName = DEFAULT_IN_FILE_NAME;
 			}
 
 			BSFManager mgr = new BSFManager();
@@ -114,45 +114,47 @@
 					cb);
 				cb.print(pw, true);
 				out.close();
-			} else
+			} else {
 				if (mode.equals(ARG_VAL_EXEC)) {
 					mgr.exec(language, inFileName, 0, 0, IOUtils.getStringFromReader(in));
-				} else /* eval */ {
-					Object obj =
-                                            mgr.eval(language, inFileName, 0, 0, IOUtils.getStringFromReader(in));
-                                        
+				} else { /* eval */
+					Object obj = mgr.eval(language, inFileName, 0, 0, IOUtils.getStringFromReader(in));
+
+
 					// Try to display the result.
-                                        
+
 					if (obj instanceof java.awt.Component) {
-                                            Frame f;
-                                            
-                                            if (obj instanceof Frame) {
-						f = (Frame) obj;
-                                            } else {
-						f = new Frame ("BSF Result: " + inFileName);
-						f.add ((java.awt.Component) obj);
-                                            }
-                                            
-                                            // Add a window listener to quit on closing.
-                                            f.addWindowListener(
-                                                                new WindowAdapter () {
-                                                                    public void windowClosing (WindowEvent e) {
-                                                                        System.exit (0);
-                                                                    }
-                                                                });
-                                            f.pack ();
-                                            f.show ();
+					    Frame f;
+                        if (obj instanceof Frame) {
+                            f = (Frame) obj;
+                        } else {
+                            f = new Frame ("BSF Result: " + inFileName);
+                            f.add ((java.awt.Component) obj);
+                        }
+                        // Add a window listener to quit on closing.
+                        f.addWindowListener(
+                                new WindowAdapter () {
+                                    public void windowClosing (WindowEvent e) {
+                                        System.exit (0);
+                                    }
+                                }
+                        );
+                        f.pack ();
+                        f.show ();
+
 					} else {
-                                            System.err.println("Result: " + 
-                                                               obj);
+                        System.err.println("Result: " + obj);
+
 					}
-                                        
+
 					System.err.println("Result: " + obj);
 				}
+            }
 		} catch (BSFException e) {
-                    e.printStackTrace();
+		    e.printStackTrace();
 		}
 	}
+    
 	private static void printHelp() {
 		System.err.println("Usage:");
 		System.err.println();
@@ -183,4 +185,4 @@
 		System.err.println(
 			"      [-out              className]   default: " + DEFAULT_CLASS_NAME);
 	}
-}
+}
\ No newline at end of file

Modified: jakarta/bsf/trunk/src/org/apache/bsf/engines/java/JavaEngine.java
URL: http://svn.apache.org/viewvc/jakarta/bsf/trunk/src/org/apache/bsf/engines/java/JavaEngine.java?rev=439627&r1=439626&r2=439627&view=diff
==============================================================================
--- jakarta/bsf/trunk/src/org/apache/bsf/engines/java/JavaEngine.java (original)
+++ jakarta/bsf/trunk/src/org/apache/bsf/engines/java/JavaEngine.java Sat Sep  2 11:13:30 2006
@@ -81,291 +81,271 @@
  * <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;
+    }
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: bsf-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: bsf-dev-help@jakarta.apache.org