Many scripting languages are used in the computing field today: VB, Perl, Python, JavaScript, Tcl/TK, REXX, and others. A project that originated at IBM, the Bean Scripting Framework (BSF) aims to provide a way to allow all of them to interoperate with Java.
The BSF consists of a management API, an engine API for driving different scripting languages, and a series of plug-ins for different scripting languages. The management API lets you either evaluate an expression in the given scripting language, such as “2+2” (which is so simple as to be valid in most supported languages), or run a script stored in a script file. In this example I’ll use JPython, a pure-Java (certified) implementation of the scripting language Python (see http://www.python.org or the O’Reilly book Learning Python).
While it is convenient (and efficient) to run JPython in the same JVM as the calling program, this is not by any means a requirement; for example, it is possible to use BSF with scripting languages written in some native language. BSF and the scripting plug-in are responsible for dealing with whatever “plumbing” -- external connections or processes -- this requires. In fact, BSF currently supports the languages listed in Table 26-1.
Table 26-1. Languages supported by BSF
Language |
Description |
---|---|
JPython |
Java implementation of Python |
Jacl |
Java implementation/interface for Tcl |
Bean Markup Language (BML) |
Related language, from IBM |
LotusXSL |
XML stylesheets (see Section 21.2) |
NetRexx |
REXX variant |
Netscape Rhino |
JavaScript implementation |
Pnuts |
Scripting language for accessing Java APIs |
Microsoft Active Scripting Format (MASF) |
Microsoft analog of BSF |
BSF could also support MacOS Apple Scripting or almost any other language, though I don’t know of an implementation at present.
Example 26-5 uses
JPython to evaluate and print the value of
22/7, a crude approximation of Math.PI
, using the
management API’s eval( )
function.
Example 26-5. BSFSample.java
import com.ibm.cs.util.*; import com.ibm.bsf.*; import java.io.*; /** Sample of using Bean Scripting Framework with JPython */ public class BSFSample { public static void main(String[] args) { BSFManager manager = new BSFManager( ); // register scripting language String[] fntypes = { ".py" }; manager.registerScriptingEngine("jpython", "com.ibm.bsf.engines.jpython.JPythonEngine", fntypes); try { BSFEngine jpythonengine = manager.loadScriptingEngine("jpython"); // try an expression Object r = manager.eval("jpython", "testString", 0, 0, "22.0/7"); System.out.println("Result type is " + r.getClass().getName( )); System.out.println("Result value is " + r); } catch (Exception ex) { System.err.println(ex.toString( )); } System.out.println("Scripting demo done."); return; } }
This program prints the following output:
$ java BSFSample 'import exceptions' failed; using string-based exceptions Result type is org.python.core.PyFloat Result value is 3.142857142857143 Scripting demo done. $
The exceptions failure is probably due to my having installed JPython in a non-standard location and not setting the environment variable(s) needed to find it. Further, the first time you run it, JPython spits out a bunch of nattering about your CLASSPATH, one line for each JAR file that it finds. These can be a bit surprising when they pop up from a script, but JPython doesn’t seem to know or care whether it’s being run interactively or dynamically.
packageManager: processing new jar, "/usr/local/java/swingall.jar"
The following longer example uses the
LabelText
bean from Section 23.8 and a push button to run a Python script that
collects the text from the LabelText
instance and
displays it on the standard output. Here is the little script,
buttonhandler.py
:
print "Hello"; print bean.getText( );
When I ran this, I typed the famous words that Alexander Graham Bell apparently sent to his assistant Watson, and had the Java program send them to the Python script.
Sure enough, when I clicked on the button, I got this on the standard output (as shown in Figure 26-2):
Script output: --> Hello Mr. Watson, come here <-- End of Script output.
Nothing you couldn’t do in Java, of course, but in this example
the LabelText
bean is registered with the BSF as a
bean, and the JButton
’s action handler runs a script
that gets that text and displays it. Example 26-6
shows the source code for the script-using program.
Example 26-6. BSFAction.java
import com.ibm.cs.util.*; import com.ibm.bsf.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; /** Longer sample of using Bean Scripting Framework with JPython */ public class BSFAction { protected String FILENAME = "buttonhandler.py"; protected BSFManager manager; protected BSFEngine jpythonengine; protected String language; protected String script; public static void main(String[] args) { new BSFAction( ); } BSFAction( ) { // Construct the Bean instance LabelText bean = new LabelText("Message to Python script"); try { manager = new BSFManager( ); // register scripting language String[] fntypes = { ".py" }; manager.registerScriptingEngine("jpython", "com.ibm.bsf.engines.jpython.JPythonEngine", fntypes); jpythonengine = manager.loadScriptingEngine("jpython"); // Tell BSF about the bean. manager.declareBean("bean", bean, LabelText.class); // Read the script file into BSF language = manager.getLangFromFilename(FILENAME); script = IOUtils.getStringFromReader( new FileReader(FILENAME)); } catch (Exception ex) { System.err.println(ex.toString( )); System.exit(0); } System.out.println("Scripting setup done, building GUI."); final JFrame jf = new JFrame(getClass().getName( )); Container cp = jf.getContentPane( ); cp.setLayout(new FlowLayout( )); cp.add(bean); // add the LabelText JButton b = new JButton("Click me!"); cp.add(b); // and the button under it. b.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent evt) { try { // When the button is pressed, run the script. System.out.println("Script output: -->"); manager.exec(language, FILENAME, 0, 0, script); System.out.println("<-- End of Script output."); } catch (BSFException bse) { JOptionPane.showMessageDialog(jf, "ERROR: " + bse, "Script Error", JOptionPane.ERROR_MESSAGE); } } }); // A Quit button at the bottom JButton qb = new JButton("Quit"); cp.add(qb); qb.addActionListener(new ActionListener( ) { public void actionPerformed(ActionEvent evt) { System.exit(0); } }); // Routine JFrame setup jf.pack( ); jf.setVisible(true); } }
Information on the Bean Scripting Framework is currently located on IBM’s alphaWorks web site, under http://oss.software.ibm.com/developerworks/projects/bsf/.
JPython has been taken under a new umbrella and renamed Jython; see http://www.jython.org.
There are many other projects that aim to blend Java with other languages. As a single example, check out the OmegaHat project’s interface at http://www.omegahat.org/RSJava/. R, itself a clone of S (http://cm.bell-labs.com/cm/ms/departments/sia/S/) is the statistical package used to produce the charts back in Figure 5-1. This interface lets you use Java inside R or S, and also to call R or S from Java code.
3.144.15.43