Java Web Start to the rescue

Find out how Java Web Start aids client-side deployment

Page 2 of 3

This simple example application illustrates some of JFC's features. It's worth noting that the networked application was launched by a single click and was decoupled from the browser (which would have restricted the user interaction).

Depending on the options set up for Java Web Start, launching the same networked application will create a desktop shortcut at the discretion of the user. Figure 3 shows the dialog box where the user can make that choice. Creation of the desktop shortcut happens only on Windows platforms.

This simple Hello World application was intended to drive home the concepts of Java Web Start. The Java Web Start installation provides demonstrations of applications that have a more advanced user interface; such applications are appropriately decoupled from the browser.

This application, however, does not perform any operations restricted by the sandbox. To illustrate more of Java Web Start's advantages, I'll next demonstrate an application that performs local disk access.

Java Web Start security

We just looked at a simple example; now, we will look at another simple example that performs some operations not permitted in the default sandbox environment. Trusted signed code can, however, leave the sandbox, as we'll see. As a basis, we will use some of the code I used in my earlier Java security articles. I've modified the Java program to exit when the window closes if invoked either as an application or using Java Web Start.

Here's the code, with modifications:

/**
  * By default, this raises a security exception as an applet.
  *
  * With JDK 1.2 appletviewer, 
  *  if you configure your system to grant applets signed by "Duke"
  *  and downloaded from the Java Software Website to write a file
  *  to your /tmp directory (or to the file named "C:\tmpfoo" on a 
  *  Windows system), then this applet can run.
  *  
  * @version JDK 1.2
  * @author  Marianne Mueller
  * @Modified by Raghavan Srinivas[Rags]
  */
import java.awt.*;
 import java.awt.event.*; 
import java.io.*;
import java.lang.*;
import java.applet.*;
public class writeFile extends Applet {
    String myFile = "/tmp/foo";
    File f = new File(myFile);
    DataOutputStream dos;
  public void init() {
    
    String osname = System.getProperty("os.name");
    if (osname.indexOf("Windows") != -1) {
      myFile="C:" + File.separator + "tmpfoo";
    }
  }
  public void paint(Graphics g) {
        try {
          dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(myFile),128));
          dos.writeBytes("Cats can hypnotize you when you least expect it\n");
          dos.flush();
          dos.close();
          g.drawString("Successfully wrote to the file named " + myFile + " -- go take a look at it!", 10, 10);
        }
        catch (SecurityException e) {
          g.drawString("writeFile: caught security exception", 10, 10);
        }
        catch (IOException ioe) {
                g.drawString("writeFile: caught i/o exception", 10, 10);
        }
   }
    public static void main(String args[]) {
        Frame f = new Frame("writeFile");
        writeFile       writefile = new writeFile();
        writefile.init();
        writefile.start();
       f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {System.exit(0);}    });
        f.add("Center", writefile);
        f.setSize(300, 100);
        f.show();
    }
}

Copy the writeFile.class and writeFile.class (the class generated as a result of the anonymous inner class corresponding to the WindowAdapter) into a subdirectory and generate the signed jar file:

D:\rags\sign>signtool -d . -Z writeFile.jar -k "Raghavan N. Srinivas's Thawte Consulting cc ID" writeFile using certificate directory: .
Generating writeFile/META-INF/manifest.mf file..
--> writeFile.class
adding writeFile/writeFile.class to writeFile.jar...(deflated 44%)
--> writeFile.class
adding writeFile/writeFile.class to writeFile.jar...(deflated 28%)
Generating zigbert.sf file..
Enter Password or Pin for "Communicator Certificate DB":
adding writeFile/META-INF/manifest.mf to writeFile.jar...(deflated 30%)
adding writeFile/META-INF/zigbert.sf to writeFile.jar...(deflated 37%)
adding writeFile/META-INF/zigbert.rsa to writeFile.jar...(deflated 28%)
tree "writeFile" signed successfully

The .JNLP file used with this application illustrates how it's possible for signed code to execute outside the default sandbox environment provided by Java Web Start. The appropriate code is illustrated in boldface:

<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for WriteFile Application -->
<jnlp spec="1.0+"
  codebase="http://anvil:8001/"
  href="writeFile.jnlp">
    <information>
      <title>writeFile Demo Application</title>
      <vendor>Rags</vendor>
      <homepage href="docs/help.html"/>
      <description>writeFile Demo Application</description>
      <description kind="short">A demo of writeFile app. </description>
      <icon href="images/swingset2.jpg"/>
      <offline-allowed/>
    </information>
   <security> 
      <all-permissions/> 
    </security> 
    <resources>
      <j2se version="1.3"/>
      <jar href="writeFile.jar"/>
    </resources>
      <application-desc main-class="writeFile"/>
</jnlp>

Provide an HTML file to launch the application as well. Now the application is ready to run. If the code has been signed and provisioned correctly on the server, the window shown in Figure 4 should pop up. The window will give the user the choice of continuing to run the application or to terminate it.

Figure 4. Dialog popup for running signed applications. Click on thumbnail to view full-size image. (35 KB)

Clicking on the Start button will cache the signer locally, and the dialog popup will not appear for subsequent invocations of the same application. If you don't want to trust the signer subsequently, the local cache can be cleared using the Java Web Start Application Manager, as you will see later.

So far, you have seen how Java Web Start can be used without any programming. The JNLP and Java Web Start API provide a set of classes for user friendly of client-side applications. For example, even though code is unsigned, it may still be used for local disk access with the user's consent. This is somewhat akin to the Save As option and manipulating cookies available in most browsers.

The Java Web Start APIs deal with this limited set of out-of-the-sandbox operations in a controlled manner, by limiting interaction to the system explicitly via dialog boxes.

Use the JNLP API

We just saw how an application can access a local filesystem by signing the code. This can be accomplished by using the API as well.

I will discuss only some API details and use some of those to modify the writeFile example we discussed earlier. These APIs come with the developers' pack, which needs to be installed as a Java extension to successfully compile the code and subsequently generate the .jar files. Rather than installing the extensions, you could also include jnlp.jar in the classpath. Refer to the Resources section below for a more detailed explanation of the API. Examples of the API are:

  • ClipBoardService: Includes methods for accessing the shared system-wide clipboard
  • FileContents: Encapsulates the name and contents of a file
  • FileOpenService: Allows the user to choose a file from the local filesystem
  • FileSaveService: Allows the user to save a file to the local filesystem
  • JNLPRandomAccessFile: Includes methods for both reading and writing to a random access file
  • PersistenceService: Includes methods for storing data locally on the client system
  • PrintService: Includes methods to access printing functions

Many of these APIs apply even when run in an untrusted environment. That is, the code does not have to be signed and trusted by the user for the operation's successful completion. In some cases, Java Web Start will warn the user of the potential security risk of letting an untrusted application access potentially confidential information.

Let's dissect some of these APIs further. The FileOpenService, for instance, supports methods like openFileDialog() and openMultiFileDaialog(), which select a single file or multiple files, respectively. They return FileContents and FileContents[], respectively. Likewise, FileSaveService supports methods like SaveAsFileDialog and SaveFileDialog. As you might expect, these APIs interact with the user via dialog boxes explicitly.

In the example below, we will look at the earlier application that was converted to write to a file picked by the user, rather than to /tmp/foo. The application uses some of the APIs mentioned above. This application need not be signed:

/**
  * This program uses JNLP API to write to a file
  * that is selected by the user
  *  
  * @author  Rags Srinivas
  */
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.*;
import java.applet.*;
import javax.jnlp.*;
public class writeFile extends Applet {
    static FileOpenService fos;
    static JNLPRandomAccessFile raf;
    static FileContents fc;
    static int count=0;
    public void init() {
    
        // Look up a FileOpenService
        try { 
            fos = (FileOpenService)ServiceManager.lookup("javax.jnlp.FileOpenService"); 
        } catch (UnavailableServiceException e) { 
            fos = null;
        } 
        if (fos != null) { 
            try {                
                // get a file with FileOpenService
                fc = fos.openFileDialog(null, null);
                // If valid file contents
                if (fc != null) {
                    long grantedLength = fc.getLength(); 
                    if (grantedLength + 1024 > fc.getMaxLength()) { 
                        // attempt to increase the maximum file size defined by 
                        // the client 
                        grantedLength = fc.setMaxLength(grantedLength + 1024); 
                    }
                    // Open the file for read write
                    raf = fc.getRandomAccessFile("rw");
                } 
             } catch (Exception e) { 
                 e.printStackTrace(); 
             } 
         } 
    }
    public void paint(Graphics g) {
        String msg="JWS can stun you! ";
        if (fos != null && fc != null) {
            try {
                // seek to the beginning and write 
                raf.seek(0); 
                raf.writeBytes(msg + count++);
            } catch (Exception e) { 
                e.printStackTrace(); 
            }
        } 
    }
    public void destroy() {
        if (fos != null && fc != null) {
            try {
                // close the file
                raf.close(); 
            } catch (Exception e) { 
                e.printStackTrace(); 
            }                   
        }
    }    
    public static void main(String args[]) {
        Frame f = new Frame("writeFile");
        final writeFile writefile = new writeFile();
        writefile.init();
        writefile.start();
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) { writefile.destroy(); System.exit(0);}    });
        f.add("Center", writefile);
        f.setSize(300, 100);
        f.show();
    }
}

In the init() method, the file the user picks is opened as a random file for both read and write. The paint() method writes a fixed message appended with an incrementing count. Finally, the destroy() method closes the file. Invoking this application will bring up a dialog box through which the user can interact to select a local file to write to.

Note that the user explicitly picks the output file; no other file can be accidentally or maliciously overwritten. This means that the application securely modifies the local filesystem.

Although the code is written to work both as an applet and an application, this functionality will not be available in the applet environment since the JNLP APIs will not be available there.

The final piece in Java Web Start I will demonstrate is the application manager.

Java Web Start Application Manager

You can employ the Java Web Start Application Manager for a variety of administrative and related tasks. You can set the http proxy, view and start applications, create desktop shortcuts, and set other advanced preferences. The main window is illustrated in Figure 5.

Figure 5.Java Web Start Application Manager. Click on thumbnail to view full-size image. (35 KB)
Figure 6. Java Web Start Application Manager preferences. Click on thumbnail to view full-size image. (40 KB)
Figure 7. Java console. Click on thumbnail to view full-size image. (18 KB)

You can manipulate other preferences as well, as illustrated in Figure 6. Examples include clearing the local cache, setting options on desktop shortcuts, and so on.

Debug Java Web Start applications

Using the application manager, it is possible to log the output or display the Java console by appropriate options in Preferences/Advanced. The Java console window is shown in Figure 7.

Combine servlets/JSPs, applets, and Java Web Start

Having shown Java Web Start's benefits I'll now turn to applets running in a plug-in environment and clients employing servlet/JSP-supported markup languages.

Consider an application that can be browsed by a variety of clients but is typically set up and administered on a desktop. In such a situation, it's possible to use servlets/JSP to support browsing, while the setup or administration functions are done using Java Web Start to provide a rich user interface.

Related:
| 1 2 3 Page 2