Package java.util.jar

Source Code of java.util.jar.JarFile

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package java.util.jar;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.harmony.archive.util.Util;

/**
* JarFile is used to read jar entries and their associated data from jar files.
*
* @see JarInputStream
* @see JarEntry
*/
public class JarFile extends ZipFile {

    public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; //$NON-NLS-1$

    static final String META_DIR = "META-INF/"; //$NON-NLS-1$

    private Manifest manifest;

    private ZipEntry manifestEntry;

    JarVerifier verifier;

    static final class JarFileInputStream extends FilterInputStream {
        private long count;

        private ZipEntry zipEntry;

        private JarVerifier verifier;

        private JarVerifier.VerifierEntry entry;

        private MessageDigest digest;

        JarFileInputStream(InputStream is, ZipEntry ze, JarVerifier ver) {
            super(is);
            if (ver != null) {
                zipEntry = ze;
                verifier = ver;
                count = zipEntry.getSize();
                entry = verifier.initEntry(ze.getName());
                if (entry != null) {
                    digest = entry.digest;
                }
            }
        }

        @Override
        public int read() throws IOException {
            int r = super.read();
            if (entry != null) {
                if (r != -1) {
                    digest.update((byte) r);
                    count--;
                }
                if (r == -1 || count <= 0) {
                    JarVerifier.VerifierEntry temp = entry;
                    entry = null;
                    verifier.verifySignatures(temp, zipEntry);
                }
            }
            return r;
        }

        @Override
        public int read(byte[] buf, int off, int nbytes) throws IOException {
            int r = super.read(buf, off, nbytes);
            if (entry != null) {
                if (r != -1) {
                    int size = r;
                    if (count < size) {
                        size = (int) count;
                    }
                    digest.update(buf, off, size);
                    count -= r;
                }
                if (r == -1 || count <= 0) {
                    JarVerifier.VerifierEntry temp = entry;
                    entry = null;
                    verifier.verifySignatures(temp, zipEntry);
                }
            }
            return r;
        }

        @Override
        public long skip(long nbytes) throws IOException {
            long cnt = 0, rem = 0;
            byte[] buf = new byte[4096];
            while (cnt < nbytes) {
                int x = read(buf, 0,
                        (rem = nbytes - cnt) > buf.length ? buf.length
                                : (int) rem);
                if (x == -1) {
                    return cnt;
                }
                cnt += x;
            }
            return cnt;
        }
    }

    /**
     * Create a new JarFile using the contents of file.
     *
     * @param file
     *            java.io.File
     * @exception java.io.IOException
     *                If the file cannot be read.
     */
    public JarFile(File file) throws IOException {
        this(file, true);
    }

    /**
     * Create a new JarFile using the contents of file.
     *
     * @param file
     *            java.io.File
     * @param verify
     *            verify a signed jar file
     * @exception java.io.IOException
     *                If the file cannot be read.
     */
    public JarFile(File file, boolean verify) throws IOException {
        super(file);
        if (verify) {
            verifier = new JarVerifier(file.getPath());
        }
        readMetaEntries();
    }

    /**
     * Create a new JarFile using the contents of file.
     *
     * @param file
     *            java.io.File
     * @param verify
     *            verify a signed jar file
     * @param mode
     *            the mode to use, either OPEN_READ or OPEN_READ | OPEN_DELETE
     * @exception java.io.IOException
     *                If the file cannot be read.
     */
    public JarFile(File file, boolean verify, int mode) throws IOException {
        super(file, mode);
        if (verify) {
            verifier = new JarVerifier(file.getPath());
        }
        readMetaEntries();
    }

    /**
     * Create a new JarFile from the contents of the file specified by filename.
     *
     * @param filename
     *            java.lang.String
     * @exception java.io.IOException
     *                If fileName cannot be opened for reading.
     */
    public JarFile(String filename) throws IOException {
        this(filename, true);

    }

    /**
     * Create a new JarFile from the contents of the file specified by filename.
     *
     * @param filename
     *            java.lang.String
     * @param verify
     *            verify a signed jar file
     * @exception java.io.IOException
     *                If fileName cannot be opened for reading.
     */
    public JarFile(String filename, boolean verify) throws IOException {
        super(filename);
        if (verify) {
            verifier = new JarVerifier(filename);
        }
        readMetaEntries();
    }

    /**
     * Return an enumeration containing the JarEntrys contained in this JarFile.
     *
     * @return java.util.Enumeration
     * @exception java.lang.IllegalStateException
     *                If this JarFile has been closed.
     */
    @Override
    public Enumeration<JarEntry> entries() {
        class JarFileEnumerator implements Enumeration<JarEntry> {
            Enumeration<? extends ZipEntry> ze;

            JarFile jf;

            JarFileEnumerator(Enumeration<? extends ZipEntry> zenum, JarFile jf) {
                ze = zenum;
                this.jf = jf;
            }

            public boolean hasMoreElements() {
                return ze.hasMoreElements();
            }

            public JarEntry nextElement() {
                JarEntry je = new JarEntry(ze.nextElement());
                je.parentJar = jf;
                return je;
            }
        }
        return new JarFileEnumerator(super.entries(), this);
    }

    /**
     * Return the JarEntry specified by name or null if no such entry exists.
     *
     * @param name
     *            the name of the entry in the jar file
     * @return java.util.jar.JarEntry
     */
    public JarEntry getJarEntry(String name) {
        return (JarEntry) getEntry(name);
    }

    /**
     * Returns the Manifest object associated with this JarFile or null if no
     * manifest entry exists.
     *
     * @return java.util.jar.Manifest
     */
    public Manifest getManifest() throws IOException {
        if (manifest != null) {
            return manifest;
        }
        try {
            ByteArrayInputStream is = (ByteArrayInputStream) super
                    .getInputStream(manifestEntry);
            if (verifier != null) {
                byte[] buf = new byte[is.available()];
                is.mark(buf.length);
                is.read(buf, 0, buf.length);
                is.reset();
                verifier.addMetaEntry(manifestEntry.getName(), buf);
            }
            try {
                manifest = new Manifest(is, verifier != null);
            } finally {
                is.close();
            }
            manifestEntry = null;
        } catch (NullPointerException e) {
            manifestEntry = null;
        }
        return manifest;
    }

    private void readMetaEntries() throws IOException {
        ZipEntry[] metaEntries = getMetaEntriesImpl(null);
        int dirLength = META_DIR.length();

        boolean signed = false;

        if (null != metaEntries) {
            for (ZipEntry entry : metaEntries) {
                String entryName = entry.getName();
                if (manifestEntry == null
                        && manifest == null
                        && Util.ASCIIIgnoreCaseRegionMatches(entryName,
                                dirLength, MANIFEST_NAME, dirLength,
                                MANIFEST_NAME.length() - dirLength)) {
                    manifestEntry = entry;
                    if (verifier == null) {
                        break;
                    }
                } else if (verifier != null
                        && entryName.length() > dirLength
                        && (Util.ASCIIIgnoreCaseRegionMatches(entryName,
                                entryName.length() - 3, ".SF", 0, 3) //$NON-NLS-1$
                                || Util.ASCIIIgnoreCaseRegionMatches(entryName,
                                        entryName.length() - 4, ".DSA", 0, 4) //$NON-NLS-1$
                        || Util.ASCIIIgnoreCaseRegionMatches(entryName,
                                entryName.length() - 4, ".RSA", 0, 4))) { //$NON-NLS-1$
                    signed = true;
                    InputStream is = super.getInputStream(entry);
                    byte[] buf = new byte[is.available()];
                    try {
                        is.read(buf, 0, buf.length);
                    } finally {
                        is.close();
                    }
                    verifier.addMetaEntry(entryName, buf);
                }
            }
        }
        if (!signed) {
            verifier = null;
        }
    }

    /**
     * Return an InputStream for reading the decompressed contents of ze.
     *
     * @param ze
     *            the ZipEntry to read from
     * @return java.io.InputStream
     * @exception java.io.IOException
     *                If an error occured while creating the InputStream.
     */
    @Override
    public InputStream getInputStream(ZipEntry ze) throws IOException {
        if (manifestEntry != null) {
            getManifest();
        }
        if (verifier != null) {
            verifier.setManifest(getManifest());
            if (manifest != null) {
                verifier.mainAttributesChunk = manifest
                        .getMainAttributesChunk();
            }
            if (verifier.readCertificates()) {
                verifier.removeMetaEntries();
                if (manifest != null) {
                    manifest.removeChunks();
                }
                if (!verifier.isSignedJar()) {
                    verifier = null;
                }
            }
        }
        InputStream in = super.getInputStream(ze);
        if (in == null) {
            return null;
        }
        return new JarFileInputStream(in, ze, ze.getSize() >= 0 ? verifier
                : null);
    }

    /**
     * Return the JarEntry specified by name or null if no such entry exists
     *
     * @param name
     *            the name of the entry in the jar file
     * @return java.util.jar.JarEntry
     */
    @Override
    public ZipEntry getEntry(String name) {
        ZipEntry ze = super.getEntry(name);
        if (ze == null) {
            return ze;
        }
        JarEntry je = new JarEntry(ze);
        je.parentJar = this;
        return je;
    }

    private native ZipEntry[] getMetaEntriesImpl(byte[] buf);

}
TOP

Related Classes of java.util.jar.JarFile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.