15.13 JarURLConnection
Applets often store their
.class files in a JAR archive, which bundles all the
classes in one package that still maintains the directory hierarchy
needed to resolve fully qualified class names like
com.macfaq.net.QueryString. Furthermore, since the
entire archive is compressed and can be downloaded in a single HTTP
connection, it requires much less time to download the
.jar file than to download its contents one file
at a time. Some programs store needed resources such as sounds,
images, and even text files inside these JAR archives. Java provides
several mechanisms for getting the resources out of the JAR archive,
but the one that we'll address here is the
jar URL. The JarURLConnection
class supports URLs that point inside JAR archives:
public abstract class JarURLConnection extends URLConnection// Java 1.2A jar URL starts with a normal URL that points
to a JAR archive, such as http://www.cafeaulait.org/network.jar or
file:///D%7C/javafaq/network.jar. Then the
protocol jar: is prefixed to this URL. Finally,
!/ and the path to the desired file inside the
JAR archive are suffixed to the original URL. For example, to find
the file com/macfaq/net/QueryString.class inside
the previous .jar files, you'd
use the URLs
jar:http://www.cafeaulait.org/network.jar!/com/macfaq/net/QueryString.class
or
jar:file://D%7C/javafaq/network.jar!/com/macfaq/net/QueryString.class.
Of course, this isn't limited simply to Java
.class files. You can use
jar URLs to point to any kind of file that
happens to be stored inside a JAR archive, including images, sounds,
text, HTML files, and more. If the path is left off, the URL refers
to the entire JAR archive, e.g.,
jar:http://www.cafeaulait.org/network.jar!/ or
jar:file:///D%7C/javafaq/network.jar!/.Web browsers don't
understand jar URLs, though.
They're used only inside Java programs. To get a
JarURLConnection, construct a
URL object using a jar URL
and cast the return value of its openConnection() method to
JarURLConnection. Java downloads the entire JAR
archive to a temporary file, opens it, and positions the file pointer
at the beginning of the particular entry you requested. You can then
read the contents of the particular file inside the JAR archive using
the InputStream returned by
getInputStream(
). For example:
try {Besides the usual methods of the URLConnection
//Open the URLConnection for reading
URL u = new URL(
"jar:http://www.cafeaulait.org/course/week1.jar!/week1/05l");
URLConnection uc = u.openConnection( );
InputStream in = uc.getInputStream( );
// chain the InputStream to a Reader
Reader r = new InputStreamReader(in);
int c;
while ((c = r.read( )) != -1) {
System.out.print((char) c);
}
}
catch (IOException ex) {
System.err.println(ex);
}
class that
JarURLConnection inherits,
this class adds eight new methods, mostly to return information about
the JAR archive itself. These are:
public URL getJarFileURL( ) // Java 1.2The getJarFileURL() method is the
public String getEntryName( ) // Java 1.2
public JarEntry getJarEntry( ) throws IOException // Java 1.2
public Manifest getManifest( ) throws IOException // Java 1.2
public Attributes getAttributes( ) throws IOException // Java 1.2
public Attributes getMainAttributes( ) throws IOException // Java 1.2
public Certificate[] getCertificates( ) throws IOException // Java 1.2
public abstract JarFile getJarFile( ) throws IOException // Java 1.2
simplest. It merely returns the URL of the jar
file being used by this connection. This generally differs from the
URL of the file in the archive being used for this connection. For
instance, the jar file URL of
jar:http://www.cafeaulait.org/network.jar!/com/macfaq/net/QueryString.class
is http://www.cafeaulait.org/network.jar. The
getEntryName( ) returns the other part of the
jar URL; that is, the path to the file inside
the archive. The entry name of
jar:http://www.cafeaulait.org/network.jar!/com/macfaq/net/QueryString.class
is com/macfaq/net/QueryString.class.The getJarFile( ) method returns
a java.util.jar.JarFile object that you can use to
inspect and manipulate the archive contents. The
getJarEntry( ) method returns
a java.util.jar.JarEntry object for the particular
file in the archive that this URLConnection is
connected to. It returns null if the URL points to a whole JAR
archive rather than a particular entry in the archive.Much of the functionality of both JarFile and
JarEntry is duplicated by other methods in the
JarURLConnection class; which to use is mostly a
matter of personal preference. For instance, the
getManifest( ) method returns
a java.util.jar.Manifest object representing the
contents of the JAR archive's manifest file. A
manifest file is included in the archive to supply
metainformation about the contents of the archive, such as which file
contains the main( ) method and which classes are
Java beans. It's called
MANIFEST.MF and placed in the
META-INF directory; its contents typically look
something like this:
Manifest-Version: 1.0The name-value pairs associated with each entry are called the
Required-Version: 1.0
Name: com/macfaq/net/FormPoster.class
Java-Bean: true
Last-modified: 10-21-2003
Depends-On: com/macfaq/net/QueryString.class
Digest-Algorithms: MD5
MD5-Digest: XD4578YEEIK9MGX54RFGT7UJUI9810
Name: com/macfaq/net/QueryString.class
Java-Bean: false
Last-modified: 5-17-2003
Digest-Algorithms: MD5
MD5-Digest: YP7659YEEIK0MGJ53RYHG787YI8900
attributes of that entry. The name-value pairs
not associated with any entry are called the main
attributes of the archive. The getAttributes() method returns a
java.util.jar.Attributes object representing the
attributes that the manifest file specifies for this
jar entry, or null if the URL
points to a whole JAR archive. The getMainAttributes(
) method returns a
java.util.jar.Attributes object representing the
attributes that the manifest file specifies for the entire JAR
archive as a whole.Finally, the getCertificates() method returns an
array of digital signatures (each represented as a
java.security.cert.Certificate object) that apply
to this jar entry, or null if
the URL points to a JAR archive instead of a particular entry. These
are actually read from separate signature files for each
jar entry, not from the manifest file. Unlike
the other methods of JarURLConnection,
getCertificates( ) can be called only after the
entire input stream for the jar URL has been
read. This is because the current hash of the data needs to be
calculated, which can be done only when the entire entry is
available.More details about the java.util.jar package, JAR
archives, manifest files, entries, attributes, digital signatures,
how this all relates to Zip files and Zip and JAR streams, and so
forth can be found on Sun's web site at http://java.sun.com/j2se/1.4.2/docs/guide/jar/
or in Chapter 9 of my book, Java I/O
(O'Reilly).