Use a Java applet in an ICN plugin

In this post, I will describe how to embed and use a Java applet in your IBM Content Navigator plugin. Applets may be useful to overstep some JavaScript limitations, usually related to security, for instance read/write the client’s file system.

I won’t explain how to write, package and sign your applet since you can find plenty of tutorials on this topic on the web. However I will explain how to embed your applet into your plugin, then how to use it.

Embedded the applet jar in your plugin jar

If you want your plugin to be self contained, a nice way to do so would be to embed your applet into your plugin’s jar. You can of course also make it available form another location. For this tutorial, I will use an applets folder under the WebContent folder of your plugin, and paste my applet jar in it. That’s all you need to do. From now on we will use the jar in the plugin’s jar.

Create a Dojo class to simplify the use of your applet

If you had the chance to work with the FileTracker applet when customizing ICN, you may have noticed that they created a single Dojo class to access the applet. This is pretty nice and takes care of all low level code like adding the applet to the DOM, log, security parameters and so on. We will do the same for our applet. First, create a new Dojo class, using a Singleton pattern.

Create the class

For this tutorial, we will call it myPluginDojo.MyApplet. This gives you the following class, almost empty for now:

define([
    "dojo/_base/declare",
    "dojo/_base/kernel",
    "dojo/_base/sniff",
    "ecm/model/_ModelObject",
    "ecm/model/Request"
], function (declare, kernel, has, _ModelObject, Request) {
    /**
     * @name myPluginDojo.MyApplet
     * @class Provides the ability to access our applet functionality.
     *        This class takes care of initializing the applet and making it available to the client.
     * @augments ecm.model._ModelObject
     */
    var MyApplet = declare("myPluginDojo.MyApplet", [
        _ModelObject
    ], {
        /** @lends myPluginDojo.MyApplet */
        /**
         * Tracks if we already initialize the applet or not (added to the DOM)
         */
        appletStarted: false,
        /**
         * Our applet
         */
        myApplet: null,
    });

    // Singleton constructor
    var _instance;
    if (!_instance) {
        _instance = new IDCMSApplet();
    }
    return _instance;
});

Add the applet to the DOM

Now we need a method to add the applet to the DOM and let the browser starts the applet. Let’s write a function createApplet:

/**
 * This utility function creates the correct tags to use for invoking an applet.
 *
 * @param name
 *            The name of the applet, for reference by other applets.
 * @param width
 *            The width of the applet.
 * @param height
 *            The height of the applet.
 * @param code
 *            The Java class for the applet.
 * @param codebase
 *            The directory in which to search for the applet's class or jar.
 * @param archive
 *            The jars containing classes for the applet.
 * @param params
 *            Additional applet parameters.
 * @private
 */
createApplet: function (name, width, height, code, codebase, archive, params) {
    var methodName = "createApplet";
    this.logEntry(methodName);
    var applet = 0;
    var param, appletDiv;
    var logLevel = ecm.logger.getLogLevel();
    var proxyUrl = "";
    var platform = (navigator && navigator.platform ? navigator.platform : "Win32");
    var jniSignatureUri = Request.appendSecurityToken("getJNISignature.do");
    var jniUriConnector = (jniSignatureUri.indexOf("?") < 0 ? "?" : "&");

    jniSignatureUri = jniSignatureUri + jniUriConnector + "platform=";

    // create the applet element
    if (has("ie") || has("trident") || (navigator.appName.indexOf("Microsoft") != -1)) {
        var objectHTML = '<object name="' + name + '" width="' + width + '" height="' + height + '" classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93">' + '<param name="code" value="' + code + '"></param>' + '<param name="codebase" value="' + codebase + '"></param>' + '<param name="archive" value="' + archive + '"></param>' + '<param name="logLevel" value="' + logLevel + '"></param>' + '<param name="scriptable" value="true"></param>' + '<param name="mayscript" value="true"></param>';
        for (param in params) {
            objectHTML = objectHTML + '<param name="' + param + '" value="' + params[param] + '"></param>';
        }
        objectHTML = objectHTML + '<param name="' + 'WCProxy' + '" value="' + window.WCProxy + '"></param>';
        objectHTML = objectHTML + '<param name="' + 'logLevel' + '" value="' + logLevel + '"></param>';
        objectHTML = objectHTML + '<param name="' + 'clientLocale' + '" value="' + kernel.locale + '"></param>';
        objectHTML = objectHTML + '<param name="jniSignatureUri" value="' + jniSignatureUri + '"></param>';
        objectHTML = objectHTML + '<param name="platform" value="' + platform + '"></param>';
        objectHTML = objectHTML + '<div id="javaPluginNotFoundFT"><p>&nbsp;<p></div>';//
        objectHTML = objectHTML + '</object>';
        appletDiv = document.createElement("div");
        appletDiv.innerHTML = objectHTML;
        applet = appletDiv.firstChild;

    } else { // for other browsers, use applet tag
        var appletHTML = '<applet' + ' alt="' + name + '" name="' + name + '" width="' + width + '" height="' + height + '" code="' + code + '" codebase="' + proxyUrl + codebase + '" archive="' + archive + '" mayscript="true">';
        appletHTML = appletHTML + '<param name="' + 'logLevel' + '" value="' + logLevel + '"></param>';
        for (param in params) {
            appletHTML = appletHTML + '<param name="' + param + '" value="' + params[param] + '"></param>';
        }
        appletHTML = appletHTML + '<param name="' + 'WCProxy' + '" value="' + window.WCProxy + '"></param>';
        appletHTML = appletHTML + '<param name="' + 'clientLocale' + '" value="' + kernel.locale + '"></param>';
        appletHTML = appletHTML + '<param name="platform" value="' + platform + '"></param>';
        appletHTML = appletHTML + '<param name="jniSignatureUri" value="' + jniSignatureUri + '"></param>';
        appletHTML = appletHTML + '<param name="java_arguments" value="-Djava.net.preferIPv4Stack=true"></param>';
        appletHTML = appletHTML + '<div id="javaPluginNotFoundFT"><p>&nbsp;<p></div>';//
        appletHTML = appletHTML + '</applet>';
        appletDiv = document.createElement("div");
        appletDiv.innerHTML = appletHTML;
        applet = appletDiv.firstChild;
    }
    this.logExit(methodName);
    return applet;
}

Initialize the applet

CreateApplet is a generic function. Let’s write a function using it to actually starts our applet:

_startApplet: function () {
    if (!this.appletStarted) {
        this.appletStarted = true;
        this.myApplet= this.createApplet("myApplet", "1px", "1px", "org.mypackage.MyApplet.class", Request.getPluginResourceUrl("MyPlugin", "applets"), "MyApplet.jar");
        document.body.appendChild(this.idcmsApplet);
    }
    return this.myApplet;
},

Notice how we use the Request.getPluginResourceUrl() to get a dynamic URL to our applet folder within our plugin’s jar. That way we do not depend on how ICN access the plugin resources.

Expose your Java methods

Now that we have a class capable of adding the applet to the DOM, let’s make available our Java methods as JavaScript functions. For this tutorial, we will say we have one method creating a folder. The Java signature is:

public boolean createDirs(String path);

The JavaScript function would be:

createDirs: function (path) {
    var methodName = "createDirs";
    this.logEntry(methodName);
    this._startApplet();
    return this.myApplet.createDirs(path);
},

Simple right? Don’t forget to always call _startApplet at the beginning of all calls, so we init the applet on the first call. You can do this for all your Java methods.

Use your applet in your plugin

That’s it! You can now use your applet anywhere in your plugin by only calling:

MyApplet.createDirs('C:\\somedir');

Of course add your Dojo class to the list of required modules.

Here is the complete class:

define([
    "dojo/_base/declare",
    "dojo/_base/kernel",
    "dojo/_base/sniff",
    "ecm/model/_ModelObject",
    "ecm/model/Request"
], function (declare, kernel, has, _ModelObject, Request) {
    /**
     * @name myPluginDojo.MyApplet
     * @class Provides the ability to access our applet functionality.
     *        This class takes care of initializing the applet and making it available to the client.
     * @augments ecm.model._ModelObject
     */
    var MyApplet = declare("myPluginDojo.MyApplet", [
        _ModelObject
    ], {
        /** @lends myPluginDojo.MyApplet */
        /**
         * Tracks if we already initialize the applet or not (added to the DOM)
         */
        appletStarted: false,
        /**
         * Our applet
         */
        myApplet: null,

        _startApplet: function () {
            if (!this.appletStarted) {
                this.appletStarted = true;
                this.myApplet= this.createApplet("myApplet", "1px", "1px", "org.mypackage.MyApplet.class", Request.getPluginResourceUrl("MyPlugin", "applets"), "MyApplet.jar");
                document.body.appendChild(this.idcmsApplet);
            }
            return this.idcmsApplet;
        },

        /**
         * Create a directory and all parents if necessary. Does nothing if the folder already exists.
         * @param path {String} the path of the new directory
         * @return <code>true</code> if the folder has been created with success or already exists,
         *         <code>false</code> if something went wrong during creation
         */
        createDirs: function (path) {
            var methodName = "createDirs";
            this.logEntry(methodName);
            this._startApplet();
            return this.myApplet.createDirs(path);
        },

        _stopApplet: function () {
        this.logEntry("_stopApplet");
        if (this.appletStarted) {
            document.body.removeChild(this.idcmsApplet);
            this.appletStarted = false;
        }
        this.logExit("_stopApplet");
        },

        /**
         * This utility function creates the correct tags to use for invoking an applet.
         *
         * @param name
         *            The name of the applet, for reference by other applets.
         * @param width
         *            The width of the applet.
         * @param height
         *            The height of the applet.
         * @param code
         *            The Java class for the applet.
         * @param codebase
         *            The directory in which to search for the applet's class or jar.
         * @param archive
         *            The jars containing classes for the applet.
         * @param params
         *            Additional applet parameters.
         * @private
         */
        createApplet: function (name, width, height, code, codebase, archive, params) {
            var methodName = "createApplet";
            this.logEntry(methodName);
            var applet = 0;
            var param, appletDiv;
            var logLevel = ecm.logger.getLogLevel();
            var proxyUrl = "";
            var platform = (navigator && navigator.platform ? navigator.platform : "Win32");
            var jniSignatureUri = Request.appendSecurityToken("getJNISignature.do");
            var jniUriConnector = (jniSignatureUri.indexOf("?") < 0 ? "?" : "&");

            jniSignatureUri = jniSignatureUri + jniUriConnector + "platform=";

            // create the applet element
            if (has("ie") || has("trident") || (navigator.appName.indexOf("Microsoft") != -1)) {
                var objectHTML = '<object name="' + name + '" width="' + width + '" height="' + height + '" classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93">' + '<param name="code" value="' + code + '"></param>' + '<param name="codebase" value="' + codebase + '"></param>' + '<param name="archive" value="' + archive + '"></param>' + '<param name="logLevel" value="' + logLevel + '"></param>' + '<param name="scriptable" value="true"></param>' + '<param name="mayscript" value="true"></param>';
                for (param in params) {
                    objectHTML = objectHTML + '<param name="' + param + '" value="' + params[param] + '"></param>';
                }
                objectHTML = objectHTML + '<param name="' + 'WCProxy' + '" value="' + window.WCProxy + '"></param>';
                objectHTML = objectHTML + '<param name="' + 'logLevel' + '" value="' + logLevel + '"></param>';
                objectHTML = objectHTML + '<param name="' + 'clientLocale' + '" value="' + kernel.locale + '"></param>';
                objectHTML = objectHTML + '<param name="jniSignatureUri" value="' + jniSignatureUri + '"></param>';
                objectHTML = objectHTML + '<param name="platform" value="' + platform + '"></param>';
                objectHTML = objectHTML + '<div id="javaPluginNotFoundFT"><p>&nbsp;<p></div>';//
                objectHTML = objectHTML + '</object>';
                appletDiv = document.createElement("div");
                appletDiv.innerHTML = objectHTML;
                applet = appletDiv.firstChild;

            } else { // for other browsers, use applet tag
                var appletHTML = '<applet' + ' alt="' + name + '" name="' + name + '" width="' + width + '" height="' + height + '" code="' + code + '" codebase="' + proxyUrl + codebase + '" archive="' + archive + '" mayscript="true">';
                appletHTML = appletHTML + '<param name="' + 'logLevel' + '" value="' + logLevel + '"></param>';
                for (param in params) {
                    appletHTML = appletHTML + '<param name="' + param + '" value="' + params[param] + '"></param>';
                }
                appletHTML = appletHTML + '<param name="' + 'WCProxy' + '" value="' + window.WCProxy + '"></param>';
                appletHTML = appletHTML + '<param name="' + 'clientLocale' + '" value="' + kernel.locale + '"></param>';
                appletHTML = appletHTML + '<param name="platform" value="' + platform + '"></param>';
                appletHTML = appletHTML + '<param name="jniSignatureUri" value="' + jniSignatureUri + '"></param>';
                appletHTML = appletHTML + '<param name="java_arguments" value="-Djava.net.preferIPv4Stack=true"></param>';
                appletHTML = appletHTML + '<div id="javaPluginNotFoundFT"><p>&nbsp;<p></div>';//
                appletHTML = appletHTML + '</applet>';
                appletDiv = document.createElement("div");
                appletDiv.innerHTML = appletHTML;
                applet = appletDiv.firstChild;
            }
            this.logExit(methodName);
            return applet;
        }
    });

    // Singleton constructor
    var _instance;
    if (!_instance) {
        _instance = new IDCMSApplet();
    }
    return _instance;
});

2 thoughts on “Use a Java applet in an ICN plugin

    1. Guillaume Post author

      Hi Adrian,

      Just use the MyApplet class as a static class, for instance:
      MyApplet.createDirs("C:\\DummyFolder");
      After taking care of importing the class of course

      Hope that helps.

      Reply

Leave a Reply