FileDocCategorySizeDatePackage
JarFile.javaAPI DocJava SE 5 API16586Fri Aug 26 14:57:26 BST 2005java.util.jar

JarFile

public class JarFile extends ZipFile
The JarFile class is used to read the contents of a jar file from any file that can be opened with java.io.RandomAccessFile. It extends the class java.util.zip.ZipFile with support for reading an optional Manifest entry. The Manifest can be used to specify meta-information about the jar file and its entries.

Unless otherwise noted, passing a null argument to a constructor or method in this class will cause a {@link NullPointerException} to be thrown.

author
David Connelly
version
1.62, 06/30/05
see
Manifest
see
java.util.zip.ZipFile
see
java.util.jar.JarEntry
since
1.2

Fields Summary
private SoftReference
manRef
private JarEntry
manEntry
private JarVerifier
jv
private boolean
jvInitialized
private boolean
verify
private boolean
computedHasClassPathAttribute
private boolean
hasClassPathAttribute
public static final String
MANIFEST_NAME
The JAR manifest file name.
private static int[]
lastOcc
private static int[]
optoSft
private static char[]
src
private static String
javaHome
Constructors Summary
public JarFile(String name)
Creates a new JarFile to read from the specified file name. The JarFile will be verified if it is signed.

param
name the name of the jar file to be opened for reading
throws
IOException if an I/O error has occurred
throws
SecurityException if access to the file is denied by the SecurityManager


                                                                      
         
	this(new File(name), true, ZipFile.OPEN_READ);
    
public JarFile(String name, boolean verify)
Creates a new JarFile to read from the specified file name.

param
name the name of the jar file to be opened for reading
param
verify whether or not to verify the jar file if it is signed.
throws
IOException if an I/O error has occurred
throws
SecurityException if access to the file is denied by the SecurityManager

        this(new File(name), verify, ZipFile.OPEN_READ);
    
public JarFile(File file)
Creates a new JarFile to read from the specified File object. The JarFile will be verified if it is signed.

param
file the jar file to be opened for reading
throws
IOException if an I/O error has occurred
throws
SecurityException if access to the file is denied by the SecurityManager

	this(file, true, ZipFile.OPEN_READ);
    
public JarFile(File file, boolean verify)
Creates a new JarFile to read from the specified File object.

param
file the jar file to be opened for reading
param
verify whether or not to verify the jar file if it is signed.
throws
IOException if an I/O error has occurred
throws
SecurityException if access to the file is denied by the SecurityManager.

	this(file, verify, ZipFile.OPEN_READ);
    
public JarFile(File file, boolean verify, int mode)
Creates a new JarFile to read from the specified File object in the specified mode. The mode argument must be either OPEN_READ or OPEN_READ | OPEN_DELETE.

param
file the jar file to be opened for reading
param
verify whether or not to verify the jar file if it is signed.
param
mode the mode in which the file is to be opened
throws
IOException if an I/O error has occurred
throws
IllegalArgumentException if the mode argument is invalid
throws
SecurityException if access to the file is denied by the SecurityManager

	super(file, mode);
	this.verify = verify;
    
Methods Summary
public java.util.Enumerationentries()
Returns an enumeration of the zip file entries.

	final Enumeration enum_ = super.entries();
	return new Enumeration<JarEntry>() {
	    public boolean hasMoreElements() {
		return enum_.hasMoreElements();
	    }
	    public JarFileEntry nextElement() {
		ZipEntry ze = (ZipEntry)enum_.nextElement();
		return new JarFileEntry(ze);
	    }
	};
    
private byte[]getBytes(java.util.zip.ZipEntry ze)

	byte[] b = new byte[(int)ze.getSize()];
	DataInputStream is = new DataInputStream(super.getInputStream(ze));
	is.readFully(b, 0, b.length);
	is.close();
	return b;
    
public java.util.zip.ZipEntrygetEntry(java.lang.String name)
Returns the ZipEntry for the given entry name or null if not found.

param
name the jar file entry name
return
the ZipEntry for the given entry name or null if not found
throws
IllegalStateException may be thrown if the jar file has been closed
see
java.util.zip.ZipEntry

	ZipEntry ze = super.getEntry(name);
	if (ze != null) {
	    return new JarFileEntry(ze);
	}
	return null;
    
public synchronized java.io.InputStreamgetInputStream(java.util.zip.ZipEntry ze)
Returns an input stream for reading the contents of the specified zip file entry.

param
ze the zip file entry
return
an input stream for reading the contents of the specified zip file entry
throws
ZipException if a zip file format error has occurred
throws
IOException if an I/O error has occurred
throws
SecurityException if any of the jar file entries are incorrectly signed.
throws
IllegalStateException may be thrown if the jar file has been closed

        maybeInstantiateVerifier();
	if (jv == null) {
	    return super.getInputStream(ze);
	}
	if (!jvInitialized) {
	    initializeVerifier();
	    jvInitialized = true;
	    // could be set to null after a call to
	    // initializeVerifier if we have nothing to
	    // verify
	    if (jv == null)
		return super.getInputStream(ze);
	}

	// wrap a verifier stream around the real stream
	return new JarVerifier.VerifierStream(
	    getManifest(),
	    ze instanceof JarFileEntry ?
	    (JarEntry) ze : getJarEntry(ze.getName()),
	    super.getInputStream(ze),
	    jv);
    
public java.util.jar.JarEntrygetJarEntry(java.lang.String name)
Returns the JarEntry for the given entry name or null if not found.

param
name the jar file entry name
return
the JarEntry for the given entry name or null if not found.
throws
IllegalStateException may be thrown if the jar file has been closed
see
java.util.jar.JarEntry

	return (JarEntry)getEntry(name);
    
private java.util.jar.JarEntrygetManEntry()

     
	lastOcc = new int[128];
	optoSft = new int[10];
	lastOcc[(int)'c"]=1;
	lastOcc[(int)'l"]=2;
	lastOcc[(int)'s"]=5;
	lastOcc[(int)'-"]=6;
	lastOcc[(int)'p"]=7;
	lastOcc[(int)'a"]=8;
	lastOcc[(int)'t"]=9;
	lastOcc[(int)'h"]=10;
	for (int i=0; i<9; i++)
	    optoSft[i]=10;
	optoSft[9]=1;
    
	if (manEntry == null) {
	    // First look up manifest entry using standard name
	    manEntry = getJarEntry(MANIFEST_NAME);
            if (manEntry == null) {
                // If not found, then iterate through all the "META-INF/"
                // entries to find a match.
                String[] names = getMetaInfEntryNames();
                if (names != null) {
                    for (int i = 0; i < names.length; i++) {
                        if (MANIFEST_NAME.equals(
                                                 names[i].toUpperCase(Locale.ENGLISH))) {
                            manEntry = getJarEntry(names[i]);
                            break;
                        }
                    }
                }
            }
	}
	return manEntry;
    
public java.util.jar.ManifestgetManifest()
Returns the jar file manifest, or null if none.

return
the jar file manifest, or null if none
throws
IllegalStateException may be thrown if the jar file has been closed

	Manifest man = manRef != null ? manRef.get() : null;
	  
	if (man == null) {
	    JarEntry manEntry = getManEntry();
	    
	    // If found then load the manifest
	    if (manEntry != null) {
		if (verify) {
		    byte[] b = getBytes(manEntry);
 		    man = new Manifest(new ByteArrayInputStream(b));
		    if (!jvInitialized) {
		        jv = new JarVerifier(b);
		    }
		} else {
		    man = new Manifest(super.getInputStream(manEntry));
		}
		manRef = new SoftReference(man);
	    }
	}
	return man;
    
private native java.lang.String[]getMetaInfEntryNames()

booleanhasClassPathAttribute()

        if (computedHasClassPathAttribute) {
            return hasClassPathAttribute;
        }

        hasClassPathAttribute = false;
        if (!isKnownToNotHaveClassPathAttribute()) {
            JarEntry manEntry = getManEntry();
            if (manEntry != null) {
                byte[] b = new byte[(int)manEntry.getSize()];
                DataInputStream dis = new DataInputStream(
                                                          super.getInputStream(manEntry));
                dis.readFully(b, 0, b.length);
                dis.close();
 
                int last = b.length - src.length;
                int i = 0;
                next:       
                while (i<=last) {
                    for (int j=9; j>=0; j--) {
                        char c = (char) b[i+j];
                        c = (((c-'A")|('Z"-c)) >= 0) ? (char)(c + 32) : c;
                        if (c != src[j]) {
                            i += Math.max(j + 1 - lastOcc[c&0x7F], optoSft[j]);
                            continue next;
                        }
                    }
                    hasClassPathAttribute = true;
                    break;
                }
            }
        }
        computedHasClassPathAttribute = true;
        return hasClassPathAttribute;
    
private voidinitializeVerifier()

	ManifestEntryVerifier mev = null;

	// Verify "META-INF/" entries...
	try {
	    String[] names = getMetaInfEntryNames();
	    if (names != null) {
		for (int i = 0; i < names.length; i++) {
		    JarEntry e = getJarEntry(names[i]);
		    if (!e.isDirectory()) {
			if (mev == null) {
			    mev = new ManifestEntryVerifier(getManifest());
			}
			byte[] b = getBytes(e);
			if (b != null && b.length > 0) {
			    jv.beginEntry(e, mev);
			    jv.update(b.length, b, 0, b.length, mev);
			    jv.update(-1, null, 0, 0, mev);
			}
		    }
		}
	    }
	} catch (IOException ex) {
	    // if we had an error parsing any blocks, just
	    // treat the jar file as being unsigned
	    jv = null;
            verify = false;
	}

	// if after initializing the verifier we have nothing
	// signed, we null it out.

	if (jv != null) {

	    jv.doneWithMeta();
	    if (JarVerifier.debug != null) {
		JarVerifier.debug.println("done with meta!"); 
	    }

	    if (jv.nothingToVerify()) {
		if (JarVerifier.debug != null) {
		    JarVerifier.debug.println("nothing to verify!");
		}
		jv = null;
                verify = false;
	    }
	}
    
private booleanisKnownToNotHaveClassPathAttribute()

        // Optimize away even scanning of manifest for jar files we
        // deliver which don't have a class-path attribute. If one of
        // these jars is changed to include such an attribute this code
        // must be changed.
        if (javaHome == null) {
            javaHome = (String) AccessController.doPrivileged(
                new GetPropertyAction("java.home"));
        }
        String name = getName();
        String localJavaHome = javaHome;
        if (name.startsWith(localJavaHome)) {
            if (name.endsWith("rt.jar") ||
                name.endsWith("sunrsasign.jar") ||
                name.endsWith("jsse.jar") ||
                name.endsWith("jce.jar") ||
                name.endsWith("charsets.jar") ||
                name.endsWith("dnsns.jar") ||
                name.endsWith("ldapsec.jar") ||
                name.endsWith("localedata.jar") ||
                name.endsWith("sunjce_provider.jar")) {
                return true;
            }
        }
        return false;
    
private voidmaybeInstantiateVerifier()

        if (jv != null) {
            return;
        }

        if (verify) {
            String[] names = getMetaInfEntryNames();
            if (names != null) {
                for (int i = 0; i < names.length; i++) {
                    String name = names[i].toUpperCase(Locale.ENGLISH);
                    if (name.endsWith(".DSA") ||
                        name.endsWith(".RSA") ||
                        name.endsWith(".SF")) {
                        // Assume since we found a signature-related file
                        // that the jar is signed and that we therefore
                        // need a JarVerifier and Manifest
                        getManifest();
                        return;
                    }
                }
            }
            // No signature-related files; don't instantiate a
            // verifier
            verify = false;
        }