Did you know? Programmers convert coffee to code.

If you like my articles, sponsor me a coffee.

Migrating applets to make them run

I know this is a rare use case, however sometimes you simply have an applet (on a website for example) which is not signed. Or you want to do something illegal and download the applet and get it run locally.

And from the new version of Java 8 these applets do not run anymore.  For the second scenario it will not run because the signature is not for your local machine instead the site where the applet is originally hosted.

So it comes handy if you could find a way to get these applets run on your machine. I try to help you to solve this issue.

I’ve faced this problem too when I tried to get an old applet running which does some functionality I’d need and I did not find any more useful solutions for it which could have been developed in short time with minor effort.

The basic case is quite easy where the applet does not take any parameters. However I am a good guy and I don’t let it be the simple case because many of the applets need some user input. However as a compensation I will not focus in this article on JavaScript based updates because it is worth an own article later in the future.

So let’s assume that we have an applet contained in a JAR. Reverse engineering is no option because the code is well obfuscated and the result source codes are not readable and if you try to compile the output you get a mess of compilation errors. To be honest, this is seldom, because if you encounter such an applet mostly it is signed to the site where it normally runs. In this case you could use the site instead of the applet locally.

But now let’s assume that you have the JAR with the applet, it is obfuscated and you cannot use it locally because if you embed it into an HTML page you get the error message from your Java that the applet is not trusted and it has been disabled. Even if you enter your site in the security exceptions you get an error too:

The typical applet error you get.

The typical applet error you get.

And this is bad. Bad because you want to let it run.

Another bad thing is that the appletviewer does not work on Mac because it needs JRE 6 — a no-go actually.

Good news

Naturally I won’t start an article where I could not help with a solution. Naturally there are some which seemed to work in the past but not with Java 8 nowadays.

So I stay with the one implementation I came up lately. It is easy to follow and it does the trick.

Imagine, you want to run the applet WellProtected.class of the WellProtected.jar. As the name tells you, this JAR its well protected so you cannot reverse engineer it (or at least not with those decompilers I’ve found; if you have something what is capable to de-obfuscate Java class files into well-readable and compilable Java files, write me!).

At the end, you could run your application with the following commando:

java -cp .:WellProtected.jar AppletRunner

In this case the WellProtected.jar and the AppletRunner.class files have to be in the same folder.

The solution

At the beginning I wanted to add only one file as the solution but I remembered that a clean coder has to produce clean code every time and I want to get a clean coder, so I’ve split up the single file into multiple classes to separate the concerns.

So the solution consists of two files: the main entry point of the application called AppletRunner and the frame holding the applet called AppletHolder. These two files make your applet run as plain old Java Applications on your desktop.

The AppletRunner

The applet runner is the main entry point of the application. It contains the main method needed for every application to start. First I parse the arguments (in a really simple way) and configure and launch the AppletHolder frame with the applet.

The application needs one or three additional parameters:

  1. the full qualified name of the main applet class
  2. the width of the applet in pixels
  3. the height of the applet in pixels

2. and 3. are optional parameters, if not provided (or just one is provided) the default values are used: default width is 800 px, the default height is 600 px.

The name of the applet class is more interesting. This parameter is required because the application launches the applet based on this information.

The interesting part is this block of code:

final AppletHolder frame = new AppletHolder(args[0], width, height);
frame.setBounds(10, 10, width, height);
frame.setVisible(true);

This creates the frame and makes it visible.

The AppletHolder

This is the base of the application. This class initializes the applet based on the main class’ name provided along as startup parameter.

public class AppletHolder extends Frame {

As you can see, the holder class is really a frame.

public AppletHolder(String appletName, int width, int height) {
    super(appletName);
    try {
        final Applet applet = (Applet) Class.forName(appletName).newInstance();
        init(applet, width, height);
    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
        e.printStackTrace();
        System.exit(-1)
    }
}

The constructor initializes the frame with the title based on the applet’s name and tries to instantiate the applet itself based on the name provided. If it is successful, the initialization is called.

private void init(Applet applet, int width, int height) {
    add("Center", applet);
    applet.init();
    appletResize(width, height);
    setVisible(true);
    applet.start();
}

Here the applet is placed at the center of the frame and is initialized. And this was it. Now the applet runs in a Java Frame on your desktop without the need of a browser.

Applet parameters

Some applets run without parameters, some require parameters.

The example above only works for applets without parameters. But as I’ve told you already I will show how to extend the functionality to enable parameters.

To be able to handle parameters, we need to implement the AppletStub interface.

public class AppletHolder extends Frame implements AppletStub {

This makes the frame to implement some additional methods. If you are using an IDE go ahead and add the unimplemented methods.

The method we are interested in is getParameter. This takes a String as input and returns another String:

@Override
public String getParameter(String name) {
    if ("password".equals(name)) {
        return "secret password";
    }
    return null;
}

The implementation is quite simple: if the requested parameter is password the method returns a hard-coded answer. Naturally if you need to make this dynamic there are some solutions: get the parameters as command line arguments and pass along with the constructor and so on.

And one thing is missing: we have to add the stub implementation to the applet. The best was is to add it in the init method:

private void init(Applet applet, int width, int height) {
    applet.setStub(this);
    // the other init calls are omitted...
}

Conclusion

And this was it. It is simple but you can run applets locally which require parameters too — however currently only one-direction: from the frame to the applet.

For dynamic parameter-exchange (with JavaScript in the browser for example) I’ll prepare another article in the future where I’ll extend the functionality of the AppletRunner.

Source code

As most of the time, the sources are available at my GitHub account under the MIT license.

GHajba
 

Senior developer, consultant, author, mentor, apprentice.

I love to share my knowledge and insights what I achieve through my daily work which is not trivial — at least not for me.

Click Here to Leave a Comment Below 0 comments
%d bloggers like this: