11d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the License.  You may obtain a copy of the License at
81d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
101d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage java.util.jar;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.File;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.FilterInputStream;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.InputStream;
241d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilsonimport java.util.ArrayList;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Enumeration;
261d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilsonimport java.util.List;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.zip.ZipEntry;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.zip.ZipFile;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
301d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilsonimport org.apache.harmony.archive.internal.nls.Messages;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.archive.util.Util;
321d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilsonimport org.apache.harmony.luni.util.InputStreamHelper;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code JarFile} is used to read jar entries and their associated data from
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * jar files.
37407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson *
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see JarInputStream
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see JarEntry
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class JarFile extends ZipFile {
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The MANIFEST file name.
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; //$NON-NLS-1$
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
481d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson    // The directory containing the manifest.
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final String META_DIR = "META-INF/"; //$NON-NLS-1$
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
511d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson    // The manifest after it has been read from the JAR.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Manifest manifest;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
541d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson    // The entry for the MANIFEST.MF file before it is read.
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private ZipEntry manifestEntry;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    JarVerifier verifier;
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private boolean closed = false;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static final class JarFileInputStream extends FilterInputStream {
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private long count;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private ZipEntry zipEntry;
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private JarVerifier.VerifierEntry entry;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
684949c14402562af123745d59020cd4fc5eb565cbUrs Grob        private boolean done = false;
694949c14402562af123745d59020cd4fc5eb565cbUrs Grob
70407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        JarFileInputStream(InputStream is, ZipEntry ze,
71407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                JarVerifier.VerifierEntry e) {
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super(is);
73407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            zipEntry = ze;
74407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            count = zipEntry.getSize();
75407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            entry = e;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int read() throws IOException {
804949c14402562af123745d59020cd4fc5eb565cbUrs Grob            if (done) {
814949c14402562af123745d59020cd4fc5eb565cbUrs Grob                return -1;
824949c14402562af123745d59020cd4fc5eb565cbUrs Grob            }
83407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            if (count > 0) {
84407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                int r = super.read();
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (r != -1) {
86407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    entry.write(r);
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    count--;
88407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                } else {
89407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    count = 0;
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
91407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                if (count == 0) {
924949c14402562af123745d59020cd4fc5eb565cbUrs Grob                    done = true;
93407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    entry.verify();
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
95407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                return r;
96407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            } else {
974949c14402562af123745d59020cd4fc5eb565cbUrs Grob                done = true;
984949c14402562af123745d59020cd4fc5eb565cbUrs Grob                entry.verify();
99407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                return -1;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int read(byte[] buf, int off, int nbytes) throws IOException {
1054949c14402562af123745d59020cd4fc5eb565cbUrs Grob            if (done) {
1064949c14402562af123745d59020cd4fc5eb565cbUrs Grob                return -1;
1074949c14402562af123745d59020cd4fc5eb565cbUrs Grob            }
108407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            if (count > 0) {
109407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                int r = super.read(buf, off, nbytes);
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (r != -1) {
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    int size = r;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    if (count < size) {
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        size = (int) count;
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
115407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    entry.write(buf, off, size);
116407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    count -= size;
117407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                } else {
118407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    count = 0;
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
120407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                if (count == 0) {
1214949c14402562af123745d59020cd4fc5eb565cbUrs Grob                    done = true;
122407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                    entry.verify();
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
124407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                return r;
125407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            } else {
1264949c14402562af123745d59020cd4fc5eb565cbUrs Grob                done = true;
1274949c14402562af123745d59020cd4fc5eb565cbUrs Grob                entry.verify();
128407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                return -1;
129407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            }
130407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        }
131407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson
132407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        @Override
133407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        public int available() throws IOException {
1344949c14402562af123745d59020cd4fc5eb565cbUrs Grob            if (done) {
135407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                return 0;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1374949c14402562af123745d59020cd4fc5eb565cbUrs Grob            return super.available();
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public long skip(long nbytes) throws IOException {
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            long cnt = 0, rem = 0;
1431d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            byte[] buf = new byte[(int)Math.min(nbytes, 2048L)];
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            while (cnt < nbytes) {
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int x = read(buf, 0,
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        (rem = nbytes - cnt) > buf.length ? buf.length
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                : (int) rem);
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (x == -1) {
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return cnt;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cnt += x;
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return cnt;
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a new {@code JarFile} using the contents of the specified file.
159407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the JAR file as {@link File}.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             If the file cannot be read.
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarFile(File file) throws IOException {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(file, true);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a new {@code JarFile} using the contents of the specified file.
171407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the JAR file as {@link File}.
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param verify
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            if this JAR file is signed whether it must be verified.
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             If the file cannot be read.
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarFile(File file, boolean verify) throws IOException {
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(file);
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (verify) {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifier = new JarVerifier(file.getPath());
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        readMetaEntries();
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a new {@code JarFile} using the contents of file.
189407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param file
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the JAR file as {@link File}.
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param verify
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            if this JAR filed is signed whether it must be verified.
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param mode
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the mode to use, either {@link ZipFile#OPEN_READ OPEN_READ} or
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            {@link ZipFile#OPEN_DELETE OPEN_DELETE}.
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             If the file cannot be read.
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarFile(File file, boolean verify, int mode) throws IOException {
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(file, mode);
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (verify) {
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifier = new JarVerifier(file.getPath());
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        readMetaEntries();
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a new {@code JarFile} from the contents of the file specified by
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * filename.
211407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param filename
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the file name referring to the JAR file.
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if file name cannot be opened for reading.
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarFile(String filename) throws IOException {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(filename, true);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create a new {@code JarFile} from the contents of the file specified by
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code filename}.
224407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param filename
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the file name referring to the JAR file.
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param verify
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            if this JAR filed is signed whether it must be verified.
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             If file cannot be opened or read.
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarFile(String filename, boolean verify) throws IOException {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super(filename);
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (verify) {
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifier = new JarVerifier(filename);
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        readMetaEntries();
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return an enumeration containing the {@code JarEntrys} contained in this
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code JarFile}.
243407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the {@code Enumeration} containing the JAR entries.
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalStateException
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if this {@code JarFile} is closed.
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Enumeration<JarEntry> entries() {
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        class JarFileEnumerator implements Enumeration<JarEntry> {
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Enumeration<? extends ZipEntry> ze;
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFile jf;
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            JarFileEnumerator(Enumeration<? extends ZipEntry> zenum, JarFile jf) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ze = zenum;
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                this.jf = jf;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public boolean hasMoreElements() {
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return ze.hasMoreElements();
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            public JarEntry nextElement() {
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                JarEntry je = new JarEntry(ze.nextElement());
266407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                je.parentJar = jf;
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return je;
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new JarFileEnumerator(super.entries(), this);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return the {@code JarEntry} specified by its name or {@code null} if no
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * such entry exists.
276407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param name
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the entry in the JAR file.
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the JAR entry defined by the name.
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public JarEntry getJarEntry(String name) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (JarEntry) getEntry(name);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the {@code Manifest} object associated with this {@code JarFile}
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * or {@code null} if no MANIFEST entry exists.
288407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the MANIFEST.
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an error occurs reading the MANIFEST file.
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IllegalStateException
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if the jar file is closed.
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see Manifest
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Manifest getManifest() throws IOException {
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (closed) {
2981d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            // archive.35=JarFile has been closed
2991d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            throw new IllegalStateException(Messages.getString("archive.35")); //$NON-NLS-1$
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (manifest != null) {
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return manifest;
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InputStream is = super.getInputStream(manifestEntry);
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (verifier != null) {
3071d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                verifier.addMetaEntry(manifestEntry.getName(),
3081d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                        InputStreamHelper.readFullyAndClose(is));
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                is = super.getInputStream(manifestEntry);
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            try {
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                manifest = new Manifest(is, verifier != null);
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            } finally {
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                is.close();
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
3161d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            manifestEntry = null;  // Can discard the entry now.
3171d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        } catch (NullPointerException e) {
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            manifestEntry = null;
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return manifest;
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3231d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson    /**
3241d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * Called by the JarFile constructors, this method reads the contents of the
3251d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * file's META-INF/ directory and picks out the MANIFEST.MF file and
3261d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * verifier signature files if they exist. Any signature files found are
3271d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * registered with the verifier.
3281d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     *
3291d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * @throws IOException
3301d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     *             if there is a problem reading the jar file entries.
3311d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     */
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void readMetaEntries() throws IOException {
3331d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        // Get all meta directory entries
3341d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        ZipEntry[] metaEntries = getMetaEntriesImpl();
3351d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        if (metaEntries == null) {
3361d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            verifier = null;
3371d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            return;
3381d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        }
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        boolean signed = false;
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3421d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        for (ZipEntry entry : metaEntries) {
3431d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            String entryName = entry.getName();
3441d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            // Is this the entry for META-INF/MANIFEST.MF ?
3451d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            if (manifestEntry == null
3461d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                    && Util.asciiEqualsIgnoreCase(MANIFEST_NAME, entryName)) {
3471d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                manifestEntry = entry;
3481d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                // If there is no verifier then we don't need to look any further.
3491d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                if (verifier == null) {
3501d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                    break;
3511d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                }
3521d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            } else {
3531d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                // Is this an entry that the verifier needs?
3541d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                if (verifier != null
3551d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                        && (Util.asciiEndsWithIgnoreCase(entryName, ".SF")
3561d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                                || Util.asciiEndsWithIgnoreCase(entryName, ".DSA")
3571d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                                || Util.asciiEndsWithIgnoreCase(entryName, ".RSA"))) {
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    signed = true;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    InputStream is = super.getInputStream(entry);
3601d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                    byte[] buf = InputStreamHelper.readFullyAndClose(is);
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    verifier.addMetaEntry(entryName, buf);
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
3651d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson
3661d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        // If there were no signature files, then no verifier work to do.
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!signed) {
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifier = null;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return an {@code InputStream} for reading the decompressed contents of
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * ZIP entry.
375407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ze
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the ZIP entry to be read.
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the input stream to read from.
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an error occurred while creating the input stream.
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public InputStream getInputStream(ZipEntry ze) throws IOException {
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (manifestEntry != null) {
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getManifest();
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (verifier != null) {
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifier.setManifest(getManifest());
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (manifest != null) {
390407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson                verifier.mainAttributesEnd = manifest.getMainAttributesEnd();
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (verifier.readCertificates()) {
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                verifier.removeMetaEntries();
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (manifest != null) {
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    manifest.removeChunks();
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!verifier.isSignedJar()) {
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    verifier = null;
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        InputStream in = super.getInputStream(ze);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (in == null) {
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
406407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        if (verifier == null || ze.getSize() == -1) {
407407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            return in;
408407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        }
409407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        JarVerifier.VerifierEntry entry = verifier.initEntry(ze.getName());
410407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        if (entry == null) {
411407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson            return in;
412407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        }
413407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        return new JarFileInputStream(in, ze, entry);
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Return the {@code JarEntry} specified by name or {@code null} if no such
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * entry exists.
419407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param name
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the entry in the JAR file.
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the ZIP entry extracted.
423407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     */
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ZipEntry getEntry(String name) {
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ZipEntry ze = super.getEntry(name);
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (ze == null) {
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return ze;
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        JarEntry je = new JarEntry(ze);
431407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson        je.parentJar = this;
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return je;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4351d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson    /**
4361d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * Returns all the ZipEntry's that relate to files in the
4371d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * JAR's META-INF directory.
4381d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     *
4391d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     * @return the list of ZipEntry's or {@code null} if there are none.
4401d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson     */
4411d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson    private ZipEntry[] getMetaEntriesImpl() {
4421d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        List<ZipEntry> list = new ArrayList<ZipEntry>(8);
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Enumeration<? extends ZipEntry> allEntries = entries();
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        while (allEntries.hasMoreElements()) {
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ZipEntry ze = allEntries.nextElement();
4461d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson            if (ze.getName().startsWith(META_DIR)
4471d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson                    && ze.getName().length() > META_DIR.length()) {
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                list.add(ze);
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4511d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        if (list.size() == 0) {
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
4541d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        ZipEntry[] result = new ZipEntry[list.size()];
4551d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        list.toArray(result);
4561d96b51e7f1e0a9d8cfa88f12dfe7cdb46d07634Jesse Wilson        return result;
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Closes this {@code JarFile}.
461407a2013b289b6b0e860b4275671b7b0194c42fcJesse Wilson     *
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @throws IOException
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *             if an error occurs.
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void close() throws IOException {
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        super.close();
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        closed = true;
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
471