In fixing this bug I plan to do the following things to cleanup the Java RPM packages in general:
*** Reduce Duplication of Code ***
- Currently there are separate RPM package specification files for the JRE and the JDK. However, the only real differences in these individual specifications is in the values of a few fields. These files, rpm-jdk.spec and rpm-jre.spec, should be combined into a single RPM package specification file that can be used to build either package.
The new specification file, named generic-rpm.spec, should use 'keywords' to represent text that is unique for a particular JDK/JRE package. The Makefile should be changed to replace the keywords, for example, by using the 'sed' command, with the correct text for the JDK and JRE targets at build time.
For example, the Makefile will replace the keyword "RPM_PKG_NAME" in the specification file with the text "jdk" or "jre" using 'sed' depending on whether it is the JDK/JRE targets respectively. Doing this for all JDK/JRE unique text removes the need for separate package specification files.
- Shell scripts should generate the text description for the RPM packages. This will A) ensure that the descriptions are formatted nicely, B) assist in making a single package specification possible, and C) make it possible to get the short, medium, and long version of the public (i.e. marketing) name for each package from a single location.
Note: these names will initially come from the RPM package bundles Makefile. However, later in Mustang other changes are planed to centralize the location for name strings to simplify the process of any future changes to the names.
- Currently a lot of shell script is duplicated in multiple places within the RPM package specifications. For example, the code to add/remove GNOME MIME-type integration is needed in both the post-install, and post-uninstall RPM package scriptlets. This duplication makes it possible for a change to be made in one place, but forgotten in another.
Instead of duplicating scripts it would be better to write them once as a macro , and use them wherever they are needed. RPM does not provide much capability for creating multi-line macros within an RPM package specification file (formatting becomes an issue quickly). However, it is possible to create a macro that behaves somewhat like a C/C++ include statement.
By using the RPM macro directives "expand:" and "%%(<shell-command>)" it is possible to generate a macro that contains all the text of a separate file. This technique should be used to replace the existing inline scripts, plus any new scripts that are required for adding the default and latest Java links to Linux. The existing scripts should be placed into separate files that are named by their functionality. For example:
unpack_jars unpacking pack200 JAR files
legacy_mime_support Netscape MIME-type integration for JavaWS
gnome_support GNOME file extensions/MIME-types integration
parse_release_info Java name/version parse, sort, compare support
link_support support for symbolic links
Note: an advantage to breaking the scripts into separate files is that they can be unit tested outside the RPM build environment. They can also be included in other scripts using the shell 'source' command. This provides the potential to eliminate more duplication by possibly using the same script text in other bundles, such as the Unix self-extracting bundles, or possibly even the Solaris SVR4 packages.
Note: due to limitations in the version of RPM currently used to build Java on the Linux AMD64 (x86_64) platform, it may be necessary to break these files into pieces. In this case, each piece of the file will be given the extension '.partN' where N is from 1 to X, where X is the total number of parts. At a later time when the AMD64 platform is upgraded, these parts should be merged back together.
*** Stop Fixing Past Mistakes ***
There are problems in past Java RPM package scripts that break the system integration setup by other versions of the Java packages. Some of these problems are bugs, others were caused due to an insufficient level of experience in creating RPM packages.
Most RPM package bugs are not critical enough to justify backporting fixes to update releases. However, in the past, some effort has been made in version Y to fix problems caused by version X. In general, this effort has only succeeded in making the RPM package specification scriptlets extremely complex.
In the process of implementing the changes for default and latest Java links, the RPM install process should be simplified. The process should always do whatever is necessary to make the version being installed functional. This typically means creating and populating the Java install directory, ensuring that the files required by the Preferences API exist, and using unpack200 to unpack packed JAR files.
The first two parts can be done automatically by RPM without any pre/post install scriptlets. Using a properly defined %files section within the RPM package specification will ensure that the Java install directory is relocatable, and populated, and that the minimum support for the Preferences API exists (without overwriting pre-existing preferences). (Note: providing a proper %files section also has the benefit of fixing CR 4887372 and 5109119.)
The third part, unpacking JAR files, can only be done with a post-install scriptlet. However, this is also the only thing that *must* happen in every post-install. All other integration should only occur when the version of Java being installed is also the "latest" version. Only in such a case should a default/latest link be created, or any other integration, such as GNOME or Netscape MIME-type integration.
Past packages attempt to do integration with every install. The idea is to "fix" a broken install even when the current install isn't the latest. However, what is correct integration today, most likely won't always be correct. When a package sets integration for a package other than itself, it could be setting old, unsupported integration that the newer package cannot later fix/use/remove.
It is best to only setup additional support functionality only when the package being installed is known to be the latest package on the system. For this same reason, the uninstall scripts should be equally simple.
The uninstall scripts should always remove any changes made by the install. The only time a change made by a package's installer shouldn't be removed by the package's uninstaller is when the same version of the opposing package is still on the system. For example, if JDK version X is being uninstalled, it should remove all changes unless JRE version X is also installed. In which case, it must still remove any changes that wouldn't normally be removed by the JRE version X uninstaller.
*** Provide a Verify Scriptlet ***
The RPM package specification should define the %verifyscript scriptlet. By using the '--verify' option, this scriptlet can be invoked by an administrator at any time after an RPM package is installed. Java RPM packages should use the verify scriptlet to ensure that Java is properly integrated into the system.
The verify script should test to determine if the version being verified is the latest version. If it is the latest version, it should do all the things that the post-install script does when the latest version is installed. Otherwise, the script should do nothing.
The purpose of the verify script is to provide administrators with a method of fixing a broken install that is caused by problems in past Java RPM packages. Instead of trying to fix these mistakes in the install/uninstall scripts, they should only be fixed in the verify script. There are several reasons for this:
1) RPM --upgrade does the following:
* run the pre-install scripts for the new package
* install the package's files
* run the post-install scripts for the new package
* run the pre-uninstall scripts for each old package
* remove any unused files from each old package
* run the post-uninstall scripts for each old package
This means that it is impossible for a post-install script to fix a problem that is caused by an older packages pre/post uninstall scripts.
2) RPM --install --force can be used to install an older version of a package onto a system that already has the latest version of Java. The old version was released long before the current version, and knows nothing about how the new version integrates additional functionality. It is quite likely that it will break some of this functionality. Without a verify script, an administrator would be forced to uninstall/reinstall the latest version.
*** Stop Using EPOCH Tags ***
The JDK RPM package specification currently specifies a EPOCH tag. This tag should never have been used. It is one of the causes for CR 6177499. An EPOCH (or "%Epoch:" in the code) causes RPM to ignore all other version information when making comparisons, i.e. 0:name-1.5.0 = 0:name-1.6.0. The JDK/J2SDK have used the *same* Epoch for *all* releases. This means j2sdk-1.3.0 = j2sdk-1.3.1 - j2sdk-1.4.0, etc...
Note: Removing the EPOCH does not fix 6177499. It could be argued that I shouldn't make this change until I fix 6177499. However, in my reading, the use of EPOCH is so proscribed, I think we should stop it's use immediately.
###@###.### 2005-04-14 20:35:59 GMT
FYI, it seemed to me that greenrd made a good argument for keeping the EPOCH, so that is what I'm doing for now.
As to the comment about using 'alternatives', that API is not supported by all platforms Java is required to support. Specifically it is not supported by SuSE based distributions.
###@###.### 2005-05-17 01:21:01 GMT