| ## Java 1.1 Unleashed # - 36 - JAR Basics by Mike Fletcher IN THIS CHAPTER What Are JAR Files? Manipulating JAR Files with jar An Overview of java.util.zip Using JAR Files Java Archive (JAR) files provide a way to bundle all the resources for an applet into a single file. This chapter introduces JAR files, explains how you can create them, describes the `java.util.zip` package, and provides a quick example of how to use JAR files with applets. More detailed information on JAR-related topics is given in Chapter 37, "Code Signing and JAR Security." ## What Are JAR Files? In versions of the JDK before version 1.1, if an applet was made up of several different class files or had resources such as GIFs or audio files, you had to download each resource individually. In addition to forcing the user of the applet to wait while the applet's pieces downloaded, this arrangement put an extra load on the HTTP server. To address this problem, Sun introduced JAR files. Based on the widely used ZIP file format developed by PKWare, a JAR file allows multiple resources (Java class files, graphics files, and others) to be bundled into a single, compressed archive file. In addition to making the server's job easier, applets and resources download quicker when they are compressed. A new package, `java.util.zip`, contains classes to manipulate JAR files (as well as normal ZIP files). You can simply store files in a JAR file, or you can compress them before storing to save space. JAR files include a manifest file in the archive. This manifest (named `META-INF/MANIFEST.MF`) gives message digests of the component files in the archive. Additionally, digital signatures of component files can be included in the `META-INF` directory of the archive. Code signed by a trusted entity can be granted extra privileges (such as writing files). Code signing and related issues are covered in detail in Chapter 37. ## Manipulating JAR Files with jar Included with the JDK 1.1 is a tool to create and manipulate JAR files. This tool is called, logically enough, `jar`. The `jar` tool runs from the DOS command line or UNIX shell prompt (represented in the examples below by the `%` character). The following examples show how to use `jar` to create a JAR file, how to list the contents of an archive, and how to extract a file from an archive. In all cases, two extra options can be used with `jar` to change how it operates:
Option | Description
`v` | Tells `jar` to generate verbose output about the actions it is performing.
`f` | Specifies the filename to manipulate. If this option is not given, `jar` writes to standard output.
If you happen to forget how to use `jar`, you can run it with no arguments to generate a usage listing. NOTE: Because JAR files are stored in the standard ZIP format, you do not have to use `jar` to create JAR files. You can use any application that can create ZIP files--as long as you generate your own manifest file and name it correctly (`META-INF/MANIFEST.MF`). You can find information about the manifest and signature file formats at this site: `http://www.javasoft.com/products/JDK/1.1/docs/guide/jar/manifest.html` Free ZIP and unZIP programs are available from the Info-ZIP group. Source code and binaries for many platforms are available from this site: `http://www.cdrom.com/pub/infozip/Info-Zip.html` ### Creating a JAR File To create an archive, you use `jar` with the `c` flag. Suppose that we want to create a JAR file with three files: `sampleApplet.class`, a Java class file; `sampleGraphic.gif`, an image file; and `sampleSound.au`, an audio file. The following command places these three files into an archive named `sample.jar`. The options `cvf` specify that we want to create an archive, we want verbose output, and the archive filename should be `sample.jar`.
    % jar cvf sample.jar sample.jar sampleApplet.class sampleGraphic.gif sampleSound.au
Here's what `jar` shows you as it's creating the archive:
    adding: sampleApplet.class in=4480 out=2065 deflated 53.0%
    adding: sampleGraphic.gif in=506 out=419 deflated 17.0%
    adding: sampleSound.au in=5529 out=1088 deflated 80.0%
For each file, `jar` specifies the input size before compression and the output size after compression, as well as a ratio showing how well the file was compressed. ### Listing the Contents of a JAR File Next, let's list the contents of the archive file we just created. The `t` option tells `jar` that we want a table of contents for the JAR file; the `vf` options specify verbose mode and the filename for which we want information:
    % jar tvf sample.jar
Here's the output from `jar`:
       402 Tue Feb 18 23:12:10 EST 1997 META-INF/MANIFEST.MF
      4480 Mon Feb 17 02:03:46 EST 1997 sampleApplet.class
       506 Tue Feb 18 22:24:52 EST 1997 sampleGraphic.gif
      5529 Mon Feb 17 00:16:02 EST 1997 sampleSound.au
Notice that there is an extra file named `META-INF/MANIFEST.MF` in the JAR archive file. This is a manifest of all the files contained in the archive and a message digest of the contents of each file (see Chapter 37, "Code Signing and JAR Security," for more information about message digests). The `jar` tool automatically generates a manifest file; alternatively, you can generate one yourself and pass the `m` flag to `jar` when you create the archive. ### Extracting a File from a JAR File Now let's extract `sampleGraphic.gif` from the `sample.jar` file. In the following command, the `vf` options are the same as they were in the preceding section (verbose mode and the filename from which you want to extract a file). The `x` option specifies that we want to extract files. If no extra arguments are given, `jar` extracts the entire contents of the archive. If arguments are given after the archive name, `jar` takes those as the names of the files to extract.
    % jar xvf sample.jar sampleGraphic.gif
Here's the response from `jar` concerning the extraction request:
    extracted: sampleGraphic.gif in=419 out=506 inflated 17.0%
## An Overview of java.util.zip The `java.util.zip` package contains several classes that facilitate the manipulation of compressed files. ### The ZipFile Class The `ZipFile` class provides a way to read the contents of a ZIP archive. There are two constructors: one that takes a `String` specifying the filename of the archive to open and one that takes a `java.io.File` object. The `getName()` method returns the path name of the ZIP file represented by the `ZipFile` object. Two methods are provided to obtain `ZipEntry` objects representing the contents of the ZIP file. The `getEntry()` method takes a `String` and returns a `ZipEntry` for the corresponding file; it returns `null` if no such file exists in the archive. The `entries()` method returns a `java.util.Enumeration` of `ZipEntry` objects for all the entries in the ZIP file. The `getInputStream()` method is used to obtain an `InputStream` for the entry represented by the `ZipEntry` given as a parameter. ### The ZipEntry Class Each file in a ZIP archive can be represented by a `ZipEntry` object. `ZipEntry` objects can be obtained for an existing file from a `ZipFile` or `ZipInputStream` object; they can also be created when you make a new ZIP archive with a `ZipOutputStream`. The `ZipEntry` class provides methods to retrieve information about the entry (for example, the filename, the compressed and uncompressed size of the file, and the compression method used for the file). The `isDirectory()` method is provided to determine whether the entry in question is a normal file or a directory. ### ZIP Stream Classes In addition to the `ZipFile` class, the `java.util.zip` package has two stream classes that handle compressed data. The stream classes in `java.util.zip` extend either `InflaterInputStream` or `DeflatorOutputStream` as appropriate. These two filtered streams provide a generic interface for handling compressed data. `ZipInputStream` reads data in the ZIP format from an `InputStream`. The `getNextEntry()` method returns a `ZipEntry` for the next component in the ZIP file and places the stream at the beginning of the data for that component. The `closeEntry()` method closes the current entry and advances the stream to return the next entry in the archive. Both methods throw a `ZipException` if a ZIP-related exception occurs. The `ZipOutputStream` provides `OutputStream` functionality for writing compressed data. The `putNextEntry()` method takes a `ZipEntry` as a parameter. A new entry is created in the ZIP file and any data written to the stream goes to the current entry. Two methods are provided to control the compression used to store entries: `setMethod()` takes as a parameter either `ZipOutputStream.DEFLATED` (to specify that the next entries should be compressed) or `ZipOutputStream.STORED` (to specify that any subsequent entries should simply be stored with no compression). The `setLevel()` method takes an integer from `0` to `9`, inclusive, with higher numbers indicating more compression (which takes longer to compress). The `setComment()` method allows the ZIP file comment to be set. ### GNU Zip Stream Classes In addition to classes for the ZIP compression format, the `java.util.zip` package provides two classes that support reading and writing files in the GNU Zip format. GNU Zip is a widely used compression format for UNIX. Unlike the ZIP format, the GNU Zip format handles only one file at a time, rather than multiple files and a directory structure. GNU Zip is most often used as a replacement for the UNIX `compress` utility, so there is no `getNextEntry()` method for the `GZIPInputStream` class. In addition, the `GZIPOutputStream` has no way to specify filenames for entries. ## Using JAR Files A new attribute has been added to the HTML `<applet>` tag: `archives`. This tag specifies one or more JAR files that should be downloaded with the applet (obviously, these JAR files contain components needed by the applet). You should still specify the `code` attribute, even if you give the `archives` attribute because `code` is used as the name of the applet class to load. Whenever the applet requests a class, image, or sound file, the archives specified are searched first. If the necessary resource is not contained in one of the JAR files downloaded, the applet contacts the server and searches for the resource as it did with the JDK version 1.0.2. You can specify multiple archive files by separating the filenames with `+` (a plus sign). A sample applet tag is shown in Listing 36.1. #### Listing 36.1. A sample <applet> tag using JAR files.
    <applet code="sampleApplet.class"
        archives="sample.jar + icons.jar + commonClasses.jar"
        width="550"
        height="300">
    <param name="animal" value="lemur">
    <param name="server" value="qa.nowhere.com">
    </applet>
## Summary JAR files provide a way to simplify applet distribution. Along with the new code-signing facilities, JAR files should greatly increase the usefulness of applets by making them easier to distribute and allowing trusted code to step outside the narrow limits of the sandbox. Additionally, the `java.util.zip` package provides support for manipulating ZIP and GNU Zip archives in any Java program.
| ©Copyright, Macmillan Computer Publishing. All rights reserved.