18. Java

## 18. Java

### 18.1. Java Specific Actions

Java (tm) Autodetection. The `<autodetectJava>` action attempts to automatically locate an existing Java (tm) installation in the system. If found, it creates a set of installer variables that contain the location and version of the executable.

The action is usually placed in the `<preInstallationActionList>` and if no valid JRE is found, the installer will abort with an error listing the supported JREs.

The `<autodetectJava>` properties are:

- `<promptUser>`: Prompt user to choose appropriate version
- `<selectionOrder>`: Order of the Java versions detected
- `<validVersionList>`: List of supported Java versions

The allowed Java versions are defined using the `<validVersion>` element, which are included in the `<validVersionList>`. Each of these versions contain the following fields:

- `<vendor>`: Java VM vendor to allow. The allowed values are: `sun` (to allow only Sun Microsystems JREs), `ibm` (for IBM JREs), `kaffe` (for Kaffe.org JREs), `openjdk` (for OpenJDK releases) and empty (for any vendor).
- `<minVersion>`: Minimum supported version of the JRE. Leave empty to not require a minimum version
- `<maxVersion>`: Maximum supported version of the JRE. Leave empty to not require a maximum version. If specified only with major and minor version numbers then it will match any number in the series. For example, 1.4 will match any 1.4.x version (1.4.1, 1.4.2, …) but not a 1.5 series JRE.
- `<bitness>`: Bitness of Java application. Leave empty to not require a specific bitness of Java. If specified, only Java compiled for specified number of bits will be matched.
- `<requireJDK>`: Whether the Java version is a JDK.

The following example will select any Sun Microsystems JRE 1.3 32bit or newer (for example, 1.3, 1.4, 1.5) or any IBM JRE regardless of bitness with version number equal or greater than 1.4.2 but inside the 1.4 series (1.5 will not work).

       <autodetectJava>
          <validVersionList>
             <validVersion>
                <vendor>sun</vendor>
                <minVersion>1.4.2</minVersion>
                <maxVersion>1.4</maxVersion>
                <bitness></bitness>
             </validVersion>
             <validVersion>
                <vendor>ibm</vendor>
                <minVersion>1.3</minVersion>
                <maxVersion></maxVersion>
                <bitness>32</bitness>
             </validVersion>
          </validVersionList>
       </autodetectJava>

Upon successful autodetection, the following installer variables will be created:

- java_executable: Path to the java command line binary (java.exe in Windows). For example `/usr/bin/java`, `C:\Program Files\Java\j2re1.4.2_03\java.exe`.
- javaw_executable: Path to javaw.exe binary, if found. Otherwise defaults to the value of `java_executable`.
- java_version: For example, 1.4.2_03
- java_version_major: For example, 1.4
- java_vendor: sun or ibm.
- java_autodetected: Set to 1
- java_bitness: 32 or 64.

It the autodetection is not successful, the variable `${java_autodetected}` will be set to 0 and the action will throw an error, which can be masked by setting `abortOnError="0"` and `showMessageOnError="0"` int he action.

The installer will look for valid JREs in the following places and select the first one that meets all of the requirements:

- Standard installation paths.
- Windows Registry, default environment `PATH`.
- Using `JAVA_HOME`, `JAVAHOME` or `JDK_HOME` environment variables, if present.

The default behavior of the `<autodetectJava>` action is to automatically pick one of the detected versions. However, it is possible to display a choice dialog to allow the user select which one he would like to use by setting `<promptUser>` to `1`. You can specify the order in which the versions detected will be displayed using the `<selectionOrder>` tag. It allows `first`, to display the versions in the same order they were detected, `newest`, to list newer versions first and `oldest`, to display older versions first. The value defined in the `<selectionOrder>` will also determine which version will be returned by default when `<promptUser>` is set to 0.

For example, the below code will pick the newest Java version in the machine automatically and won’t report an error if none is available:

       <autodetectJava>
          <abortOnError>0</abortOnError>
          <showMessageOnError>0</showMessageOnError>
          <promptUser>0</promptUser>
          <selectionOrder>newest</selectionOrder>
          <validVersionList>
             <validVersion>
                <vendor></vendor>
                <minVersion></minVersion>
                <maxVersion></maxVersion>
             </validVersion>
          </validVersionList>
       </autodetectJava>

When you do not have any requirement for the Java version, instead of providing a `<validVersion>` with all of its fields set to empty, you can just omit the `<validVersionList>`. The above code is then equivalent to the following:

       <autodetectJava selectionOrder="newest" promptUser="0"/>

You can also combine the autodetection with a `<httpGet>` action and download the runtime if it is not available in the system:

     <!-- Set abortOnError="0" and showMessageOnError="0" so the action does not report any error
     if Java is not detected -->
     <autodetectJava selectionOrder="newest" promptUser="0" abortOnError="0" showMessageOnError="0"/>
     <actionGroup>
        <actionList>
          <actionGroup>
             <actionList>
                <showProgressDialog>
                  <title>Downloading files</title>
                  <actionList>
                    <httpGet>
                      <filename>${installdir}/java.tar.gz</filename>
                      <url>http://www.example.com/downloads/java/1.6/jre1.6.0_24-linux.tar.gz</url>
                    </httpGet>
                  </actionList>
                </showProgressDialog>
                <runProgram>
                  <program>tar</program>
                  <programArguments>xzf ${installdir}/java.tar.gz -C ${installdir}</programArguments>
                </runProgram>
             </actionList>
             <ruleList>
                <platformTest type="linux"/>
             </ruleList>
          </actionGroup>
          <actionGroup>
             <actionList>
                <showProgressDialog>
                  <title>Downloading files</title>
                  <actionList>
                    <httpGet>
                      <filename>${installdir}/java.exe</filename>
                      <url>http://www.example.com/downloads/java/1.6/jre1.6.0_24-windows.exe</url>
                    </httpGet>
                  </actionList>
                </showProgressDialog>
                <runProgram>
                  <program>${installdir}/java.exe</program>
                  <programArguments>/s INSTALLDIR="${installdir.dos}\JRE" REBOOT=Suppress</programArguments>
                </runProgram>
             </actionList>
             <ruleList>
                <platformTest type="windows"/>
             </ruleList>
          </actionGroup>
        </actionList>
        <ruleList>
           <isFalse value="${java_autodetected}"/>
        </ruleList>
     </actionGroup>

### 18.2. Bundling a JRE

VMware InstallBuilder can be used to package Java-based applications that provide their own Java Runtime Environment (JRE). You can download ready to use components containing a JRE and InstallBuilder component from the following location:

http://installbuilder.com/java/

These components provide the following features:

- Deployment of JDK or JRE (JRE not available in Java 11 and later)
- Creating a Java launcher binary that runs a specified JAR file
- For Microsoft Windows, automatically creating a Start Menu entry for the launcher

Java Runtime Environments are provided as a ZIP archive. Each archive contains JRE binaries as well as a Java component XML file that contains the packing and installation logic for the application.

| License and redistribution rights for OpenJDK bundles
VMware InstallBuilder provides Java bundles using binaries built from OpenJDK provided binaries. It is recommended to check license for OpenJDK and ensure that redistributing the Java binaries in your application complies with the license terms.

Each archive contains a directory structure similar to:

- `jdk11.0.1-windows-x64` - base directory; this name depends on JDK version and platform
- `jdk11.0.1-windows-x64/java.xml` - Java component definition that should be included in your project
- `jdk11.0.1-windows-x64/java-windows` - JRE binaries for Microsoft Windows

You will need to unpack the zip file and use an `<include>` tag to reference the Java component XML file.

| File `java.xml` should be in same directory as your project file
The `java.xml` and all files inside the base directory file should be copied to same path where your project is located. Otherwise the Java files may not be included in the installer properly or building the installer may fail.

By default, the names of the launcher and the start menu entry are the project `<shortName>` and `<fullName>`. You will need to provide a path to your application JAR using the `java_launcher_jar` variable.

The example below shows a project packaging a Java module for an application `Sampleapp.jar`.

    <project>
      <shortName>samplejavaapp</shortName>
      <fullName>Sample Java Application</fullName>
      <componentList>
        <!-- application's component(s) - i.e. "default" created by installbuilder GUI -->
        <component>
          <name>default</name>
          <description>Default Component</description>
          <canBeEdited>1</canBeEdited>
          <selected>1</selected>
          <show>1</show>
          ...
        </component>

        <!-- include Java component XML definition -->
        <include file="java.xml"/>
      </componentList>

      <!-- set up variables for Java component -->
      <initializationActionList>
        <setInstallerVariable>
          <name>java_launcher_jar</name>
          <value>Sampleapp.jar</value>
        </setInstallerVariable>
      </initializationActionList>
    </project>

All of the logic for deploying the JRE / JDK, creating the Java launchers and adding shortcuts in start menu is handled by the Java component definition in `java.xml`.

Each JRE / JDK bundle contains Java binaries for a single platform. It is possible to create a single project that ships binaries for multiple platforms by copying binaries for needed platforms into a single directory. Its structure needs to be as follows:

- `jdk11.0.1` - base directory
- `jdk11.0.1/java.xml` - Java component definition
- `jdk11.0.1-windows/java-windows` - JRE binaries for Microsoft Windows
- `jdk11.0.1-windows/java-linux-x64` - JDK binaries for Linux (64bit)
- `jdk11.0.1-windows/java-osx` - JDK binaries for macOS (64bit)

Java component deployment can be customized to fit an application’s needs. The following variables are used by `java.xml`:

- java_launcher_destination - defines the destination where Java launcher should be created; defaults to `${installdir}`
- java_launcher_binary_name - name of the launcher binary; defaults to `${project.shortName}-launcher.${platform_exec_suffix}`
- java_launcher_arguments - command line arguments to pass to the launcher; defaults to empty string
- java_launcher_vm_parameters - additional parameters to pass to the Java VM; defaults to empty string
- java_launcher_jar - JAR file to use; defaults to empty string
- java_launcher_mainClass - JAR file to use; defaults to empty string
- java_launcher_classpath - classpath to pass to Java, comma separated regardless of target platform; defaults to empty string
- java_launcher_startmenu_shortcut_name - name for the start menu shortcut on Microsoft Windows; defaults to `Launch ${project.fullName}`
- java_launcher_add_to_win_startmenu - whether the start menu item should be created on Microsoft Windows; defaults to 1
- java_install_jre - whether the JRE should be installed and used by default by the launcher binary; defaults to 1

The `java_launcher_jar`, `java_launcher_mainClass` and `java_launcher_classpath` variables specify how the launcher should run the application. If a `java_launcher_jar` is specified, the `java -jar` command is used to run the application. Otherwise `java` is run by specifying the class path and main class to run.

These variables map to the `<jarFile>`, `<classpath>` and `<mainClass>` attributes for `<createLaunchers>` action. This action is described in more detail in the next section.

### 18.3. Launchers

Java (tm) launchers are binaries that allow running Java-based applications as if they were native. They work by locating an installed JRE in the target machine or using one provided to launch a Java application with the right options.

Java Launchers are created using the `<createJavaLaunchers>` action. It allows creating multiple launchers in the specified destination, configurable through the `<destination>` tag. These launchers are added in its <javaLauncherList>. A launcher is specified using the `<javaLauncher>` tag.

The target file name for the launched application is specified in `<binaryName>`. The extension .exe is automatically appended on the Windows operating systems.

The details of how to run the Java application are provided using the tags `<classpath>`, `<mainClass>` and `<jarFile>` where `<jarFile>` takes precedence if it is specified. If a `<jarFile>` is provided, the JRE is called with the `-jar` option to execute it and `<classpath>` and `<mainClass>` are ignored. If `<jarFile>` is empty, the `<classpath>` is configured with the `-cp` flag and the `<mainClass>` is passed as name of the class to run. Regardless of the operating system, paths in `<classpath>` are semi-colon separated.

The `<arguments>` tag specifies the arguments to pass to the Java application. Additional arguments can be passed to the launcher (that will in turn pass them to the Java application) through the command line if the `<allowCommandLineArguments>` tag enables it. These additional arguments will be appended after the predefined `<arguments>`.

The example below shows how to create two launchers at the end of the installation:

    <postInstallationActionList>
      <createJavaLaunchers>
        <destination>${installdir}/javalaunchers</destination>
        <javaLauncherList>
          <!-- A launcher to call the com.installbuilder.testapplication.MainClass
          class, looking for it in the testapplication.jar;additional.jar files -->
          <javaLauncher>
            <arguments></arguments>
            <binaryName>launcher1</binaryName>
            <classpath>testapplication.jar;additional.jar</classpath>
            <mainClass>com.installbuilder.testapplication.MainClass</mainClass>
            <allowCommandLineArguments>1</allowCommandLineArguments>
            <preferredJavaBinary></preferredJavaBinary>
            <runInConsole>1</runInConsole>
            <workingDirectory>${installdir}/javalaunchers</workingDirectory>
          </javaLauncher>
          <!-- A launcher to call the testapplication.jar file -->
          <javaLauncher>
            <binaryName>launcher2</binaryName>
            <jarFile>testapplication.jar</jarFile>
            <mainClass></mainClass>
            <allowCommandLineArguments>1</allowCommandLineArguments>
            <preferredJavaBinary></preferredJavaBinary>
            <runInConsole>1</runInConsole>
            <vmParameters></vmParameters>
          </javaLauncher>
        </javaLauncherList>
      </createJavaLaunchers>
    </postInstallationActionList>

This will create two test launchers. The first one, `testlauncher1` (or `testlauncher1.exe` on Windows) will run Java using `-cp` flags and specifying a main class name. The binary `testlauncher2` will run Java using the `-jar` option and Java will read the main class from the JAR file’s MANIFEST.MF file.

The file names of the generated launchers are also automatically added to the uninstaller. They will be deleted when the uninstaller is run.

By default, Java launchers will use the default Java available on the system. It is also possible to set specific Java versions that it will accept. The `<validVersionList>` can be used to specify these accepted versions. It works as explained in the Java autodetection section.

The following example defines a launcher that will use any Sun Microsystems JRE 1.3 or newer (for example, 1.3, 1.4, 1.5) or any IBM JRE with version number equal or greater than 1.4.2 but inside the 1.4 series (for example, 1.5 will not be accepted as valid):

          <javaLauncher>
            <arguments></arguments>
            <binaryName>launcher2</binaryName>
            <classpath></classpath>
            <jarFile>testapplication.jar</jarFile>
            <validVersionList>
              <validVersion>
                <minVersion>1.4.2</minVersion>
                <maxVersion>1.4</maxVersion>
              </validVersion>
              <validVersion>
                <vendor>ibm</vendor>
                <minVersion>1.3</minVersion>
                <maxVersion></maxVersion>
              </validVersion>
            </validVersionList>
          </javaLauncher>

On Windows systems the launcher executable resource information can be configured:

      <createJavaLaunchers>
        <destination>${installdir}/javalaunchers</destination>
        <javaLauncherList>
          <javaLauncher>
            <binaryName>launcher1</binaryName>
            <classpath>testapplication.jar;additional.jar</classpath>
            <mainClass>com.installbuilder.testapplication.MainClass</mainClass>
            ...
            <windowsResourceFileVersion>1.0.0.0</windowsResourceFileVersion>
            <windowsResourceLegalCopyright>Test Launcher 1</windowsResourceLegalCopyright>
            <windowsResourceLegalTrademarks>(c) 1998-2020 VMware Inc.</windowsResourceLegalTrademarks>
            <windowsResourceOriginalFilename>launcher1.exe</windowsResourceOriginalFilename>
            <windowsResourceProductName>Test launcher 1</windowsResourceProductName>
            <windowsResourceProductVersion>1.0</windowsResourceProductVersion>
            <workingDirectory>${installdir}/javalaunchers</workingDirectory>
          </javaLauncher>
       </javaLauncherList>
      </createJavaLaunchers>

In addition, it is possible to specify an icon file to use. It must point to an existing file in the target machine at the time the `<createJavaLaunchers>` action is executed. If not specified, the default icon for the launchers will be the same as the icon for the installer.

Windows launchers can also request running with administrative privileges using the `<requestedExecutionLevel>` tag. This is necessary for Windows Vista and Windows 7 operating systems where UAC may prevent some operations if the Java process is not elevated. It accepts the following values:

- requireAdministrator - Require administrator
- asInvoker - As invoker
- highestAvailable - Highest available

The example below covers using the `launcher.ico` file as the binary icon, which is located in the installation directory, and requires being administrator on UAC-enabled systems:

          <javaLauncher>
            <arguments></arguments>
            <binaryName>launcher2</binaryName>
            <classpath></classpath>
            <jarFile>testapplication.jar</jarFile>
            <windowsExecutableIcon>${installdir}/launcher.ico</windowsExecutableIcon>
            <requestedExecutionLevel>requireAdministrator</requestedExecutionLevel>
          </javaLauncher>

Regardless of the operating system, paths in `<classpath>` are semi-colon separated.

17. File associations |  | 19. Regular expressions