In this article you will be covered:
- Using Clibuilder for support of command-line options, the parameters required for script execution are passed through command-line options.
- Use Groovyclassloader to load Groovy class.
- Use Antbuilder to build the Jar package.
Before you begin about this article
Maybe you've written some interesting or useful Groovy scripts and want to share them with your friends, but you don't want to force them to install groovy, so you might want to make a gadget that your friends can use to compile your groovy script and generate an executable Jar package. This article will show you how to make a gadget that allows your groovy script to be instantly compiled and packaged as an executable Jar in an environment where groovy is not installed, and to introduce some interesting features of groovy in this process.
In this article, we will design and implement a command-line tool that completes the immediate compilation and packaging of Groovy scripts. We will use Clibuilder to implement the command-line processing of the program, use Antbuilder to handle packaging problems, and use the Filesystemcompiler class to compile the Groovy script file.
Goal
Use this sample to learn about how Clibuilder is used in groovy and how antbuilder is applied in groovy.
Prerequisite
- Eclipse IDE
- Groovy Plugin for Eclipse
- Apache Ant Java Library (you can find http://ant.apache.org/bindownload.cgi here)
System Requirements
Because both the Eclipse IDE and the Groovy language are cross-platform, you can write the program in this sample on any platform and run it on any platform.
Back to top of page
Designing a command-line program with Clibuilder
Scripting with Groovy is a good way to develop cross-platform tools. As your script grows in complexity, you may need to handle command-line options in your script. It can be cumbersome to process these options or parameters and display the appropriate help information depending on the situation. Groovy bundled the Apache Commons CLI Library as part of it, but it also provides a much simpler clibuilder to use. So, let's take a look at how to use it.
Set command-line options for a program listing 1. Creating Clibuilder instances and defining command-line Options
Create Clibuilder instances and define command-line options def cmdline = new Clibuilder (usage: ' Groovypackman-[chflms] [date] [prefix] ') cmdline.h ( Longopt: ' Help ', Required:false, ' Show usage information ') CMDLINE.D (longopt: ' DestFile ', argname: ' DestFile ', req Uired:false, args:1, ' jar destintation filename ') cmdline.m (longopt: ' MainClass ', argname: ' MainClass ', Requi Red:true, Args:1, ' fully qualified main class ') cmdline.c (longopt: ' Groovyc ', Required:false, ' Run groovyc ') cmdline.s (longopt: ' SourcePath ', argname: ' SourcePath ', required:true, args:1, ' fully path to the MainClass. M UST is specified with. Groovy file path when-c option used. ')
In the above code snippet, we first create an instance of Clibuilder. Clibuilder has a property called usage, which can be used to display information such as instructions for using the program. Here, it is passed as a parameter to the constructor that will tell the program's consumer what options are available. Next, we define the command-line options using a single-letter method, and the Longopt property allows options to be specified as-H or--help. The Argname property is used to specify the parameter name of the option that is displayed in the usage description. The Args property is used to specify the number of arguments required for the option. The Required property is used to tell the command-line parser whether the current option is required. The last parameter in the function specifies the descriptive information for the option.
The Groovy language closure (closure) is a very important concept, more like a "code block" or a method pointer, where the code is defined somewhere and then executed at the subsequent call. About closures This article does not introduce more, please refer to the following articles for more detailed information:
Combat Groovy: Metaprogramming using closures, Expandometaclass, and categories
Description of the WITH (Object Self, Closure Closure) method in Groovydoc
Groovy gives us the with method, which allows the closure to be called by the object's reference itself, by assigning the object to the delegate property of the closure and passing it as a parameter to the closure. Using the With method can sometimes help us reduce the amount of code, and here we look at how different parameters are defined using the WITH () method as in the method used by code Listing 1.
Listing 2. Code after using the With method
def cmdline = new Clibuilder (usage: ' Groovypackman-[chflms] [date] [prefix] ') //Use the With method on object to omit the CmdLine object's qualification Cmdline.with { h longopt: ' Help ', Required:false, ' Show usage information '; D longopt: ' DestFile ', argname: ' DestFile ', Optionalarg:true, args:1, ' jar destintation filename '; M longopt: ' MainClass ', argname: ' MainClass ', Required:true, args:1, ' Fully name of main class '; C longopt: ' Groovyc ', Required:false, ' Run groovyc '; s longopt: ' SourcePath ', argname: ' SourcePath ', Required:true, args:1, ' fully path to the MainClass. Must is specified with. Groovy file path when-c option used. '; }
In this way, we set the command line entry for the program. which
- Use "-H" or "--help" to display the use Help information.
- Use "-D" or "--destfile" to target file names for the generated. jar file name, which is an optional option.
- Use "-M" or "--mainclass" to specify the full name of the main class, which will be used as the file name of the target Jar package when the "-d" option is not specified.
- It is an option to control whether the compilation process is performed by using the "-C" option.
- When "-C" is specified on the command line, "-S" or "--sourcepath" need to point to the directory where the script (package) is to be compiled, and the directory where the. class file is located when "-C" is not specified.
In the last chapter of this article, you will see an example of compiling a packaged script with this command-line tool (named: Groovypackman) in this article.
Parse the command line to enter listing 3. Parsing command-line options using the Parse method
def opt = cmdline.parse (args) if (!opt) {return} if (opt.h) { cmdline.usage () return }
The parse () method is used to parse the command line input parameters when the program executes. After parsing the command-line arguments by Parser, we can get an instance of the Optionaccessor object, which is empty when the input argument is not valid.
Further processing of command-line arguments
With the OPT object we can easily get to all the options that have been specified on the command line, and we will process the values of each option to match our requirements.
Listing 4. Get command-line options and assign values to variables
Assign a command-line option to the variable def mainClass = opt.m def sourcepath = Opt.s def destfile = MainClass + '. Jar ' if (! ( Sourcepath.endswith ("\ \")) | |! (Sourcepath.endswith ("/"))) ( SourcePath = SourcePath + "/") if (OPT.D) { destfile = opt.d }
Back to top of page
Using Antbuilder for ANT script programming
After processing the command-line options for the program, we will go into the other focus of this example: using Antbuilder to implement the compilation and packaging of scripts. First, let's get to know the generator.
Generator (builder)
The builder is a feature in groovy that makes it easy to construct a tree-like data structure in groovy, such as an XML document. And Antbuilder is a member of a number of generators that you can effortlessly construct an ANT XML-based architecture file (build.xml), without the need to process XML to perform the build. What's even more exciting is that you can write loops, conditional statements, and even take advantage of object-oriented languages, in contrast to the laborious use of copy-and-paste to create build.xml files.
The following code snippet shows a very simple example of using Antbuilder. In this example, when the user specifies the-C option on the command line, a Groovy script file that specifies that it needs to be compiled is output in the command-line window.
Listing 5. Creating Antbuilder instances and working with compiled objects
def ant = new Antbuilder () if (opt.c) { //Check if the script file exists def scriptbase = Mainclass.replace ('. ', '/') def Scrip Tfile = new File (sourcepath + scriptbase + '. Groovy ') if (!scriptfile.canread ()) { println "cannot read script fil E: ' ${scriptfile} ' " return } Ant.echo (" Compiling ${scriptfile} ") }
Call Filesystemcompiler to instantly compile Groovy scripts
In this example, after the user specifies a valid Groovy script file with the-C option on the command line, the program compiles it. We will use the Filesystemcompiler class to compile the script file, and code snippet 6 shows the process.
Listing 6. Implementing the compilation process with an instance of Groovyclassloader
try{ filesystemcompiler fc= new Filesystemcompiler () fc.commandlinecompile ([ScriptFile] as string[]) } catch (Org.codehaus.groovy.control.MultipleCompilationErrorsException e) { println e.getmessage () println "* * * Possible solution:please copy Groovypackman.jar to dir \" ${sourcepath}\ "and try again. * * * " return }
An instance of the Filesystemcompiler class is equivalent to a Groovy command-line compiler (GROOVYC). In groovy, you can call the groovy compiler directly to compile a script file whose commands are generally groovyc *.groovy. This process will generate one or more *.class files that can be executed using Java commands (but when executing groovy-generated. class files, ensure that the ClassPath is pointing to Groovy's library files, such as: Goovy-1.x.x.jar, etc.) 。
You can also use the command groovy *.groovy to complete compiling and running groovy scripts in a system with groovy installed. Unlike the GROOVYC command, the Groovy command generates the *.class file in memory instead of the file system and executes immediately.
Using Ant tasks in Groovy for flow control
After you have implemented the functionality of compiling the groovy script file, you will next take advantage of the ANT task in groovy to package the work.
Listing 7. Construct an XML-like structure with the builder's syntax
def groovy_support = (system.getenv (' Groovy_support '))? (New File (system.getenv (' Groovy_support '))): ""//If GROOVY is installed on the system, we will get the Jar package if (groovy_support!= "") necessary for the program to run from the system if it is packaged { if (Groovy_support.canread ()) {//Build executable Jar package and specify MainClass ant.echo ("Processing *.class files in ${sourcepath} ...") Ant.jar (Destfile:destfile, compress:true) {Fileset (Dir:sourcepath, includes: ' **/*.class ') Zipgroupfileset ( Dir:groovy_support, includes: ' Groovy-all-*.jar ') Zipgroupfileset (Dir:groovy_support, includes: ' Commons*.jar ') Zipgroupfileset (Dir:groovy_support, includes: ' Ant*.jar ')//You can add more jar packages here, depending on your needs manifest {attribute ( Name: ' Main-class ', Value:mainclass) attribute (name: ' Class-path ', Value: '. ') }}}}//If the system does not detect a Groovy environment, it will be packaged with the jar package that is necessary to get the program to run in Groovypackman.jar-else {ant.echo ("Missing Environment Varia ble groovy_support: ' ${groovy_support} ' ") def Packman = Urldecoder.decode (GroovyPackman.class.getProtectionDomain ().Getcodesource (). GetLocation (). GetFile (), "UTF-8") Packman = Packman.tostring (). Replacefirst ("/", "") Ant.echo ("Using Packman: ' ${packman} ' ") Ant.jar (Destfile:destfile, compress:true) {Fileset (Dir:sourcepath, includes: ' **/*.class ') Zipfileset (excludes: ' groovypackman*.*,org/apache/tools/**,images/** ', Src:packman)//You can add more Jar ma depending on your needs Nifest {attribute (name: ' Main-class ', Value:mainclass) attribute (name: ' Class-path ', Value: '. ') } } }
In Listing 7, you first check whether the environment variable Groovy_support exists, which is typically set after groovy Eclipse Plugin is installed, pointing to the directory containing the groovy runtime file. Then the different packing process is done for the existence or not of groovy_support. When Groovy_support is available we will pick up the relevant runtime from the directory pointed to by Groovy_support (e.g., Groovy-all-*.jar,commons*.jar,ant*.jar, etc.), and when Groovy_support Unavailable when Groovy is not installed on the system, the program will pick up the appropriate runtime from itself and package it with the compiled script.
Finally, compile our program
In the first step, we need to compile this script file in Eclipse to generate *.class. To compile groovy scripts in Eclipse, you can click the menu run, run as, groovy script.
Figure 1. The. class file generated by Eclipse after compilation
For ease of sharing and easier execution, the second step is to execute the generated. class file with Java commands and package itself as an executable Jar package.
Listing 8. Run Groovypackman.class to package itself
C:\groovy\groovypackman\bin>set groovy_support= D:\eclipse\plugins\org.codehaus.groovy_ 1.7.5.20101020-2100-e35-release\lib C:\GROOVY\GROOVYPACKMAN\BIN>JAVA-CP. \;%groovy_support%\;%groovy_ support%\ Groovy-all-1.7.5.jar;%groovy_support%\commons-cli-1.2.jar;%groovy_support%\ant.jar;%groovy_ Support%\ant-launcher.jar groovypackman-m groovypackman-s c:\Groovy\GroovyPackman\bin
Figure 2. Execute Groovypackman.class to package itself
Back to top of page
Look at the effect of this applet how to instantly compile and package a set of sample Groovy scripts
In this example, we use a very simple HelloWorld program to do a demo and see how to compile and package with the gadget we just made. This HelloWorld program contains two *.groovy script files, which itself is a three-tier directory structure package, as shown in 3:
Figure 3. Two groovy scripts included in the demo program
Here, we execute the following command at the command line:
Listing 9. Test Groovypackman.jar
Java-jar Groovypackman.jar
Test whether the previously packaged gadget works properly. 4 is shown below:
Figure 4. Groovypackman.jar executed at the command line
As the output from the command line, Groovypackman.jar is functioning normally. Next, start compiling and packaging the Hellowworld sample program.
Copy the Groovypackman.jar to the root directory where the Com.test.helloworld package resides. Execute the following command at the command line:
Listing 10. Run Groovypackman.jar Package HelloWorld program
Java-jar groovypackman.jar-m com.test,helloworld.helloworld-s c:\groovy-c
The HelloWorld will be automatically compiled and packaged, as shown in 5:
Figure 5. Helloworld program is packaged
As you can see from Figure 6, the *.groovy script file has been compiled into multiple *.class files.
Figure 6. The. class file that is generated during the packaging process
From Figure 7, you can see the HelloWorld program that has been packaged.
Figure 7. The HelloWorld program after packing
Next we run the HelloWorld program that we just generated in the command line, as shown in result 8:
Figure 8. Helloworld running results after packaging
Reference Learning
- For more tips on using Ant in Groovy, refer to building software with Gant (DeveloperWorks).
- You can also visit the mastery of Groovy (developerWorks) to learn more and more wonderful groovy knowledge.
- "Evolutionary architecture and emergent design: Building a DSL using Groovy" (developerworks,2010 September): Internal Domain-specific language (DSL) is possible, but the Java language's restrictive syntax makes its use inflexible. Other languages in the JVM are more suitable for building them. This period of evolutionary architecture and emergent design covers many of the features you can take advantage of, as well as the problems you will encounter when building your internal DSL using Groovy.
- "Functional Thinking: Functional features in Groovy, part 1th" (developerworks,2011 December): Over time, the language and the runtime have handled more and more trivial details for us. The functional language embodies its trend in this respect, and modern dynamic languages employ many functional features that make it easier for developers to work. This article will cover some of the functional features in Groovy and will show how to use recursion to hide states and build lazy lists.
- "Functional Thinking: Functional features in Groovy, part 2nd" (developerworks,2012 February): With Groovy, meta-programming (metaprogramming) and functional programming form a powerful combination. Learn how metaprogramming enables you to add methods to an Integer data type, allowing you to take advantage of Groovy's built-in functional features. Learn how to use meta-programming to seamlessly integrate the rich functional set of features of the functional Java framework into Groovy.
- "Functional Thinking: Functional features in Groovy, part 3rd" (developerworks,2012 March): Modern dynamic languages incorporate many functional features to help developers accomplish their usual tasks. This article uses Groovy to explore the benefits of applying caching at the function level and to compare this caching method with a command-based approach. This article demonstrates two types of caches, in-method caches and external caches, and also explores the pros and cons of imperative and functional versions.
- DeveloperWorks Java Technology Zone: Here are hundreds of articles on various aspects of Java programming.
Discuss
- Join DeveloperWorks Chinese community. View developer-driven blogs, forums, groups, and wikis, and communicate with other DeveloperWorks users.
Http://www.ibm.com/developerworks/cn/java/j-lo-groovypackage/index.html
Http://www.ibm.com/developerworks/cn/java/j-pg06239.html
Instantly compile and package your Groovy scripts (go)