blob: 3b6d8f7ef29e45ac4ddd6c1af7a64c814796f76e [file]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>
</head>
<body style="background-color: white;">
<p>This framework facilitates construction of installers for laying
down bits onto a target machine. This framework is focused solely on
interacting with the user and installing data; Provisioning, packaging,
and automating the process of assembling the installer are expressly
outside the scope of this framework.</p>
<p>These installers are currently self
contained, having both installation behavior and data to be installed,
although the framework can be extended to pull data from remote sources
as part of the installation process. The bulk of the installer, written
in java, is optionally wrappered in a native executable used to either locate
or deliver a suitable java virutal machine and
then start the java based installer.&nbsp;The resulting installer can
interact with the user as a traditional installer using an SWT/JFace
based wizard, as a console based installer,&nbsp;or even headlessly
where all installation options are described in an options file. The
framework could easily be extended to interact with the user using a
Swing based wizard rather than an SWT/JFace based wizard if so desired.
</p>
<p><a name="main">Constructing
an installer involves writing a <span style="font-weight: bold;">main class</span></a> to describe the information
to be gathered and the operations necessary to install the data onto
the target machine (see example below). The information to be gathered is described using
{@link com.instantiations.installer.core.model.IInstallStep} subclasses
and placed into an
instance of {@link com.instantiations.installer.core.InstallOptions}. A
sequence of {@link
com.instantiations.installer.core.model.InstallOperation}s is
constructed to perform the actual installation of bits onto the target
machine based upon the&nbsp;{@link
com.instantiations.installer.core.InstallOption}s selected. The {@link
com.instantiations.installer.core.steps.RunOperationsStep} is used to
execute the&nbsp;{@link
com.instantiations.installer.core.model.InstallOperation}s. This
approach separates the collection of installation information from the
acutall installation so that different inputs (wizard, console,
headless) will drive the same installation operations.&nbsp;</p>
<p>An {@link com.instantiations.installer.core.InstallerFactory}
instantiates a subclass of {@link com.instantiations.installer.core.model.Installer}
to interpret these {@link com.instantiations.installer.core.model.IInstallStep}s
and gather the information necessary for the installtion.
Which installer is instantiated depends upon the command line options
choosen when the installer is launched.&nbsp;One
installer subclass will interact with the user using a traditional wizard based
interface while another gathers information using a console window.</p>
<p>During
the {@link com.instantiations.installer.core.steps.RunOperationsStep}, the&nbsp;{@link
com.instantiations.installer.core.model.InstallOperation}s are executed and a log
file generated containing a complete list of the operations that were
performed during installation. The {@link com.instantiations.installer.core.operations.CreateUninstallerOperation} creates
an uninstaller that, when executed at a later time, reads the
installation log generated by the&nbsp;{@link com.instantiations.installer.core.steps.RunOperationsStep} and performs the
inverse operation resulting in the removal of the application from the
target machine.</p>
<p>Some operations such as {@link com.instantiations.installer.core.operations.RegisterProductOperation}
are resolved during execution to platform specific operations and
behavior. Other platform specific information and behavior can be
accessed via {@link com.instantiations.installer.core.Platform#getPlatform()}.</p><p>Installers
for Eclipse extensions can use {@link
com.instantiations.installer.core.eclipse.EclipseInstallation} to
locate existing installations of Eclipse based applications. {@link
com.instantiations.installer.core.steps.ChooseEclipseStep} and more
generically {@link
com.instantiations.installer.core.steps.ChooseProductStep} prompt the
user for which&nbsp;Eclipse based applications are to be extended
while&nbsp;{@link
com.instantiations.installer.core.operations.LinkProductOperation}links
the applications.</p>
<h2><a name="example">Example</a></h2>
<p>The main() method in a typical installer main class involves:&nbsp;</p>
<ul>
<li>initializing the&nbsp;{@link com.instantiations.installer.core.InstallOptions}</li>
</ul>
<pre> options = new {@link com.instantiations.installer.core.InstallOptions}(getClass(), "install.properties");<br> options.setUninstall(isUninstaller());<br> //options.setNobackup(true);<br> initInstallDir();<br> options.parseCommandOptions(args);<br></pre>
<ul>
<li>instantiating a new installer based upon the installation options (wizard, console, headless)</li>
</ul>
<pre> installer = {@link com.instantiations.installer.core.InstallerFactory}.createInstaller(options);<br></pre>
<ul>
<li>setting up the install steps and install operations based upon whether this is an installation or uninstallation</li>
</ul>
<pre> if (options.isInstall())<br> createInstall();<br> else<br> createUninstall();<br></pre>
<ul>
<li>and then running the installer</li>
</ul>
<pre> installer.run();</pre>
<p>In the code above, after the {@link
com.instantiations.installer.core.InstallOptions} have been
instantiated, the isUninstaller method determines whether or not the
code should be installing or uninstalling. This method determines
whether or not the code is being installed or unstalled based upon
whether or not the data is contained within this instance of the
installer or if this installer is a data-less copy of the installer
generated by {@link
com.instantiations.installer.core.operations.CreateUninstallerOperation}.
Installation or uninstallation can be overridden by an option on the
command line read as parsed by the parseCommandOptions method in the
code above.</p><pre>&nbsp;&nbsp;&nbsp; protected boolean isUninstaller() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String selfPath = System.getProperty(Context.INSTALLER_JAR_PROPERTY);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (selfPath == null) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ZipFile image = new ZipFile(selfPath);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ZipEntry installImage = image.getEntry(INSTALL_IMAGE);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (installImage == null) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch (IOException ex) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp;&nbsp; }</pre>
<p>The directory into which the product is installed is determined at time of execution:</p><pre>&nbsp;&nbsp;&nbsp; protected String initInstallDir() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; IPlatform platform = Platform.getPlatform();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (platform == null)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[] productLocations;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; productLocations = platform.readPreviousProductInstallLocations(options);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch (Exception e) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (options.isVerbose())<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (productLocations == null || productLocations.length == 0)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String installDir = productLocations[productLocations.length - 1];<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (options.isVerbose())<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Setting InstallDir to prior installation: " + installDir);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; options.set(InstallOptions.OPTION_INSTALL_DIR, installDir);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return installDir;<br>&nbsp;&nbsp;&nbsp; }</pre><p>Once
the&nbsp;{@link
com.instantiations.installer.core.InstallOptions} have been initialized
and a new installer instantiated by the&nbsp;{@link
com.instantiations.installer.core.InstallerFactory}, either the
createInstall method is called</p><pre>&nbsp;&nbsp;&nbsp; protected void createInstall() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installer.setTitle(options.getString("InstallerTitle"));<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; welcomeStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; licenseStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installDirStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chooseProductStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; chooseEclipseStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; checkEclipseRunning();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cleanConfigStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; removeEmbeddedInstallStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; verifyInstallStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installCodeStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installResultStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installCompleteStep();<br>&nbsp;&nbsp;&nbsp; }</pre><p>or the createUninstall method is called</p><pre>&nbsp;&nbsp;&nbsp; protected void createUninstall() {<br>&nbsp;&nbsp;&nbsp; installer.setTitle(options.getString(InstallOptions.OPTION_PRODUCT_NAME) + " Uninstaller");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; verifyUninstallStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; uninstallCodeStep();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; uninstallCompletStep();<br>&nbsp;&nbsp;&nbsp; }</pre><p>The installDirStep() describes prompting the user for the application's installation location:</p><pre>&nbsp;&nbsp;&nbsp; protected String initInstallDir() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; IPlatform platform = Platform.getPlatform();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (platform == null)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[] productLocations;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; productLocations = platform.readPreviousProductInstallLocations(options);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch (Exception e) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (options.isVerbose())<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; e.printStackTrace();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (productLocations == null || productLocations.length == 0)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String installDir = productLocations[productLocations.length - 1];<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (options.isVerbose())<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Setting InstallDir to prior installation: " + installDir);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; options.set(InstallOptions.OPTION_INSTALL_DIR, installDir);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return installDir;<br>&nbsp;&nbsp;&nbsp; }</pre><p>The
installCodeStep method constructs {@link
com.instantiations.installer.core.model.IInstallStep}s to lay down the
bits on the disk based upon the&nbsp;{@link
com.instantiations.installer.core.InstallOptions}.</p><pre>&nbsp;&nbsp;&nbsp; protected RunOperationsStep installCodeStep() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; final RunOperationsStep step = new RunOperationsStep(installer) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void aboutToStep() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; createInstallOperations(this);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; catch (IOException e) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; showException(e);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; initStep(step, "InstallCode");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installer.add(step);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return step;<br>&nbsp;&nbsp;&nbsp; }</pre><pre>&nbsp;&nbsp;&nbsp; protected void createInstallOperations(RunOperationsStep step) throws IOException {<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Assemble install operations<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String selfPath = System.getProperty(Context.INSTALLER_JAR_PROPERTY);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // The file containing code to be delivered<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ZipFile image = new ZipFile(selfPath);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // The directory into which the product will be installed<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; File installDir = new File(options.getString(InstallOptions.OPTION_INSTALL_DIR));<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Get subproducts to be installed<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SubProduct[] subProducts = getSubProductsToInstall();<br><br> // Build the install operations<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int j = 0; j &lt; subProducts.length; j++) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SubProduct each = subProducts[j];<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String relInstallPath = each.getInstallDirName() + File.separator + "E-" + eclipseTargetAlt;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; File installSubDir = new File(installDir, relInstallPath);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ZipEntry[] entries = each.getEntries(image);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int k = 0; k &lt; entries.length; k++)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; step.add(new ExtractDirectoryOperation(image, entries[k], installSubDir));<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String primaryProductDirName = getPrimaryProduct().getInstallDirName();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; File primaryProductDir = new File(installDir, primaryProductDirName);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; step.add(new CreateUninstallerOperation(primaryProductDir, CreateUninstallerOperation.UNINSTALL_JAR,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; INSTALL_IMAGE));<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; step.add(new RegisterProductOperation(options, primaryProductDirName + File.separator<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; + CreateUninstallerOperation.UNINSTALL_JAR));<br>&nbsp;&nbsp;&nbsp; }</pre><p>The verifyUninstallStep method describes prompting the user to confirm the uninstall, while
the uninstallCodeStep method&nbsp;constructs {@link
com.instantiations.installer.core.model.IInstallStep}s to remove the
bits from the disk. The {@link
com.instantiations.installer.core.operations.UninstallOperation}
operation referenced below reads the install log file and&nbsp;performs the
inverse operation resulting in the removal of the application from the
target machine.</p><pre>&nbsp;&nbsp;&nbsp; protected RunOperationsStep uninstallCodeStep() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; final RunOperationsStep step = new RunOperationsStep(installer) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void aboutToStep() {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; createUninstallOperations(this);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; step.setDescription("Uninstalling...");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; installer.add(step);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return step;<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; protected void createUninstallOperations(RunOperationsStep step) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // Assemble uninstall operations<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String selfPath = System.getProperty(Context.INSTALLER_JAR_PROPERTY);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; File self = new File(selfPath);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; File logFile = new File(self.getParentFile(), CreateUninstallerOperation.INSTALL_LOG);<br><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; step.add(new UninstallOperation(logFile));<br>&nbsp;&nbsp;&nbsp; }</pre><h2>Related Documentation</h2>
For overviews, tutorials, examples, guides, and tool documentation, please see:
<ul>
<li><a href="../../gettingstarted/packager.html">Introduction to RCP Packager</a></li>
<li><a href="../../gettingstarted/GenSample.html">Generating a Sample RCP Application</a></li>
<li><a href="../../gettingstarted/GenInstaller.html">Generating an Installer</a></li>
</ul>
</body></html>