Support for Installed Extensions in Java Plug-in 1.3

- Version 0.9 9/27/99 -
Jerome Dochez (dochez@eng)



 
 

send feedback to dochez@eng

Introduction

This proposal defines a standard mechanism that Applets running inside the Java Plug-in should use to define Java Platform extensions which would be installed on the end user desktop environment. The goals of such a design are :
1.0 Java Platform Extensions dependency
 
In Java 2 SDK documentation, the standard way for declaring your dependency on an extension is through the class-path attribute in the manifest information of the jar file. For applets or applications relying on installed extensions, the class-path attribute can be omitted since the system class loader added the extensions at boot time. For extensions declared in the class-path (unless the sealed attribute is used), we will use the normal Java 2 Runtime Environment mechanism : if the extensions is installed, use it, if the extension is not installed, it becomes a bundled extension for this applet.

We need a better way to declare the Applet or Application dependency on extensions. First, the current dependency mechanism relies on jar file names. This is not sufficient since different extensions might share the same jar file name or different jar files may implement the same  extension specification. Second, the applet has no way of requesting minimal versioning of the requested extensions. The applet may have very unexpected results when ran against an older extensions than the one it has been developed and tested against. Finally, the applet has no way of providing alternate site for downloading missing extensions. All extensions has to be downloaded from the same codebase the Applet originated from.

All these short-comings have reduced the ease of using installed standard extension forcing applet or application providers to rely extensively on bundled extensions to avoid walking on each other toes.

1.1 Extension Manifest Attributes
I propose to add several attributes to the manifest file of Extensions. These tags would be partly immediately used and others would be used as hooks for future enhancements of the Java 2 platform

Extension-name

The attribute specifies a unique name for an extension used to identify its specification. This name is usually the main specification package identifier for the extension.

Extension-URL

The attribute specifies the URL to check for an updated version of an extension.

Implementation-Vendor

The Implementation-Vendor optional field should be used for user feedback only. This field usually contains the legal company name of the provided software. To avoid name clashing, the Implementation-Id field should really be used for uniquely identifying the vendor.

Implementation-Id

Although there is already an Implementation-Vendor attribute which specifies the vendor name for an extension implementation, this could still lead to name clashing (Example: the *Morgan* banks). We could use the prefix for the implementation package to uniquely identify the implementation vendor. This name should use the guidelines as defined in the JLS. The Implementation-Vendor will therefore only be used for user-feedback.

Examples :

Here is an example of the standard extension "jhelp.jar" which implements the standard extension "javax.help"

Manifest-Version: 1.0
Extension-Name: javax.help
Specification-Version: 1.0
Specification-Vendor: Sun Microsystems. Inc
Implementation-Version: 1.0
Implementation-Vendor: Sun Microsystems, Inc
Implementation-Vendor-Id: com.sun

A different vendor implementation manifest file would look like this :

Manifest-Version: 1.0
Extension-Name: javax.help
Specification-Version: 1.0
Specification-Vendor: Sun Microsystems. Inc
Implementation-Version: 1.0.3
Implementation-Vendor: International Business Machine
Implementation-Vendor-Id: com.ibm

There could be a problem with attempting to install multiple jar files having the same name.  To minimize this problem, we should promote a suitable convention for naming the jar files.  One suggestion was to use the name of the main package in the jar file as the jar file name, but with the dots changed to underscores to avoid known portability problems.  It would also make sense to append the spec version number to the file name.  E.g.  for the Java Sound version 1.0 extension, the
file could be named javax_sound_1_0.jar.

1.2 Bundled Extensions
Bundled Extensions (also referred to as download extensions) should use the same mechanism as before. This ensure backwards compatibility. Any applet not using the new proposed tags uses the old class-path manifest attribute. The Java Plug-in will then consider these extensions dependencies as bundled extension dependency. For reference, the class-path attribute of the applet manifest file is used to declare bundled extensions. These extensions will be downloaded and cached following the same rules as any jar file dependency declared through the ARCHIVE applet HTML tag.
1.3 Installed Extensions
1.3.1 Extension dependency declaration
I therefore propose to add attributes to the applet manifest to declare the Java Platform extensions dependencies it might have. This attributes should carry the following information :
- Standard Extension Name
- Standard Extension URL
- Vendor ID (optional)
- Minimum Specification Version required (optional)
- Minimum Implementation Version required (optional)
The applet should be able to declare several Java Plaform Extensions dependency through the Extension-List attribute. The  extension download URL should not be limited to the Applet codebase. All downloadable components will need to be signed using an DSA or RSA certificate so we ensure that we do not install rogue extensions on the user's disk. Non signed extensions will be treated as bundled extensions and loaded through the AppletClassLoader sharing the applet security attributes.
Example :

This is an example of a manifest file of an applet declaring its dependency on two installed extensions

Manifest-Version: 1.0
Extension-List: javahelp java3d
javahelp-Extension-Name: javax.help
javahelp-Specification-Version: 1.0
javahelp-Implementation-Version: 1.0.3
javahelp-Implementation-Vendor-Id: com.sun
javahelp-Implementation-URL: http://java.sun.com/products/stdext/javahelp.jar
java3d-Extension-Name: javax.3d
java3d-Specification-Version: 1.0
java3d-Implementation-Version: 1.2.1
java3d-Implementation-Vendor-Id: com.sun
java3d-Implementation-URL: http://java.sun.com/products/stdext/java3d.jar

1.3.2 Extension file format

Although you always point to a jar file, the content of the specified jar can be :

  • Extension Installation
    The extension is a 100 % pure java application. After downloading the jar file and verified its signature, we check the manifest file for the main-class key. If the main-class key is defined, this jar file is considered as being an installation jar file and therefore we should invoke its main() with the applications security rights (remember that this jar file has to be signed or it will be rejected).
  • Native Extension Installation
    The extension needs a full installation (probably to install some native libraries and access to the registry for example). The Java Plug-in will verify its RSA or DSA signature of the jar file. The jar file will need to have a Manifest attribute called extension-installation which point to a native installation application.

    The Implementation-URL attribute can actually be in the form
        java3d-Implementation-URL: http://.../stdext/java3d-$(os-name)$.jar
    $(os-name)$ would be replaced at runtime with the system property "os.name".

    All native installations would be invoked with one parameter, the value of the system property "java.ext.dirs".

  • Extension file
    If the jar manifest do not define the main-class or the extension-installation attributes, the jar file will be considered being the raw extension jar file and it will be copied "As is" to the standard extension directory.
  • 1.3.3 Installation Rules

    This paragraph is to described to rules the mechanism for installing and upgrading the extensions using the above mentioned manifest attributes. All extensions will have to be digitally signed using the RSA or DSA protocol. Unless the vendor-id is in the user's list of "Always trusted provider", the Java Plug-in will display security warnings about the software being downloaded and installed. The user will have to explicitly acknowledge these warnings.

    These are the installation rules the Plug-in or any other tool that want to install/upgrade installed extensions should follow :

  • If an extension with the same Extension-Name does not exist, the new extension can be safely installed. The installation component should still check for any possible package name conflicts and should warn the user for possible damages. This would indicate the extensions did not follow the JLS guidelines on package naming.
  • If an installed extension with the same Extension-Name already exists then the following case arise :
    • The installed Specification-Version >= applet Specification-Version
      • The Implementation-Vendor-Id match
        • The installed Implementation-Version >= applet Implementation-Version
          Nothing to do, the extension is already installed and ready to use.
        • The installed Implementation-Version <applet Implementation-Version
          Prompt to user for an upgrade from the same vendor.
      • The Implementation-Vendor-Id do not match
        Prompt the user for an upgrade/switch to a different vendor
    • The installed Specification-Version  < applet Specification-version
      • The Implementation-Vendor match
        Prompt the user for an upgrade from the same Vendor
      • The Implementation-Vendor do not match
        Prompt the user for an upgrade to a different Vendor

  • If the Implementation-Vendor is not specified, it is considered as having the value "any". All installation should happen in the first directory pointed by the java.ext.dirs property.

    2.0 Java 2 platform impact

    2.1 JRE changes

    2.1.1 Extension dependency detection

    In order to implement such features, some Java 2 platform core classes will need to be modified. At this early stage of the design, I think the core of the changes should happen in sun.misc.URLClassPath that David Connelly added in JDK 1.2. This class is responsible for managing the class-path attributes of jar file manifest. See the  Support for Extensions and Applications article how the classapth for bundled extensions is constructed. This URLClassPath class which currently manages interdependencies of extensions and applets could be extended to check for the new tags I am proposing and propose the extensions installations as described earlier. When loading jar files, the URLClassPath checks for dependencies through the class-path attribute, the new code will also checks for the new tags for extensions dependencies.

    The class sun.misc.ExtensionDependency is responsible for implementing the algorithm described in the paragraph 1.3.4. Upon detection that an required extension needs to installed or upgraded, the ExtensionDependency will rely on the registered callback interface which is responsible for providing download and installation of the extension following the rules described in 1.3.3.

    This is the protocol defined in sun.misc.InstallationDependency to register and unregister ExtensionInstallationProvider. If several ExtensionInstallationProvider are registered, they will be invoked one after the other until the installExtension API return true or the ExtensionInstallationException is thrown.

        /*
         * Add an ExtensionInstallationProvider to delegate all missing extensions
         * installations to
         * /
        public static void addExtensionInstallationProvider(ExtensionInstallationProvider eip);

        /*
         * Remove an ExtensionInstallationProvider
         */
        public static void removeExtensionInstallationProvider(ExtensionInstallationProvider eip);

        /*
         * @return the list of currently registered ExtensionInstallationProvider implementation
         */
        public ExtensionInstallationProvider[] getExtensionInstallationProviders();

    The Plug-in or any other application should register the CallBack interface to the ExtensionDependency at boot time to enable the extension dependancy mechanism.

        public interface ExtensionInstallationProvider {

                /*
                 * <p>
                 * Request the installation of an extension in the extension directory
                 * </p>
                 *
                 * @param requestedExtensionInfo information on the extension that need
                 * to be installed
                 * @param installedExtensionInfo information on the current compatible
                 * installed extension. Can be null if no current installation has been found.
                 * @return true if the extension was successfully installed or false if the
                 * provider could not install the desired extension
                 * @throw ExtensionInstallationException. An installation was attempted
                 * but failed, no more installation should be attempted
                 */
                public boolean installExtension(ExtensionInfo requestedExtensionInfo, ExtensionInfo installedExtensionInfo)
                                throw ExtensionInstallationException

        }

    The ExtensionInfo class contains all the information identifying a particular extension.

                /**
                 * This class holds all necessary information to install or
                 * upgrade a extension on the user's disk
                 *
                 */
                public class ExtensionInfo {

                    public String title;
                    public String name;
                    public String specVersion;
                    public String specVendor;
                    public String implementationVersion;
                    public String vendor;
                    public String vendorId;
                    public String url;
                    public String[] jarFiles;
                }
     

    We will also move all the extension code from sun.misc to a more descriptive package like sun.extension. The list of classes to be moved is
        sun.misc.Launcher
        sun.misc.URLClassPath

    and the new classes
        sun.misc.ExtensionDependency
        sun.misc.ExtensionInstallationProvider
        sun.misc.ExtensionInfo
        sun.misc.ExtensionInstallationException

    2.1.2 Extension Installation Notification

    Some service providers may be interested to be notified when new extensions have been successfully installed in the running Java VM. In order to receive notification they should register the following listener interface

    package sun.misc;
    public interface ExtensionInstallationListener {

        /*
         * Invoked when an extension has been sucessfully installed
         */
        public void installationNotification(ExtensionInstallationEvent e);
    }

    package sun.misc;
    public class ExtensionInstallationEvent extends java.util.EventObject {
        /*
         * Construct a new event with the information about the installed extension
         */
        public ExtensionInstallationEvent(ExtensionInfo ei);

        /*
         * @return the information about the installed extension
         */
        public ExtensionInfo getInstalledExtensionInfo();
    }

    This listener interface will be registered on sun.misc.ExtensionDependency class through :

    /*
     * Register a new ExtensionInstallationListener interface
     */
    public void addExtensionInstallationListener(ExtensionInstallationListener eil);

    /*
     * Unregister a previously registered ExtensionInstallationListener interface
     */
    public void removeExtensionInstallationListener(ExtensionInstallationListener eil);

    2.1.3 ClassLoader changes

    In order to provide a seemless experience to the user, the newly installed extension should be visible to the client code without requiring to restart the Java RunTime. In order to do so, a few modification have to be made to the sun.misc.Launcher classes which manage the class-loaders for applications and installed extensions. The main change is to move the class definition sun.misc.ExtClassLoader (responsible for loading extensions) from private to package restricted and add a package restricted method to add newly installed jar files to the list of installed extensions.

    2.1.3 RSA signature

    We should also modify the RSA security provider we provide with the Java Plug-in (1.2.1) to make it an extension. That way, users could install the RSA security provider as described in the Java 2 Platform Security documentation  to check and validate jar files when running as an application rather than just an applet inside the Java Plug-in. We would be adding a second default security provider beside the sun.security.provider.Sun. I would advocate we make this second security provider ON by default in the java.security file that ships with the jdk by adding the following :

     security.provider.2=sun.security.jsafe.Provider
    Issue: The current RSA provider relies on the availability of a Browser to actually do the signature verification. If Internet Explorer are not installed on the client machine, we would need to fail gracefully warning the user with a precise error message.
    2.2 Plugin changes
    The plugin will provide an implementation of the sun.misc.ExtensionInstallationProvider. These implementation will be registered at initialization time to enable installation of dependent extensions.
    2.2.1 User Feedback

    During the download of extensions, we need to provide simple feedback to the user to notify on the progress of the download and installation of the requested extensions. The feedback should appear in the a temporary top dialog.

    2.2.2 Support Tools

    A number of tools will need to be added or modified to help the user deploying its applets with  extensions within the Java 2 Runtime Environment and the Java Plug-in.

    3.0 Java 2 platform dependency
    In order to have this proposal working, the Java Plug-in team needs several improvements to the Java 2 platform.
    3.1 Multiple implementation of a specification (optional)
    If applet A requires standard extensions javax.help implementation from com.sun Implementor-Id and Applet B requires javax.help implementation from com.ibm Implementor-Id, the current behaviour of currently undefined.

    Issue: Should we use the ClassLoader delegation model to load extensions in separate trusted class loader to avoid implementation and version collision ?
     

    3.2 Intelligent extension directory parsing
    Right now, all extensions (jar files) present in the lib/ext directory are blindly added to the extension class loader. I think we should provide a minimum sanity check when loading these jars to load only the latest version (if multiple versions are installed) to reduce the risks of version clashing.