001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.util.zip;
019:
020: import java.io.ByteArrayInputStream;
021: import java.io.File;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.security.AccessController;
025: import java.security.PrivilegedAction;
026: import java.util.Enumeration;
027: import java.util.NoSuchElementException;
028:
029: import org.apache.harmony.archive.internal.nls.Messages;
030: import org.apache.harmony.luni.util.Util;
031:
032: /**
033: * ZipFile is used to read zip entries and their associated data from zip files.
034: *
035: * @see ZipInputStream
036: * @see ZipEntry
037: */
038: public class ZipFile implements ZipConstants {
039:
040: String fileName;
041:
042: long descriptor = -1;
043:
044: private int size = -1;
045:
046: private int mode;
047: static {
048: System.loadLibrary("hyarchive"); //$NON-NLS-1$
049: ntvinit();
050: }
051:
052: /** Open ZIP file for read. */
053: public static final int OPEN_READ = 1;
054:
055: /** Delete ZIP file when closed. */
056: public static final int OPEN_DELETE = 4;
057:
058: /**
059: * Constructs a new ZipFile opened on the specified File.
060: *
061: * @param file
062: * the File
063: * @throws ZipException
064: * if a ZIP format exception occurs reading the file
065: * @throws IOException
066: * if an IO exception occurs reading the file
067: */
068: public ZipFile(File file) throws ZipException, IOException {
069: this (file.getPath());
070: }
071:
072: /**
073: * Constructs a new ZipFile opened on the specified file using the specified
074: * mode.
075: *
076: * @param file
077: * the file
078: * @param mode
079: * the mode to use, either <code>OPEN_READ</code> or
080: * <code>OPEN_READ | OPEN_DELETE</code>
081: * @throws IOException
082: * if an IO exception occurs reading the file
083: */
084: public ZipFile(File file, int mode) throws IOException {
085: if (mode == OPEN_READ || mode == (OPEN_READ | OPEN_DELETE)) {
086: fileName = file.getPath();
087: SecurityManager security = System.getSecurityManager();
088: if (security != null) {
089: security.checkRead(fileName);
090: if ((mode & OPEN_DELETE) != 0) {
091: security.checkDelete(fileName);
092: }
093: }
094: this .mode = mode;
095: openZip();
096: } else {
097: throw new IllegalArgumentException();
098: }
099: }
100:
101: /**
102: * Constructs a new ZipFile opened on the specified file path name.
103: *
104: * @param filename
105: * the file path name
106: * @throws IOException
107: * if an IO exception occured reading the file
108: */
109: public ZipFile(String filename) throws IOException {
110: SecurityManager security = System.getSecurityManager();
111: if (security != null) {
112: security.checkRead(filename);
113: }
114: fileName = filename;
115: openZip();
116: }
117:
118: private void openZip() throws IOException {
119: int result = openZipImpl(Util.getUTF8Bytes(fileName));
120:
121: if (result != 0) {
122: switch (result) {
123: case 1:
124: throw new ZipException(Messages.getString(
125: "archive.24", fileName)); //$NON-NLS-1$
126: case 2:
127: throw new ZipException(Messages.getString(
128: "archive.25", fileName)); //$NON-NLS-1$
129: default:
130: throw new OutOfMemoryError();
131: }
132: }
133: }
134:
135: @Override
136: protected void finalize() throws IOException {
137: close();
138: }
139:
140: /**
141: * Closes this ZipFile.
142: *
143: * @throws IOException
144: * if an IO exception occured closing the file
145: */
146: public synchronized void close() throws IOException {
147: if (descriptor != -1 && fileName != null) {
148: // Only close initialized instances
149: closeZipImpl(descriptor);
150: if ((mode & OPEN_DELETE) != 0) {
151: AccessController
152: .doPrivileged(new PrivilegedAction<Object>() {
153: public Object run() {
154: new File(fileName).delete();
155: return null;
156: }
157: });
158: }
159: }
160: }
161:
162: /**
163: * Answers all of the ZIP entries contained in this ZipFile.
164: *
165: * @return an Enumeration of the ZIP entries
166: */
167: public Enumeration<? extends ZipEntry> entries() {
168: return new ZFEnum<ZipEntry>();
169: }
170:
171: /**
172: * Gets the zip entry with the specified name from this ZipFile.
173: *
174: * @param entryName
175: * the name of the entry in the zip file
176: * @return a ZipEntry or null if the entry name does not exist in the zip
177: * file
178: */
179: public ZipEntry getEntry(String entryName) {
180: if (entryName != null) {
181: ZipEntry entry = getEntryImpl(descriptor, entryName);
182: return entry;
183: }
184: throw new NullPointerException();
185: }
186:
187: /**
188: * Answers an input stream on the data of the specified ZipEntry.
189: *
190: * @param entry
191: * the ZipEntry
192: * @return an input stream on the ZipEntry data
193: * @throws IOException
194: * if an IO exception occurs reading the data
195: */
196: public InputStream getInputStream(ZipEntry entry)
197: throws IOException {
198: if (descriptor == -1) {
199: /*
200: * the descriptor is set to -1 by native code to indicate the zip
201: * was closed
202: */
203: throw new IllegalStateException();
204: }
205: byte[] buf = inflateEntryImpl2(descriptor, entry.getName());
206: if (buf == null) {
207: return null;
208: }
209: return new ByteArrayInputStream(buf);
210: }
211:
212: /**
213: * Gets the file name of this ZipFile.
214: *
215: * @return the file name of this ZipFile
216: */
217: public String getName() {
218: return fileName;
219: }
220:
221: private synchronized native int openZipImpl(byte[] fileName1);
222:
223: private native void closeZipImpl(long descriptor1)
224: throws IOException;
225:
226: private native ZipEntry getEntryImpl(long descriptor1,
227: String entryName);
228:
229: private native byte[] inflateEntryImpl2(long descriptor1,
230: String entryName) throws ZipException;
231:
232: /**
233: * Returns the number of ZipEntries in this ZipFile.
234: *
235: * @return Number of entries in this file
236: */
237: public int size() {
238: if (size != -1) {
239: return size;
240: }
241:
242: size = 0;
243: Enumeration<?> e = entries();
244: while (e.hasMoreElements()) {
245: size++;
246: e.nextElement();
247: }
248: return size;
249:
250: }
251:
252: private static native void ntvinit();
253:
254: class ZFEnum<T extends ZipEntry> implements Enumeration<T> {
255: private final long nextEntryPointer;
256:
257: private T current;
258:
259: ZFEnum() {
260: nextEntryPointer = resetZip(descriptor);
261: current = getNextEntry(descriptor, nextEntryPointer);
262: }
263:
264: private native long resetZip(long descriptor1);
265:
266: private native T getNextEntry(long descriptor1,
267: long nextEntryPointer1);
268:
269: public boolean hasMoreElements() {
270: if (descriptor == -1) {
271: /*
272: * the descriptor is set to -1 by native code to indicate the
273: * zip was closed
274: */
275: throw new IllegalStateException();
276: }
277: return current != null;
278: }
279:
280: public T nextElement() {
281: if (current == null) {
282: throw new NoSuchElementException();
283: }
284: T ze = current;
285: current = getNextEntry(descriptor, nextEntryPointer);
286: return ze;
287: }
288: }
289: }
|