|
Comments
Did you read today's front page stories & breaking news?
SYS-CON.TV
|
Java Desktop BPP: The Beanshell Preprocessor
Increase your productivity benefits
By: Warren MacEvoy
Jun. 3, 2004 12:00 AM
The Beanshell preprocessor, or BPP for short, is intended to be a convenient and powerful preprocessing tool for Java developers. It's convenient because the preprocessor is based on Beanshell, which is essentially interpreted Java. This means that Java or Beanshell programmers can quickly use all of BPP's features. It's powerful for the same reasons: all the power of the Java SDK with the convenience of the Beanshell scripting language is available as double payment: once as a development language and once as a preprocessing language. In the current world of sexy words for new concepts in software development, a new preprocessor is sure to draw a yawn. But for Java developers, this preprocessor can revolutionize core software development. The reason is that it isn't actually just a new processor, but an entirely different kind of preprocessor: a symmetric preprocessor. A language with a symmetric preprocessor gives the full power (and syntax) of the language as a preprocessor, including the provision for a preprocessor, and so on. Getting BPP and Beanshell java bsh.Console from a command shell to start up the Beanshell desktop. A windowed Beanshell desktop should appear. In the window, type: you="Jay R. EE"; After seeing the expected message, add a sticky note to your monitor with the words: "Learn Beanshell now; save time later." For now, just close the Beanshell desktop (see Figure 1). BPP does not use the Beanshell desktop; instead it uses the bsh.Interpreter class internally as a lightweight Java interpreter. Show Me How Useful BPP Is!
#
# greetings=new String[] {
# "hola mundo",
# "ciao mondo",
# "hello world",
# "\u043F\u0440\u0438\u0432\u0435\u0442 \u043C\u0438\u0440",
# };
#
public class Xample1 {
public static void main(String[] args) {
#for (i=0;i<greetings.length; ++i) {
System.out.println("$(greetings[i])");
#}
}
}
If you save the above code in a file named Xample1.java.bpp, then running BPP with the line java -jar bp.jar Xample1.java.bpp will produce the following text in Xample1.java:
![]() The last line is "hello world" in Russian, and may appear strangely on systems that don't understand UTF-8 encoded unicode. Point is, the #'ed lines are executed at "preprocess time" by BPP. This results in a Java source file with, in compiler optimization parlance, an "unwound loop." Admittedly, unwinding the above loop at preprocess time will provide no particular advantage over executing the loop at runtime. There are places where such unwinding could make a great deal of difference. Similar preprocessor code could write substantial "boiler plate" code that you might otherwise use a more traditional "copy/paste/edit" approach on, but we will leave that to the reader's imagination (and online tutorials on the BPP Web site). The next example takes on a loftier software engineering goal: compile-time versus runtime safety. Safe Sets BPP can quickly create compile-time type-safe wrapper classes for collections (or wherever else you need them). Listing 1 provides a snippet of the type-safe template for Collection. To use the code in Listing 1, save it in a file called "makeTypedCollection.bpp" and generate the equivalent Beanshell script with: java -jar bpp.jar -b makeTypedCollection.bpp The -b option tells BPP to create the script, but not execute it. The script is written in this case to makeTypedCollection.bsh. With this handy "template" around, creating a compile-time type-safe collection is a snap. For example, a string collection would be the following smidgen of lines in StringCollection.java.bp: #source("makeTypedCollection.bsh"); Notice that I source the Beanshell script generated by BPP, not the BPP script itself. There is a philosophical point here: judicious use of BPP can move many checks from runtime to compile time. This can make an order-of-magnitude difference in how long it takes (and expensive it is) to find and correct mistakes. Now let's look at how BPP does its magic. You is What? Beanshell is a get-to-the-point Java. Typing:
you="Jay R. EE";
print("Welcome, " + you);
in Beanshell is equivalent to compiling and executing the following Java code:
public class SomeClass
{
public static void main(String[] args)
{
String you="Jay R. EE";
System.out.println("Welcome, " + you);
}
}
Which one would you rather type? See www.beanshell.org for many useful resources on Beanshell. For now, here is what I claim to be the shortest tutorial of a production programming language in history: Beanshell is an interpreted version of Java with optional types. Types are great for safety, but they can turn the quick and dirty into the slow and tedious. Beanshell adheres to types you specify, but also allows unspecified types so you can choose your safety level. As of version 2.0, Beanshell has seamless integration with JDK 1.3 and above. Thus Beanshell is a flexible superset of Java that I encourage any Java developer to get to know. How Does It Work?
#n=10;
#for(i=0; i<n; ++i) {
becomes
n=10;
for(i=0; i<n; ++i) {
in the Beanshell script. -$ is a legal start and part of a Java identifier. If you need to have such a value in a BP script use $(my$-strange$id). -When $ is not succeeded by an identifier, a left parenthesis, or another $, it simply represents a single $. $$ on a magically quoted line represents a single $. For example: #static import bpp.Format.*; "Dear $title $lastName; "You owe $$$(N(blnc,"#,###.00")). becomes
static import bpp.Format.*;
print("Dear "+title+" "+lastName+";");
print("You owe $"+(N(blnc,"#,###.00"))+".");
in the Beanshell script. For those new to Beanshell, print() is equivalent to System.out.println(). The N(Number n,String f) method is a static member of the bpp.Format class as a convenience for formatting numbers. '#static import bpp.Format.*; 'Dear $title $lastName; 'You owe $(N(blnc,"$#,###.00")). becomes
print("#static import bpp.Format.*;");
print("Dear $title $lastName;");
print("You owe $(N(blnc,\"$#,###.00\")).");
in the Beanshell script. Putting these together for the first example, the first BPP source file, Xample1.java.bpp, produces the Beanshell script:
greetings=new String[] {
"hola mundo",
"ciao mondo",
"hello world",
"\u043F\u0440\u0438\u0432\u0435\u0442 \u043C\u0438\u0440",
};
print("");
print("public class Xample1 {");
print(" public static void main(String[] args) {");
for (i=0;i<greetings.length; ++i) {
print(" System.out.println(\""+(greetings[i])+"\");");
}
print(" }");
print("}");
Executing this script with Beanshell generates the promised pure Java source file shown above as Xample1.java. Conclusion Here are a few other gains. Have Fun! Big Tools Make Little Ones Dr. Piet Jonas in his "Type Safe Collections" article also addresses type safety, but in another manner. Jonas' idea is to verify the types for collections at insertion time using runtime type information. This causes an exception to be thrown early (at insertion time) rather than late (at extraction time). In either case, the exception is thrown at runtime. The type-safe wrappers we suggest using here allow for compile-time safety. Protecting IP Simplification Enjoy BPP! References Reader Feedback: Page 1 of 1
Your Feedback
SOA World Latest Stories
Subscribe to the World's Most Powerful Newsletters
Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
|
SYS-CON Featured Whitepapers
Most Read This Week |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||