[OpenVMS, Ant] A Quick HOWTO Guide
PRODUCT: ANT Field Test Version 1.7 Java Version 1.5.0-4 and Above
OP/SYS: OpenVMS Alpha/IA64 Version 8.3 and above
SOURCE: Philippe Vouters Fontainebleau/France
LOW-COST HIGH-TECH: http://techno-star.fr
OVERVIEW: This article highlights a quick HOWTO Guide to get started with existing Ant applications on both OpenVMS Alpha and Itanium servers. It also provides an ANT small tested example for those willing to start with this software technology.
PREREQUISITE: Download OpenVMS ANT T1.7 software from: http://h71000.www7.hp.com/openvms/products/ips/ant/index.html?jumpid=reg_R1002_USEN Make sure you read and follow the Product Installation Guide at: http://h71000.www7.hp.com/openvms/products/ips/ant/ant_rel_notes.txt Provided you incur the following Java error: java.io.IOException: Child creation error: file name too long either get the latest OpenVMS ANT ECO or download: ../zip/ANT.JAR and copy it to destination:[VMS$COMMON.ANT_17.LIB] Also you may face an error with an ANT construct such as: <condition property="grep" value="/gnu/bin/grep"> <os name="OpenVMS"/> </condition> <condition property="grep" value="/usr/sfw/bin/ggrep"> <os name="SunOS"/> </condition> <condition property="grep" value="ggrep"> <os name="OpenBSD"/> </condition> <property name="grep" value="grep"/> <apply dir="${build.native}" executable="${grep}" parallel="true" failonerror="true" relative="true" output="${md5.file}"> <arg value="-A"/> <arg value="1"/> <arg value="JNIEXPORT"/> <fileset dir="${build.native}" includes="*.h"/> </apply> If you need a correction to the apply ANT macro and do need latest ANT version 1.7.1 jars, download them from ../zip/ant-1.7.1-jars.tar.gz. These jars are compatible with JSEE V6.0 for OpenVMS Itanium servers and correspond to: $ ant "-version" Apache Ant version 1.7.1 compiled on October 18 2010 In addition, this 1.7.1 Ant version compiled on October 18 2010 enables on OpenVMS Itanium servers using JSEE V6.0 to successfully execute the following macros : <signjar alias="jna" keystore="jna.keystore" storepass="jnadev" lazy="true"> <fileset dir="${build}/jws" includes="jna.jar,jna-test.jar,junit.jar,jnidispatch.jar,clover.jar"/> </signjar> <exec executable="dcl.exe" dir="${native}" failonerror="true" vmlauncher="true"> <arg value="${vms.make}"/> <arg value='/macro=(LIBFFI_HOME="${libffi.home}",JAVAHEADER="${build.native}",LIBFFI=${vms.libffi.share})'/> </exec> with ${vms.make} being MMS (a DCL verb) or MMK (a global symbol). A precision must be brought to the reader to facilitate his understanding. The success of this <exec> ANT macro depends upon the installation of the OpenVMS GNV product, the dcl.exe code actually running being GNU:[BIN]DCL.EXE and not SYS$SYSTEM:DCL.EXE. This GNU:[BIN]DCL.EXE is a DCL wrapper based upon lib$spawn. For detailled informations, refer to: ../tima/OpenVMS-Java-Executing_DCL_commands.html The only change with the original Apache/Ant V1.7.1 source code and which still applies with Apache/Ant V1.8.1 occurs in Java method isFailure in ant-1.7.1-src/src/main/org/apache/tools/ant/taskdefs/Execute.java. The change now codes the following: public static boolean isFailure(int exitValue) { //on openvms even exit value signals failure; // for other platforms nonzero exit value signals failure return Os.isFamily("openvms") ? (exitValue % 2 == 0) && (exitValue != 0) : (exitValue != 0); } whereas the original source file coded this way: public static boolean isFailure(int exitValue) { //on openvms even exit value signals failure; // for other platforms nonzero exit value signals failure return Os.isFamily("openvms") ? (exitValue % 2 == 0) : (exitValue != 0); } Using Java V1.6.0 for OpenVMS, the original source code revealed not matching the many external OpenVMS programs exit codes that Ant can activate. Provided you did not $ PRODUCT INSTALL ANT/DESTINATION=device, you may replace destination:[VMS$COMMON.ANT_17.LIB] with SYS$COMMON:[ANT_17.LIB] Check with: $ java -fullversion this returns Java Version 1.5.0-4 or Above.
OPENVMS ANT HOWTO USER GUIDE: destination:[VMS$COMMON.ANT_17.BIN]ANT.COM internally defines the following logicals and restores them to their previous value at exit time: DECC$EFS_CHARSET to ENABLED DECC$READDIR_DROPDOTNOTYPE to TRUE DECC$EFS_CASE_PRESERVE to TRUE JAVA$DELETE_ALL_VERSIONS to TRUE JAVA$FILE_OPEN_MODE to 3 DECC$FILE_SHARING to ENABLED JAVA$CREATE_DIR_WITH_OWNER_DELETE to TRUE JAVA$READDIR_CASE_DISABLE to TRUE JAVA$FORK_SUPPORT_CHDIR to TRUE JAVA$CREATE_STMLF_FORMAT to TRUE JAVA$FILENAME_CONTROLS to 8 DECC$ARGV_PARSE_STYLE to TRUE DECC$RENAME_NO_INHERIT to TRUE DECC$MAILBOX_CTX_STM to TRUE These logicals are so set to pass most of the Apache/Ant test suite. In order to control which actual arguments are passed from HP OpenVMS ANT to your Java application via a Java exec because you have in your XML fork="true", define the JAVA logical JAVA$PRINT_COMMAND_ARGS to TRUE. This setting will bring to your attention all the Java program arguments that are passed to your program. Along with "-verbose" or "-debug" ANT command qualifier, this ought to help you to determine the actual cause of an error such as java.lang.NoClassDefFoundError. Providing your XML file contains lowercase file names and your application files reside on an ODS-5 disk but the file names are upper or mixed-cased , define DECC$EFS_CASE_SPECIAL to TRUE.
INTRODUCTION TO WRITING ANT XML INPUT FILES: Ant has been designed as a "Makefile" enabling to automatically build Java complex applications but its use is not limited to the traditional build in the meaning it may execute Java applications with complex and conditional Java command arguments. This is quite often its real use. As an introduction to Ant, consider the following Java source file: ************ * Locking.java ************ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.AsynchronousCloseException; public class Locking extends Thread { private final int position = 0; private int number; private int pause; private boolean flag; private String filename; public static void main(String args[]) { Boolean flag = Boolean.valueOf(args[args.length-1]); String path=args[args.length-2]; if (System.getProperty("os.name").compareTo("OpenVMS") == 0){ System.out.println("DECC$WLS = " +System.getenv("decc$wls")); System.out.println("JAVA$DISABLE_JAVA_FCNTL_LOCKS = "+ System.getenv("java$disable_java_fcntl_locks")); } if ( flag == Boolean.TRUE) System.out.println("*** Use of tryLock() ***"); else System.out.println("*** Use of lock() ***"); for (int i = 0; i < 3; i++) { Locking thread = new Locking(i, i + 1, flag.booleanValue(), path ); thread.start(); } } public Locking(int number, int s, boolean flag, String path) { this.number = number; this.pause = s * 1000; this.flag = flag; this.filename = path + "/uselocks.txt"; } public void run() { try{ this.execute(); } catch (IOException e){ e.printStackTrace(); } } public void execute() throws IOException { FileLock lock = null; RandomAccessFile raf=null; boolean LockObtained = false; try { raf = new RandomAccessFile(filename, "rw"); FileChannel fc = raf.getChannel(); System.out.println("Opening channel " + number); if ( flag ) lock = fc.tryLock(position,fc.size() , true); else { while ( ! LockObtained ){ try{ lock = fc.lock(position, fc.size(), true); LockObtained = true; } catch (IOException e){ LockObtained = false; } } } System.out.println("Lock number " + number + " acquired. lock=" + lock); System.out.println("\tPausing " + (pause / 1000) + "s on lock number" + number ); Thread.sleep(pause); System.out.println("\tEnd of pause of lock number " + number ); if(lock != null) { System.out.println("\tFreeing lock number " + number); lock.release(); } System.out.println("Closing channel " + number); if (raf != null) raf.close(); } catch (InterruptedException ie) { if(lock != null) { System.out.println("\tFreeing lock number " + number); lock.release(); } System.out.println("Closing channel " + number); if (raf != null) raf.close(); } } } To compile using javac, create a Java archive using jar and execute it on both Linux and OpenVMS systems so that you get the exact same behavior on both platforms, you would write an ANT coded XML input file, such as: ************ * Locking.xml ************ <project name="Locking application Makefile and launcher"> <description> This script builds the Locking application using javac and jar and executes it with the appropriate OS environnement when applicable. For OpenVMS, the correct run-time environnement implies correctly setting the JAVA$ and DECC$ logicals, so that the use of this file provides identical results accross OS platforms. For simplicity we restrict the work to Linux and OpenVMS operating systems. </description> <property name="Locking" value="Locking" /> <!-- Tell java via ANT where it can find our .jar file --> <path id="Locking.classpath"> <fileset dir="./"> <include name="*.jar"/> </fileset> </path> <target name="compile"> <echo message="Compiling ${Locking}.java using javac" /> <javac srcdir="." destdir="." includes="${Locking}.java" /> </target> <target name="compress" depends="compile"> <echo message="Creating archive using jar tool" /> <jar destfile="${Locking}.jar" basedir="./" compress="yes" includes="*.class"> <fileset file="*.class" /> <manifest > <attribute name="Class-Path" value=". Locking.jar" /> <attribute name="Main-Class" value="Locking" /> </manifest> </jar> </target> <target name="Logicals" if="VMS"> <echo message="Setting DECC and JAVA logicals" /> <!-- WARNING: Unlike what is stated in ANT Manual at: http://ant.apache.org/manual/CoreTasks/exec.html one must NOT specify the at ('@') character sign in front of a DCL command file specification. According to ../tima/OpenVMS-Java-Activating_DCL_procedure-Testing_GETENV_logical.html and the tests performed, this seems especially true using Java 1.5.0-4 on VMS IA64 systems and not with Java 1.5.0-5 on VMS Alpha servers. Doubling the '$' character in the logical name is the way to escape it. --> <exec executable="SYS$$LOGIN:Locking.com" /> </target> <target name="OS"> <condition property="VMS"> <os family="OpenVMS" /> </condition> <echo message="Running on ${os.name}" /> </target> <target name="run" depends="compile, compress, OS, Logicals"> <echo message="Running the Locking demo" /> <java classname="Locking" fork="true" failonerror="true" taskname="${Locking}"> <classpath> <path refid="Locking.classpath" /> </classpath> <arg value="." /> <arg value="true" /> </java> </target> </project> ************ * Locking.com ************ $! On OpenVMS,we MUST define/job because the <exec ...> ANT tag spawns a $! process. $! $! On Windows XP, one can eventually write a program like the one at $! ../tima/Windows-2000-background-task-Event-logger-C++-example.html $! that sets up the Windows registry at HKEY_CURRENT_USER\Environment to set up $! environment variables for use inside the ANT childs targets. $! Refer to the RegxxxEx functions usage in this article. $! $! On Unix systems such as Linux, there is no way to export a symbol from $! a child process to a parent process. This is a pure Unix limitation $! $! As well, ANT has not been designed to setup internal environment variables $! for use by child processes. ANT via the XML tags: $! <property environment="env" /> $! <property name="${env.ENV_VAR}" value="value" /> $! can only setup the new value of an EXISTING environment variable. In no $! way, it has been designed to create new environment variables. $! $! $ if f$trnlnm("DECC$EFS_CASE_SPECIAL") .eqs. "" $ then $ define/job DECC$EFS_CASE_SPECIAL TRUE $ endif $ if f$trnlnm("DECC$WLS") .eqs. "" $ then $ define/job DECC$WLS TRUE $ endif $ if f$trnlnm("JAVA$DISABLE_JAVA_FCNTL_LOCKS") .eqs. "" $ then $ define/job JAVA$DISABLE_JAVA_FCNTL_LOCKS TRUE $ endif $! Using $! $ java -fullversion $! java full version "1.5.0-4" $! setting this logical below works as documented. $! See: http://h18012.www1.hp.com/java/documentation/1.5.0/ivms/docs/release_notes.html $ define/job/user JAVA$GETENV_JOB_LIST DECC$WLS,JAVA$DISABLE_JAVA_FCNTL_LOCKS $ exit $STATUS
EXPLANATION: Typing the command: $ ant -f Locking.xml run invokes the ANT XML targets "compile" (activates the javac compiler), "compress" (activates jar to create an archive), "OS" (to test the "OpenVMS" operating system condition), "Logicals" which statements block is conditionaly executed if the "VMS" condition tested in the "OS" block reveals true and finally the "run" target because this is part of the shell command. All above but the "run" target are specified in the depends=".." statement, hence their execution.
VERIFICATION: Linux output: [philippe@victor ~]$ export JAVA_HOME=/usr/local/jdk1.6.0_04 [philippe@victor ~]$ ant -f Locking.xml run Buildfile: Locking.xml compile: [echo] Compiling Locking.java using javac [javac] Compiling 1 source file to /home/philippe compress: [echo] Creating archive using jar tool [jar] Building jar: /home/philippe/Locking.jar OS: [echo] Running on Linux Logicals: run: [echo] Running the Locking demo [Locking] *** Use of tryLock() *** [Locking] Opening channel 0 [Locking] Lock number 0 acquired. lock=sun.nio.ch.FileLockImpl[0:0 shared valid] [Locking] Pausing 1s on lock number0 [Locking] Opening channel 1 [Locking] Lock number 1 acquired. lock=sun.nio.ch.FileLockImpl[0:0 shared valid] [Locking] Pausing 2s on lock number1 [Locking] Opening channel 2 [Locking] Lock number 2 acquired. lock=sun.nio.ch.FileLockImpl[0:0 shared valid] [Locking] Pausing 3s on lock number2 [Locking] End of pause of lock number 0 [Locking] Freeing lock number 0 [Locking] Closing channel 0 [Locking] End of pause of lock number 1 [Locking] Freeing lock number 1 [Locking] Closing channel 1 [Locking] End of pause of lock number 2 [Locking] Freeing lock number 2 [Locking] Closing channel 2 BUILD SUCCESSFUL Total time: 5 seconds [philippe@victor ~]$ OpenVMS V8.3-1H1 output: $ ant "-f" Locking.xml "run" Buildfile: LOCKING.XML compile: [echo] Compiling Locking.java using javac [javac] Compiling 1 source file to /SYS$SYSDEVICE/PHV compress: [echo] Creating archive using jar tool [jar] Building jar: /SYS$SYSDEVICE/PHV/Locking.jar OS: [echo] Running on OpenVMS Logicals: [echo] Setting DECC and JAVA logicals [exec] Result: 1 run: [echo] Running the Locking demo [Locking] DECC$WLS = true [Locking] JAVA$DISABLE_JAVA_FCNTL_LOCKS = true [Locking] *** Use of tryLock() *** [Locking] Opening channel 0 [Locking] Lock number 0 acquired. lock=sun.nio.ch.FileLockImpl[0:0 shared vali d] [Locking] Pausing 1s on lock number0 [Locking] Opening channel 1 [Locking] Lock number 1 acquired. lock=sun.nio.ch.FileLockImpl[0:0 shared vali d] [Locking] Pausing 2s on lock number1 [Locking] Opening channel 2 [Locking] Lock number 2 acquired. lock=sun.nio.ch.FileLockImpl[0:0 shared vali d] [Locking] Pausing 3s on lock number2 [Locking] End of pause of lock number 0 [Locking] Freeing lock number 0 [Locking] Closing channel 0 [Locking] End of pause of lock number 1 [Locking] Freeing lock number 1 [Locking] Closing channel 1 [Locking] End of pause of lock number 2 [Locking] Freeing lock number 2 [Locking] Closing channel 2 BUILD SUCCESSFUL Total time: 18 seconds $
RELATED ARTICLES IN THIS DATABASE: ../tima/All-OS-Java-Lock-tryLock-example.html ../tima/OpenVMS-Java-file-locking-ENQLM-quota.html ../tima/OpenVMS-Java-Activating_DCL_procedure-Testing_GETENV_logical.html ../tima/OpenVMS-IA64-Java-JNA-libffi-Porting_JNA_to_OpenVMS_Itanium_servers.html
REFERENCE(S): An excellent ANT FAQ is available at: http://bobcat.webappcabaret.net/javachina/faq/ant_01.htm For detailed information on possible DECC$ logicals, refer to the HP C Run-Time Library Reference Manual for OpenVMS Systems at: http://h71000.www7.hp.com/doc/732final/5763/5763pro_004.html For a complete list of DECC logicals DECC$SHR supports, refer to ../tima/OpenVMS-DECC-Getting_the_logicals_DECC_list.html For possible JAVA$ logicals along with their explanation, refer to: SYS$SYSDEVICE:[VMS$COMMON.JAVA$1%%.DOCS]USER_GUIDE.HTML If your VMS computer is not a Workstation with the OpenVMS SWB product installed, transfer this file to your PC using either sftp or ftp. Using the local Web Browser, open the link: file:///path/USER_GUIDE.HTML Still for JAVA$ possible logicals, another source of information is: SYS$HELP:JAVA$1xx.RELEASE_NOTES