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.0 test test 1.0 Test jdom jdom 1.0 verify 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.0 javazoom.jlgui.player.amp StandalonePlayer 1.0 pom javazoom.jlgui jlgui 3.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