Supported scripting languages
After the installation, the following languages will be available out-of-the-box:
- Javascript;
- Groovy;
- Beanshell;
- Jaskell;
- Jelly;
- JRuby;
- JScheme;
- Jython;
- Pnuts;
- TCL;
- AWK;
- Java FX;
- Fortress;
- Scala;
- Velocity;
- Freemarker.
For example:
// hello.js
importPackage(Packages.java.lang);
System.out.println("Hello!!!");
In the same way you can work with Beanshell scripts:
// hello.bsh
System.out.println("Hello!!!");
Similarly we can create and run scripts for Groovy language. It is very interesting new
language with the set of advanced features such as closures, native support
for various markup languages (html, xml, ant etc.). For example:
// helloworld.groovy
println("Hello world")
Groovy scripts can be used to get access the Ant API in "Groovy"-like way.
For example:
ant = new AntBuilder()
ant.echo("hello")
myDir = "dist/src"
ant.mkdir(dir:myDir)
ant.copy(todir:myDir) {
fileset(dir:".") {
include(name:"**/*.groovy")
}
}
ant.input(message:"Press Return key to continue...")
ant.delete(dir:"target")
ant.echo("done")
We also can run jelly script, that looks almost like Ant script (but not competely):
Lets start by calling the echo task:
End.
As you can see, we can mix Ant tasks with plain text. Plus, this script will execute tasks
and display plain text sequentially (there is no "target" tag used).
Ant scripts as regular scriptlets (antlets)
We can introduce scripting support for Ant projects. Let's think about Ant projects not only
as the way for creating development projects, but also as the convenient infrastructure
for expressing various scenarios, built from the sequence of Ant tasks. Using optional
"script" Ant task, we can "plug-in" any other scripting language to it, greatly extending
in such a way basic functionality of the Ant.
We can register yet another extension for the Ant scripts: ".ant". Let's call such script
as "antlet", little Ant scripts. Such scripts are regular Ant build files,
but you don't have to specify build file name or to have predefined name,
like build.xml. For example:
Hello, World!!!
You can use any other scripting language inside antlets. To work with the scripting
engines, Ant uses Bean Scripting Framework (BSF). Jar files for this framework and
jars for the scripting engines should be present in CLASSPATH. Scriptlandia takes care
about these details.
For example:
In similar way you can use Java Scripting Framework:
Antlets can be used as the convenient way for building command-line tools.
By mixing predefined Ant tasks with scripting languages code, we can build
something more powerful, like Java compiler, Jar tool etc. It could be general
tool or very specific tool that serves your today needs. For example:
Antlet adapter
If you are not ready to convert your favorite project file into antlet,
let's use the adapter:
Executing antlets from inside "jar" files
Current implementation of Java execution mechanism uses special MANIFEST.MF file
properties to represent Java "jar" file as an executable:
>java -jar jarfile.jar
By using antlets we can build more powerful framework. Say, we want to assign set of
commands with given jar file (not only starting the application, but more powerful set of commands).
To do it, we prepare special file with the predefined name: "default.ant". This file resides
inside "META-INF" directory, similar to "MANIFEST.MF" file.
As an example, let's associate two commands: "start" and "stop" with our jar file.
Antlet for this case looks like:
Now, we have to associate "jar" extension with special launcher program (it is the part
of the framework), which extracts this antlet from the archive, prepares
"project" object and then executes specified target. The variable "${jar.file}"
is prepared inside this launcher program.
The typical execution will look like:
>Test.jar
>Test.jar start
>Test.jar stop
First 2 commands do exactly the same: execute "start" target. The 3rd command
executes "stop" target.
The following command runs "start" then "stop" targets consequentially:
>Test.jar start stop
Working with command line parameters in antlets
When we work with the scripting languages outside of antlets, we have access
to the command line in the standard for this language way (see documentation
for the given language).
For antlets we have to introduce special mechanism, which can "filter" Ant targets
and separate them from command line parameters:
>CommandLine.ant start [a] [b] [c]
In the above example we have "start" target and command line: "a b c".
In the similar way we can prepare command line for the new "jar" executable:
>Test.jar start [a] [b] [c]
Repetitive execution of Ant commands
It is possible to load Ant script into the memory (for standalone antlets or
antlets from jar files) and run them periodically without reloading Ant
script for every execution.
To do it, place "-i" parameter on your command line:
>test.ant -i
or
>Test.jar -i
In this case the user has the ability to enter various targets interactively
along with the command line parameters.
To leave the interactive mode, enter the "quit" ("q") command.
This interactive mode is supported for all scripts withing Scriptlandia.
Forcing GUI mode
If your script is based on AWT or Swing, we need to make sure not to close
awt-thread from execution. You have to use -wait command line parameter:
>testWithGui.bsh -wait
Jelly Scripts
Jelly is yet another interesting scripting language that uses xml syntax to express itself.
For example:
Hello World!
It is possible to include "ant" script inside "jelly" script. You need to include ant tags library:
Lets start by calling the echo task:
Java home is ${java.home}
End.
The jelly launcher is dependent on the following tag libraries:
- "commons-jelly-tags-ant";
- "commons-jelly-tags-beanshell";
- "commons-jelly-tags-sql";
- "commons-jelly-tags-swing";
- "commons-jelly-tags-swt";
- "commons-jelly-tags-define";
- "commons-jelly-tags-log".
New tag libraries could be easily added to the framework by including new dependencies.
Velocity and Freemarker templates
Velocity templates can be treated as another type of scripting language. The situation
here is more complex than usual, because Velocity is expecting some external parameters
to be entered in order to generate actual source from the template.
The solution used here is to use beanshell script as the object with actual parameters
(context object). This "beanshell" script has predefined name: "context.bsh". If you need
to use other name, specify it on command line next to velocity script name:
>test1.vm
>test2.vm myContext.bsh
For example, context file can contain this information:
// context.bsh
import org.apache.velocity.VelocityContext;
VelocityContext context = new VelocityContext();
context.put("name", "Velocity");
context.put("project", "Jakarta");
return context;
Velocity template will look like this:
## test1.vm
Hello from $name in the $project project.
In same way we can execute Freemarker scripts:
// context.bsh
Map context = new HashMap();
context.put("message", "Hello from Freemarker!");
return context;
And then freemarker template:
FreeMarker Example Web Application 1
${message}
APT tool
Java 5 support APT tool for processing annotations in user defined way. In order to do this,
separate factory class should be written, compiled and registered. This process is tedious.
In order to simplify this process, Apt-Jelly library is used. Instead of using Java code for
representing the factory, dynamic languages are used instead: Jelly and Freemarker.
Apt-Jelly library is already registered as the dependency. In order to use this abilities,
your factory file should have apt-jelly or apt-fmt extension.
For example, in order to process all java files in src directory, you have to execute
the following command:
>test.apt-fmt src/.../*.java
Dynamic loading of external libraries
We have Ant task in order to dynamically add new libraries to the Ant script.
Usually, If you have the Ant script, that is relying on 3-rd party library, you have to download
this library and install it somewhere. Or you have already this library, previously installed
somewhere. To make the situation controllable, we can write simple script-adapter:
For beanshell scripts we can use addClassPath() method to have libraries dynamically loaded.
In the following example beanshell script is ant-aware and can perform manipulations
with Ant API:
// run-ant.bsh
addClassPath("ant-1.7.1.jar");
addClassPath("ant-launcher-1.7.1.jar");
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.DefaultLogger;
Project project = new Project();
project.init();
BuildLogger logger = new DefaultLogger();
logger.setMessageOutputLevel(Project.MSG_INFO);
logger.setOutputPrintStream(System.out);
logger.setErrorPrintStream(System.err);
project.addBuildListener(logger);
File buildFile = new File("build.xml");
ProjectHelper.getProjectHelper().parse(project, buildFile);
project.executeTarget(project.getDefaultTarget());
For scripting languages that do not have dynamic libraries loading feature, we can use hook
into Scriplandia internals (to ClassWorlds guts):
import org.sf.jlaunchpad.Launcher;
import org.sf.scriptlandia.ScriptlandiaHelper;
Launcher launcher = ScriptlandiaHelper.getLauncher();
launcher.addClasspathEntry("3rdparty.library.jar");
Another useful technique to dynamically load libraries is to use "-lib" parameter from the
command line:
>Test.ant -lib lib
>Test.bsh -lib lib
These commands will pick up all libraries from "lib" folder and add them to "CLASSPATH" variable.
In the latest version pofg the project there is the way how to dynamically download, install and add
to classpath 3-rd party libraries (if they are present at remote repository). For example:
import org.sf.scriptlandia.ScriptlandiaHelper;
ScriptlandiaHelper.resolveDependencies("freemarker", "freemarker", "2.3.9");
In this example we reslove the dependency to fremarker library, version 2.3.9.
Maven scripts as regular scriptlets (mavenlets) and dependencies files
Maven project files can also be used as scripts. Instead of having predefined "pom.xml" file
for each maven project, we will create file with ".maven" extension. The primary goal for
these scripts is to express dependencies on other libraries.
In case when we need some additional libraries for running the script, we can express this
dependencies in the form of maven file. For example, this file describes dependency on jdom:
4.0.0testtest1.0Testjdomjdom1.0verify
We can use these dependencies inside Ant script (within "script" task). For example,
by running the following method we will add all classes in "compile" scope to main class realm:
import org.sf.scriptlandia.ScriptlandiaHelper;
ScriptlandiaHelper.resolveDependencies("deps.maven");
If you need to run Maven from within your script, use this method:
import org.sf.scriptlandia.MavenHelper;
MavenHelper.executeMaven("deps.maven", args);
Scriptlandia scripts
You can use maven project files as executables. To do so you have to rename
"pom.xml" file into something more meaningful with ".sl" extension. This extension is registered
in such a way, that it will try to run this file. The class to be executed is
"embedded" inside "groupId" and "artifactId" tags. The "groupId" tag contains package part of
the fully qualified class name and the "artifactId" tag - short class name. For example,
in order to run JLGUI mp3 player (http://www.javazoom.net/jlgui/jlgui.html),
you have to create this file:
4.0.0javazoom.jlgui.player.ampStandalonePlayer1.0pomjavazoom.jlguijlgui3.0
...
In repositories section you have to specify the repository location (if dependent
libraries are not located in default repository).
Classworld scripts
The same application can be started in slightly different way by using classworld file.
The ".cwd" extension is registered to launch such files. For example, in order to
run JLGUI mp3 player you can use this file:
# jlgui.cwd
main is javazoom.jlgui.player.amp.StandalonePlayer from jlgui.core
set jlgui.version default 3.0
[jlgui.core]
load ${repository.home}/javazoom/jlgui/jlgui/${jlgui.version}/jlgui-${jlgui.version}.jar
Usually classworld file does not provide loading dependent files on-the fly. But there is
small trick that can do it. If you try to load libraries from ${repository.home}, the program will try
to calculate "artifactId", "groupId" and "version" and then download it (including transitive
dependencies).
Working with mobile applications
If you have Java Micro Edition, installed on your computer, you will be able to run jar files
for mobile applications in the same way as for Java Standard Edition. By executing jar file,
the system will recognize such application and run it inside the phone emulator. The trick is that
manifest file has specific attributes, unique to phone applications only.
This is very convenient way to test mobile application before moving it to your cell phone.
If there is no Java ME installed, default JME implementation will be used (see http://microemu.org
for details).
Starting scripts as batch files
In Unix:
#!/bin/sh
exec scala "$0" "$@"
!#
Console.println("Hello, world!")
argv.toList foreach Console.println
In Windows:
::#!
@echo off
call scala -savecompiled %0 %*
goto :eof
::!#
Console.println("Hello, world!")
argv.toList foreach Console.println