Home

Back

Contents

Next

BeanShell Commands

BeanShell commands take the form of pre-defined methods such as print(). BeanShell Commands are are mostly composed of BeanShell scripts, supplied in the JAR file. We'll talk about adding your own commands to the classpath a bit later.

Commands Overview

This is a high level overview of the BeanShell command set. You can find documentation for all BeanShell commands in the "BeanShell Commands Documentation" section of this manual. See also the "BshDoc" section which covers javadoc style documenation of BeanShell script files.

Interpreter Modes

The following commands affect general modes of operation of the interpreter.
exit() Exit the interpreter. (Also Control-D).
show() Turn on "show" mode which prints the result of every evaluation that is not of void type.
setAccessibility() Turn on access to private and protected members of Java classes.
server() Launch the remote access mode, allowing remote access to the interpreter from a web browser or telnet client.
debug() Turns on debug mode. Note: this is very verbose, unstructured output and is primarily of interest to developers.
setStrictJava() Turn on "strict Java" mode which enforces Java compatability by dissallowing loose types and undeclared variables.

Output

The following commands are used for output:
print(), error() Print output to standard out or standard error. print() always goes to the console, whereas System.out may or may not be captured by a GUI console or servlet.
frame() Display the AWT or Swing component in a Frame

Source and Evaluation

The following commands are used for evaluation or to run external scripts or applications:
eval() Evaluate a string as if it were typed in the current scope.
source() Source an external file into the current interpreter
run(), bg() Run an external file in a subordinate interpreter or in a background thread in a subordinate interpreter.
exec() Run a native executable in the host OS

Utilities

The following commands are useful utilities:
javap() Print the methods and fields of an object, similar to the output of javap
which() Like the Unix 'which' command for executables. Map the classpath and determine the location of the specified class.
load(), save() load a serializable object from a file or save one to a file. Special handling is provided for certain objects.
object() Create an "emtpy" object context to hold variables; analagous to a Map.

Variables and Scope

The following commands affect the current scope:
clear()Clear all variables, methods and imports from the current scope.
unset()Remove a variable from the current scope. (Return it to the "undefined" state).
setNameSpace() Set the current namespace to a specified scope. Effectively bind the current scope to a new parent scope.

Classpath

The following commands manipulate or access the classpath:
addClassPath(), setClassPath(), getClassPath() Modify the BeanShell classpath.
reloadClasses() Reload a class or group of classes.
getClass() Load a class explicitly taking into account the BeanShell classpath.
getResource() Get a resource from the classpath.

Files and Directories

The following commands work with files, directories, and the working directory:
cd(), pwd(), dir(), rm(), mv(), cat() Unix Style file commands.
pathToFile() Translate a relative path to an absolute path taking into account the BeanShell current working directory.

Desktop and Class Browser

The following commands work with GUI tools:
classBrowser(), browseClass() Open a class browser window or browse a specific class or object.
desktop() Launch the BeanShell GUI desktop.
setNameCompletion() Turn on or off name completion in the GUI console.

Note:
The dir() command is written in Java; primarily as a demonstration of how to do this when desired.

Adding Commands to BeanShell

Adding to the set of "prefab" commands supplied with BeanShell is as easy as writing any other BeanShell methods. You simply have to place your script into a file named with the same name as the command and place the file in the classpath under a bsh/commands/ path. The command files can be anywhere in the classpath - in your own directories or in a JAR file.

For example, let's make a helloworld() command:

// File: helloworld.bsh
helloworld() { 
    print("Hello World!");
}

If we place helloworld.bsh in the classpath under the path bsh/commands/ we can now use helloworld() just like any other BeanShell command.

BeanShell command scripts can contain any number of overloaded forms of the method, e.g.:

// File: helloworld.bsh
helloworld() { print("Hello World!"); }
helloworld( String msg ) { print(msg); }

You can also implement BeanShell commands directly in Java as compiled class files which are dynamically loaded when needed. The dir() command is an example of a BeanShell command that is implemented in Java. See it for an example.

Commands Scope

BeanShell commands are always sourced into the 'global' scope. A useful feature of BeanShell for command writers is the 'this.caller' reference, which allows you to create side effects in the caller's scope. For example:

// File: setvar.bsh
fooSetter() {
    this.caller.foo=42;
}

The above command has the effect that after running it the variable 'foo' will be set in the current scope. e.g.:

fooSetter();
print( foo ); // 42

It would not have been correct in this example for the command to refer to 'super', as that would simply always point to the global scope.

Getting the Caller Context

We mentioned earlier in this manual the difference between the 'super' or parent context of a method and the caller's context. The 'super' of a method is always the context in which the method was defined. But the caller may be any context in which the method is used. In the following example, the parent context of foo() and the caller context of foo() are the same:

foo() { ... }
foo();

But this is not always the case, as for bar() in the following example:

foo() { 
    bar() { ... }
    ...
}

// somewhere
fooObject.bar();

The special "magic" field reference: 'this.caller' makes it possible to reach the context of whomever called bar(). The 'this.caller' reference always refers to the calling context of the current method context.

The diagram above shows the foo() and bar() scopes, along with the caller's scope access via 'this.caller'.

The most common example of where this is useful is in writing BeanShell commands. BeanShell command methods are always loaded into the global scope. If you refer to 'super' from your command you will simply get 'global'. Often it is desirable to write commands that explicitly have side effects in the caller's scope. The ability to do so makes it possible to write new kinds of commands that have the appearance of being "built-in" to the language.

A good example of this is the eval() BeanShell command. eval() evaluates a string as if it were typed in the current context. To do this, it sends the string to an instance of the BeanShell interpreter. But when it does so it tells the interpreter to evaluate the string in a specfic namespace: the namespace of the caller; using this.caller.

    eval("a=5");
    print( a ); // 5

You can follow the call chain further back if you want to by chaining the '.caller' reference, like so:

    this.caller.caller...;

Or, more generally, another magic reference 'this.callstack' returns an array of bsh.NameSpace objects representing the full call "stack". This is an advanced topic for developers that we'll discuss in another location.

Getting the Invocation Text

You can get specific information about the invocation of a method using namespace.getInvocationLine() and namespace.getInvocationText(). The most important use for this is in support of the ability to write an assert() method for unit tests that automatically prints the assertion text.

assert( boolean condition ) 
{
    if ( condition )
        print( "Test Passed..." );
    else {
        print(
            "Test FAILED: "
            +"Line: "+ this.namespace.getInvocationLine()
            +" : "+this.namespace.getInvocationText()
            +" : while evaluating file: "+getSourceFileInfo()
        );
        super.test_failed = true;
    }
}

Working With Class Identifiers

You may have noticed that certain BeanShell commands such as javap(), which(), and browseClass() which take a class as an argument can accept any type of argument, including a plain Java class identifier. For example, all of the following are legal:

javap( class ); // use a class type directly
javap( someobject ); // uses class of object
javap( "java.lang.Thread" ); // Uses string name of class
javap( java.lang.Thread );  // Use plain class identifier

In the last case above we used the plain Java class identifier java.lang.Thread. In Beanshell this resolves to a bsh.Name.ClassIdentifier reference. You can get the class for a ClassIdentifier using the Name.identifierToClass() method. Here is an example of how to work with all of the above, converting the argument to a class type:

    if ( o instanceof Name.ClassIdentifier )
        clas = this.namespace.identifierToClass(o);
    if ( o instanceof String)
        clas = this.namespace.getClass((String)o);
    else if ( o instanceof Class )
        clas = o;
    else
        clas = o.getClass();


Home

Back

Contents

Next