Kohei Nozaki's blog 

BeanShell recipies


Posted on Sunday Jan 24, 2016 at 04:00PM in Technology


BeanShell is a handy lightweight scripting language for Java. In this entry, I’ll introduce you some useful snippets powered by BeanShell, and some recipies about it.

Setup and hello world

Grab a copy of bsh-2.0b4.jar from http://www.beanshell.org and put following shell script named bsh into your PATH:

#!/bin/sh
BEANSHELL_JAR=$HOME/Downloads/bsh-2.0b4.jar # replace path to suit your environment
java -cp $BEANSHELL_JAR bsh.Interpreter $@

Then fire up bsh from your console then just put print("hello, world!"); to confirm it works.

$ bsh
BeanShell 2.0b4 - by Pat Niemeyer (pat@pat.net)
bsh % print("hello, world!");
hello, world!

Hit Ctrl+D to exit interpreter.

You can launch your BeanShell script in a file as follows:

$ echo 'print("hello, world!");' > hello.bsh
$ bsh hello.bsh
hello, world!

Stdin

Text filtering script can be written as follows:

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
  String line = scanner.nextLine();
  System.out.println(line.toUpperCase());
}

Save this script as toUpperCase.bsh . The script can be executed as follows:

$ echo foo | bsh toUpperCase.bsh
FOO

Command line arguments

Command line arguments can be used as follows:

sb = new StringBuilder();
for (arg : bsh.args) {
    sb.append(arg);
}
print(sb);

Save this script as args.bsh. The script can be executed as follows:

$ bsh args.bsh foo bar
foobar

Use of external jar

Any external jar can be added via addClassPath clause dynamically. For example, a SQL beautifier script powered by a Hibernate class can be written as follows:

addClassPath("/path/to/hibernate-core-4.3.7.Final.jar"); // replace path to suit your environment
import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;

scanner = new Scanner(System.in);
sb = new StringBuilder();
while (scanner.hasNextLine()) {
  sb.append(scanner.nextLine()).append('\n');
}

beautifized = new BasicFormatterImpl().format(sb.toString());
print(beautifized);

Save this script as sql-beautifier.bsh then execute following command:

$ SQL="SELECT t0.content AS a2, t0.contenttype AS a3, t0.email AS a4 FROM roller_comment t0, weblogentry t1 WHERE ((t1.websiteid = 'f0588427-f2ca-4843-ac87-bbb31aa6013c') AND (t1.id = t0.entryid)) ORDER BY t0.posttime DESC LIMIT 31 OFFSET 0;"
$ echo $SQL | bsh sql-beautifier.bsh

This yields nicely formatted SQL:

SELECT
    t0.content AS a2,
    t0.contenttype AS a3,
    t0.email AS a4
FROM
    roller_comment t0,
    weblogentry t1
WHERE
    (
        (
            t1.websiteid = 'f0588427-f2ca-4843-ac87-bbb31aa6013c'
        )
        AND (
            t1.id = t0.entryid
        )
    )
ORDER BY
    t0.posttime DESC LIMIT 31 OFFSET 0;

Maven plugin

If you have Maven installed, you can execute any BeanShell script without obtaining bsh-2.0b4.jar by hand. Maven and the beanshell-maven-plugin takes care of it instead of you:

$ mvn com.github.genthaler:beanshell-maven-plugin:1.0:run -Dbsh.file="hello.bsh"
...
[INFO] --- beanshell-maven-plugin:1.0:run (default-cli) @ standalone-pom ---
[INFO] Executing Script
[INFO] file class java.lang.String
[INFO] script class java.lang.Object
[INFO] interpreting file hello.bsh
hello, world!

Note that you don’t need to create pom.xml to execute a simple BeanShell script.

For managing complex dependencies, you can leave that duty to Maven with pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>sql-beautifier</groupId>
    <artifactId>sql-beautifier</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>com.github.genthaler</groupId>
                <artifactId>beanshell-maven-plugin</artifactId>
                <version>1.0</version>
                <configuration>
                    <script><![CDATA[
                    import java.nio.charset.Charset;
                    import org.apache.commons.io.FileUtils;
                    import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;

                    file = new File(System.getProperty("sql"));
                    sql = FileUtils.readFileToString(file, Charset.defaultCharset());
                    result = new BasicFormatterImpl().format(sql);

                    print(result);
         ]]></script>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.hibernate</groupId>
                        <artifactId>hibernate-core</artifactId>
                        <version>4.3.7.Final</version>
                    </dependency>
                    <dependency>
                        <groupId>commons-io</groupId>
                        <artifactId>commons-io</artifactId>
                        <version>2.4</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

Save the SQL you want to beautify as original.sql and executing following command yields similar result:

$ mvn bsh:run -Dsql=original.sql

jEdit integration

jEdit has pretty nice integration with BeanShell. You can integrate that SQL beautifier as a jEdit macro. Put following snippet as ~/Library/jEdit/macros/FormatSQL.bsh (for OS X) or create it with Macros → New Macro from jEdit menu bar:

addClassPath("/path/to/hibernate-core-4.3.7.Final.jar"); // replace path to suit your environment
import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;

sql = textArea.getSelectedText();
beautifized = new BasicFormatterImpl().format(sql);
textArea.setSelectedText(beautifized);

Paste SQL to any jEdit buffer, and select SQL statement and execute the macro with Macros → FormatSQL to trigger formatting.