The BugRunner ApplicationThe BugRunner code is unchanged from Chapter 11, aside from the addition of one new method in the BugRunner class, which is explained in the next section. Preparing the JARsI'm assuming that the target machine for the installation doesn't have Java 3D installed, so the test machine where I develop the installation shouldn't have it either. Instead, j3dutils.jar and J3DUtils.dll are placed in the BugRunner/ directory (as shown in Figure A-4). Figure A-4. The BugRunner/ directorySince Java 3D isn't installed in a standard location checked by javac and java, the calls to the compiler and JVM must include additional classpath information. The compileBR.bat batch file in BugRunner/ contains this line:
The BugRunner.bat batch file contains a similar line:
There's no need to mention J3DUtils.dll, which will be found by the JAR as long as it's in the same directory. Once the program has been tested, the classes and all other application resources must be packaged up as JARs prior to being passed to install4j. The BugRunner application consists of various classes and the two subdirectories, Images/ and Sounds/. These should be thrown together into a single BugRunner.jar file, along with any DLLs. The makeJar.bat batch file contains the following line:
The manifest details in mainClass.txt are as follows:
The manifest specifies the class location of the application's main( ) method and adds j3dutils.jar to the classpath used when BugRunner.jar is executed. For this example, the application assumes this JAR in the same directory as BugRunner.jar.
The DLL is stored in the JAR because the installation is easier if install4j only has to deal with JARs. However, after the installation EXE file has been downloaded to the user's machine, the DLL must be removed from BugRunner.jar and written to the new BugRunner/ directory. This copying from the JAR to the local directory is carried out by the BugRunner class, which is the new method I mentioned earlier. main( ) in BugRunner calls an installDLL( ) method:
installDLL( ) will be called every time that BugRunner is executed, so installDLL( ) first checks whether the DLL is present in the local directory. If not, it's installed by being written out to a file. The stream from the DLL file inside the JAR is created with:
This works since the DLL is in the same JAR as BugRunner, so the class loader for BugRunner can find it. Figure A-5 illustrates the technique. Figure A-5. Installing a DLL locallyThe result is that the BugRunner application installed on the user's machine will consist of two JARs, BugRunner.jar and j3dutils.jar. After the first execution of BugRunner, these two JARs will be joined by J3DUtils.dll. TestingThe best testing approach is to move the two JARs to a different machine, specifically one that doesn't have Java 3D installed (but J2SE or JRE must be present). Double-click on BugRunner.jar, and the game should begin. The J3DUtils.dll will magically appear in the same directory. Alternatively, the application can be tested with this command:
Executing this in a command window will allow standard output and error messages to be seen on the screen, which can be useful for testing and debugging. You could stop at this point since the game is nicely wrapped up inside two JARs. However, an installer will allow a professional veneer to be added, including installation screens, splash windows, desktop and menu icons, and an uninstaller. These are essential elements for most users. Creating the BugRunner InstallerThis is not a book about install4j, so I'll only consider the more important points in creating the BugRunner installer. install4j has an extensive help facility and links to a tutorial at its web site at http://www.ej-technologies.com/products/install4j/tutorials.html. Another good way of understanding things is to browse through the various screens of the BugRunner installation script, bugRun.install4j. The screenshots are taken from install4j v.2.0.7; the latest release has modified some of the configuration screens and added lots of new features. A crucial step is to define the distribution tree, the placement of files and directories in the BugRunner/ directory created on the user's machine at install time. My approach is to include an Executables/ subdirectory to hold the two JAR files. This directory structure is shown in Figure A-6. A quick examination of Figure A-6 will reveal three JARs inside Executables/: BugRunner.jar, j3dutils.jar, and custom.jar. custom.jar contains Java code deployed by the uninstaller, which is explained below. BugRunner.jar is not called directly but via an EXE file, which is set up on the Configure executable screen during the Launchers stage (shown in Figure A-7). The executable's name is BugRunner.exe and will be placed in the Executables/ directory along with the JARs. It's important to set the working directory to be ".", so the JAR will search for resources in the correct place.
Figure A-6. Distribution tree for the BugRunner installerFigure A-7. Configuring the BugRunner executableThe EXE file must be told which JAR file holds the main( ) method for the application and which JARs are involved in the application's execution. This is done through the Configure Java Invocation screen shown in Figure A-8. Figure A-8. Configuring the Java invocationFigure A-8 shows that custom.jar (holding the uninstaller code) isn't part of the application since it isn't included in the Class path list. The GUI Installer stage (shown in Figure A-9) allows the customization of various stages of the installation: the welcome screen, tasks to be done before installation, tasks after installation, and the finishing phase. The screen on the right of Figure A-9 is for the installer actions, which contains uninstallation actions. Perhaps the best advantage of using install4j is its close links to Java, most evident in the way the installation (and uninstallation) process can be customized. install4j offers a Java API for implementing many tasks, and the install4j distribution comes with an example installer that uses the API's capabilities. For example, the default action carried out prior to uninstallation is to call the DLLUninstallAction class in custom.jar, so application-specific tasks can be defined by overriding that class. I use this technique in the next section. UninstallationThe default install4j uninstaller will delete the JARs that it added to the Executables/ directory along with all the other files and directories it created at installation time. However, the installer didn't add J3DUtils.dll to Executables/; that task was carried out by the BugRunner class when it first ran. Figure A-9. The installer/uninstaller actions for the GUI installerinstall4j knows nothing about J3DUtils.dll, so it won't delete it or the subdirectory that holds it. The outcome is that a basic BugRunner uninstaller won't remove the BugRunner/Executables/ directory or the J3DUtils.dll file inside it. To get around this, you need to define a pre-uninstall operation that removes the DLL, so the main uninstaller can delete everything else. custom.jar contains the DLLUninstallAction class, which extends install4j's UninstallAction class. UninstallAction offers two abstract methods for custom behavior:
The uninstallation task (in this case, deleting the DLL) should be placed inside performAction( ). User messages can be sent to the uninstallation screen via the ProgressInterface object. performAction( ) should return true if the task is successful or false to abort the uninstallation process. getPercentOfTotalInstallation( ) gets the amount of the progress slider assigned to the task, returning a number between 0 and 100. My implementation of performAction( ) obtains a list of the DLLs in the Executables/ directory and then deletes each one. This approach is more flexible than hardwiring the deletion of J3DUtils.dll into the code and means that the same DLLUninstallAction class can be employed with the Checkers3D installer discussed later:
The tricky aspect of the code is the use of the PATH variable. The uninstaller is executed in the .install4j/ directory, which is at the same level as Executables/. Both of these are located in the BugRunner/ directory installed on the user's machine (see Figure A-10). Figure A-10. The installed BugRunner directoriesThe PATH string redirects the File object to refer to Executables/. A list of filenames ending in ".dll" is collected by using a FileFilter anonymous class, and the list is passed to deleteDLLs( )
deleteDLLs( ) loops through the filenames, calling deleteFile( ) for each. The ProgressInterface object informs the user of the progress of these deletions.
The DLLUninstallAction class must be compiled with the install4j API classes added to the classpath:
The creation of the JAR file is standard:
The BugRunner InstallerThe resulting installer, called BR_1.0.exe, takes a few seconds to generate and is about 1.4 MB.
A version bundled with JRE 1.4.2 comes in at 12 MB. |
Wednesday, December 30, 2009
The BugRunner Application
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment