Java JNLP
Java JNLP
JNLP*
By John Zukowski
Introduction to JNLP ....................................................................................................... 3
Getting Started .................................................................................................................. 3
The JNLP API ................................................................................................................... 5
The Source Code ............................................................................................................... 9
Conclusion ....................................................................................................................... 13
Resources ......................................................................................................................... 14
About the Author ............................................................................................................ 14
Introduction to JNLP
The Java* Network Launch Protocol (JNLP*) is the standard Java deployment option for delivering rich client-side
applications. Through implementations such as Sitraka’s DeployDirector* or the open source OpenJNLP* effort, you can
deploy Java applets and applications through the browser to be executed outside the browser. Once deployed, your program
can be run without bringing up a browser or downloading the classes again, though the system will check for updates to the
program.
This paper discusses packaging Web applications using the javax.jnlp package, which defines the JNLP API. It provides a
collection of classes and interfaces for working locally within the untrusted client environment provided by DeployDirector,
OpenJNLP, Java Web Start*, and others.
Getting Started
The JNLP API is actually rather small. It consists of one class, twelve interfaces, and an exception. The class,
ServiceManager, is used to look up services, which are a majority of the interfaces. Use these interfaces to access the
system clipboard, read or write files, or print. Each attempted request triggers a security warning the user must confirm
before the action succeeds. Standard Java code signing mechanisms also are supported for activities such as accessing a
third-party Web server, but they are not part of the JNLP API.
Notice that since the program is unsigned, the app displays a yellow warning bar across the bottom, similar to running an
unsigned applet.
Here is the source code for the user interface:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
JTextArea textArea;
public Editor() {
super("Editor");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container contentPane = getContentPane();
textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
contentPane.add(pane, BorderLayout.CENTER);
setSize(300, 300);
}
Feel free to add menu mnemonics or other convenience features as you wish to this functional interface.
Packaging
The next step is to package the application for Java Web Start (or whichever JNLP implementation you use). Since Java Web
Start is installed automatically on Windows* with the Java 2 SDK, version 1.4 release (and separately installable for Linux*
and Solaris* users), we’ll use it for this exercise.
Packaging for Java Web Start involves creating a JAR file with the program’s classes and creating an XML file (named with
a jnlp extension) that describes the application. Opening the JNLP file through the browser kicks off Java Web Start.
Assuming you are working in a directory just for this project, create the JAR file with the following command:
Be sure that the codebase matches the location from which you are loading the file. If you are placing the application on a
Web server, replace the file: URL with an http: URL. Another condition of placing the application on a Web server is
that the server must report the proper MIME type for the application loader. For Tomcat* 4.0 and many of the latest releases
of Web and application servers, this is preconfigured. Otherwise, be sure to map the .jnlp extension to the
application/x-java-jnlp-file MIME type. How to do this is dependent on the server you are using.
Load the Editor.jnlp file in your browser to bring up the application interface shown previously.
The JNLP API is comprised of eight services, each with its own interface:
• BasicService
• ClipboardService
• DownloadService
• ExtensionInstallerService
• FileOpenService
• FileSaveService
• PersistenceService
• PrintService
•
Implementations of these interfaces offer access to the client machine. When such access is needed, even in an untrusted
execution environment, the user is prompted for permission before access is granted. The prompt isn’t for global access but
granted on a very restricted basis. For instance, with FileOpenService, the user is granted access to read a file on the client
machine but is restricted to selecting the file from a file dialog window.
The ServiceManager class controls use of the JNLP services. Use the lookup() method of the ServiceManager
to lookup a service by fully qualified interface name, and an implementation is returned for you to use:
In the case of the FileOpenService, a single or multi-select file dialog box is shown. After selection, you can get the
InputStream associated with the selection to read. The following security prompt appears prior to the dialog:
Let’s add this behavior to the text editor to demonstrate.
import javax.jnlp.*;
Then create and add the appropriate listener. Look up the appropriate service within the listener. Next, use the service
returned to prompt for an open file selection. In this case, the method is openFileDialog(), which automatically deals
with the security advisory. This then returns a FileContents object from which to read the contents to display in the text
area.
Once you’ve added this to the Editor.java file, recompile the file and remember to recreate the JAR file before running
the application. Depending upon your platform, you may notice that the file dialog can opt to not offer the use of the file
extensions provided.
Working our way through the remaining “File” menu options, saving a file is similar to reading, but is actually simpler. You
don’t actually have to write the data, only provide an InputStream that contains the bytes to save. Here’s the core part of
that code:
// Convert to InputStream
ByteArrayInputStream input =
new ByteArrayInputStream(bytes);
// Lookup service
FileSaveService fileSaveService = (FileSaveService)
ServiceManager.lookup("javax.jnlp.FileSaveService");
All of the menu options work in a similar fashion: look up the service, and then use it. In the case of the PrintService,
you must implement the java.awt.print.Printable or java.awt.print.Pageable interfaces. As this isn’t an
exercise in printing with Java, you’ll provide a simple implementation that just prints a screen dump of the JTextArea. If
you want to paginate the text, you’ll find that the java.awt.font.TextLayout and
java.awt.font.LineBreakMeasurer classes are valuable.
import java.awt.print.*;
. . .
public class Editor extends JFrame
implements Printable {
. . .
public int print(Graphics g,
PageFormat pageFormat, int pageIndex)
throws PrinterException {
int x = (int)pageFormat.getImageableX();
int y = (int)pageFormat.getImageableY();
g.translate(x, y);
if (pageIndex == 0) {
textArea.paint(g);
return Printable.PAGE_EXISTS;
} else {
return Printable.NO_SUCH_PAGE;
}
}
The actual printing code behind the menu is just look up PrintService and call print(), passing in the Printable
implementor.
// Lookup service
PrintService printService = (PrintService)
ServiceManager.lookup("javax.jnlp.PrintService");
That leaves the Edit menu and the Cut, Copy, and Paste operations. Here, the service of interest is the
ClipboardService. Other than looking up the service, the rest is just an understanding of clipboard access and the
java.awt.datatransfer package.
The Cut and Copy operations are the same as far as the ClipboardService goes:
// Put on Clipboard
String selection = textArea.getSelectedText();
StringSelection data = new StringSelection(selection);
clipboardService.setContents(data);
The Paste operation requires a little bit of work to get the right DataFlavor.
import java.awt.datatransfer.*;
Depending upon the operation performed, the prompt to the user indicates whether read-only or write access is desired:
Unless the user checks “Do not show this advisory again,” every access to the system clipboard will require confirmation
from the security advisory.
JTextArea textArea;
public Editor() {
super("Editor");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container contentPane = getContentPane();
textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
contentPane.add(pane, BorderLayout.CENTER);
// Read in file
InputStreamReader isr =
new InputStreamReader(is);
BufferedReader reader =
new BufferedReader(isr);
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
String line;
while ((line = reader.readLine()) != null) {
writer.println(line);
}
// Close streams
writer.close();
reader.close();
// Convert to InputStream
ByteArrayInputStream input =
new ByteArrayInputStream(bytes);
// Lookup service
FileSaveService fileSaveService =
(FileSaveService)ServiceManager.lookup(
"javax.jnlp.FileSaveService");
// Put on Clipboard
String selection =
textArea.getSelectedText();
StringSelection data =
new StringSelection(selection);
clipboardService.setContents(data);
setSize(300, 300);
}
Editor.jnlp
Note: If you want debug messages printed to System.out/err, enable the Java Console from the application manager
specific to your JNLP implementation. For Java Web Start, this is available from
http://java.sun.com/products/javawebstart/demos.html.
Conclusion
The JNLP API is a small but powerful API to add to your bag of programming tricks. Through the simple service lookup
method, you’re given access from an untrusted program directly to the end user’s desktop, without the security risk. While
code signing is certainly available through Java Web Start, for many tasks, the associated hassles are not required given the
controlled limited access available through the classes of the javax.jnlp package.
Resources
JNLP API javadoc**
Java Web Start**
Java Web Start Developer’s Guide**
DeployDirector**
OpenJNLP**
Tomcat**
** Intel provides Internet links in this document as a convenience to its customers. The linked sites are independent of Intel and Intel does not
warrant and cannot be responsible for their contents.