# RCE Launcher Customization

The Equinox framework provides a launcher JAR, which is the first point of entry for the JRE when running the application/product.
This launcher, after performing various initialization steps, spawns and delegates to the OSGi framework (in this case, Equinox), which then locates and starts the application's bundles.
Most of the application's startup logic should usually take place in these bundles' activators and the `Application` subclass (in case of RCE, `de.rcenvironment.core.start.Application`), so the default launcher is often sufficient.

Over time, however, we have identified some initializations that could (at least at that time) not be injected early enough via these standard mechanisms.
One important use case is launch parameter rewriting, especially regarding parameters that affect the Equinox framework's startup itself.
For example, when running RCE with the `--headless` launch option, we want this to automatically include the standard Equinox `-nosplash` launcher parameter.
Another example is making launch parameters more consistent, e.g. providing a custom `--console` parameter as an alias to Equinox' `-console` parameter.
(TODO list other use cases)
To address these needs, we have introduced a customized Equinox launcher.

The default launcher is `org.eclipse.equinox.launcher`, which can be overridden in the application's .ini file with the `-startup` parameter.
Looking at the `rce.ini` in the root folder of an RCE build, this is the reference that replaces the default launcher with the custom `de.rcenvironment.core.launcher` JAR:
```
-startup
plugins/de.rcenvironment.core.launcher_<version tag>.jar
```

The project and build setup behind this, however, is somewhat complicated, and may be confusing at first.
The custom launcher (where this README is also found) is located in the `org.eclipse.equinox.launcher` sub-folder of the repository root.
This is also the name of the Eclipse IDE project when importing this folder.
However, as part of the build process, the launcher is actually built from the `de.rcenvironment.core.launcher` sub-folder's POM, and packaged into a JAR of the same name.
This POM setup references/uses the sources from the `org.eclipse.equinox.launcher` sub-folder/project.
  
As the result of this setup, the patched launcher code "looks like" an `org.eclipse.equinox.launcher` bundle inside the Eclipse IDE, but is actually compiled and packaged as a `de.rcenvironment.core.launcher` bundle at build time, and referenced as such when running the standalone product.

An additional complication arising from this setup is the OSGi test bundle `de.rcenvironment.core.launcher.tests`.
As usual, this test bundle is a fragment of the bundle to be tested.
However, the "host bundle" declaration defining this is tricky, because at build time, it needs to be `de.rcenvironment.core.launcher`, while the bundle is made to look like `org.eclipse.equinox.launcher` in the IDE workspace.
As a result, this project is (as of 10.3.0) not made an Eclipse project as well, which prevents it to be imported into the workspace and cause problems.
However, this makes keeping this test bundle in sync (and using it for testing) cumbersome.

Why was this somewhat convoluted setup chosen?

The core problem that this setup addresses was/is the problem of also using the customized launcher when running RCE from inside Eclipse.
When using the straightforward approach of handling the custom launcher as a normal project bundle, the IDE will launch using the standard `org.eclipse.equinox.launcher` bundle as provided by the target platform.
When the `org.eclipse.equinox.launcher` workspace project is imported and open, however, this overrides the default bundle from the target platform, and the custom launcher is used as intended.
Intuitively, there should be an explicit parameter in the launch options to choose a custom launcher project, but at least at the time when this customization was added, the developer working on this could not find any way that worked.
As a result, this setup was built, and while it is fairly complicated, it has worked well so far.

One alternative approach that was considered, but rejected at the time was pre-compiling the custom launcher bundle, and replacing the `org.eclipse.equinox.launcher` of the target platform with it.
This way, both IDE and standalone launches should automatically use it, removing the need for the setup described above.
However, this would separate the launcher from the application code, which would create higher coupling between the target platform and the application.
Additionally, this way the custom launcher would be even more obscured than it is now, making any related debugging even more difficult.
Another small downside would be that when iterating on the launcher, any code change would require a target platform recompile; however, as changes in the launcher are fairly rare, this is not too relevant.

A different approach that might work would be treating `de.rcenvironment.core.launcher` (and its test bundle) as a normal project, and use it as the standalone launcher directly.
To resolve the IDE launch situation, a small "shim" bundle with the bundle id `org.eclipse.equinox.launcher` would be added that does nothing but delegate to the real launcher (the `de.rcenvironment.core.launcher` bundle and project).

In summary, the current setup works well, but it would still be desirable to see if a less complicated setup is possible with current Equinox and Eclipse IDE versions.

## Upgrading the launcher bundle to a new RCP version

* In RCE's custom launcher project, temporarily move/rename these existing folders:
** `src/main/java/org/`
** `META-INF/`

* Find the "drop" page for the new Equinox release on https://download.eclipse.org/equinox/ or https://archive.eclipse.org/equinox/ . 

* Download that version's SDK zip and extract it to a temporary location.

* From this, extract the `plugins/org.eclipse.equinox.launcher.source_<version tag>.jar` file to a temporary location.

* Copy the following folders and files from the unpacked JAR into the custom launcher project:
** `org/`-> `src/main/java/org/` (unpacked location -> location in custom bundle)
** `META-INF/MANIFEST.MF`
** `about.html`
** `build.properties`

* Copy the new `[src/main/java/]org/eclipse/equinox/launcher/Main.java` to `reference/Main_<version tag>.java` as a base point for future diff inspection.

* Patch the new `org.eclipse.equinox.launcher.Main` class
** Make sure to never invoke the Eclipse formatter on the whole file, as this would create lots of unmaintainable per-line differences. This is especially relevant if you have configured your IDE to "auto-format on save".
** Copy the file header over from the previous patched file (from the previous "org/" folder renamed above).
** Check the copyright lines' diff against the original file for correctness; adjust as necessary.
** Check the copyright year number(s); adjust if necessary.
** Apply "optimize imports" in Eclipse to resolve the ".*" import statements. This is not strictly necessary, but generally a good practice.
** TODO document details; until then, use the existing diff as reference

* Patch `META-INF/MANIFEST.MF`
** TODO document details; until then, use the existing diff as reference
