1/*
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24import java.io.*;
25import java.nio.*;
26import java.util.*;
27import java.util.zip.*;
28
29public class LargeZipFile {
30    // If true, don't delete large ZIP file created for test.
31    static final boolean debug = System.getProperty("debug") != null;
32
33    static final int DATA_LEN = 1024 * 1024;
34    static final int DATA_SIZE = 8;
35
36    static long fileSize = 3L * 1024L * 1024L * 1024L; // 3GB
37
38    static boolean userFile = false;
39
40    static byte[] data;
41    static File largeFile;
42    static String lastEntryName;
43
44    /* args can be empty, in which case check a 3 GB file which is created for
45     * this test (and then deleted).  Or it can be a number, in which case
46     * that designates the size of the file that's created for this test (and
47     * then deleted).  Or it can be the name of a file to use for the test, in
48     * which case it is *not* deleted.  Note that in this last case, the data
49     * comparison might fail.
50     */
51    static void realMain (String[] args) throws Throwable {
52        if (args.length > 0) {
53            try {
54                fileSize = Long.parseLong(args[0]);
55                System.out.println("Testing with file of size " + fileSize);
56            } catch (NumberFormatException ex) {
57                largeFile = new File(args[0]);
58                if (!largeFile.exists()) {
59                    throw new Exception("Specified file " + args[0] + " does not exist");
60                }
61                userFile = true;
62                System.out.println("Testing with user-provided file " + largeFile);
63            }
64        }
65        File testDir = null;
66        if (largeFile == null) {
67            testDir = new File(System.getProperty("test.scratch", "."),
68                                    "LargeZip");
69            if (testDir.exists()) {
70                if (!testDir.delete()) {
71                    throw new Exception("Cannot delete already-existing test directory");
72                }
73            }
74            check(!testDir.exists() && testDir.mkdirs());
75            largeFile = new File(testDir, "largezip.zip");
76            createLargeZip();
77        }
78
79        readLargeZip();
80
81        if (!userFile && !debug) {
82            check(largeFile.delete());
83            check(testDir.delete());
84        }
85    }
86
87    static void createLargeZip() throws Throwable {
88        int iterations = DATA_LEN / DATA_SIZE;
89        ByteBuffer bb = ByteBuffer.allocate(DATA_SIZE);
90        ByteArrayOutputStream baos = new ByteArrayOutputStream();
91        for (int i = 0; i < iterations; i++) {
92            bb.putDouble(0, Math.random());
93            baos.write(bb.array(), 0, DATA_SIZE);
94        }
95        data = baos.toByteArray();
96        try (FileOutputStream fos = new FileOutputStream(largeFile);
97             BufferedOutputStream bos = new BufferedOutputStream(fos);
98             ZipOutputStream zos = new ZipOutputStream(bos))
99        {
100            long length = 0;
101            while (length < fileSize) {
102                ZipEntry ze = new ZipEntry("entry-" + length);
103                lastEntryName = ze.getName();
104                zos.putNextEntry(ze);
105                zos.write(data, 0, data.length);
106                zos.closeEntry();
107                length = largeFile.length();
108            }
109            System.out.println("Last entry written is " + lastEntryName);
110        }
111    }
112
113    static void readLargeZip() throws Throwable {
114        try (ZipFile zipFile = new ZipFile(largeFile)) {
115            ZipEntry entry = null;
116            String entryName = null;
117            int count = 0;
118            Enumeration<? extends ZipEntry> entries = zipFile.entries();
119            while (entries.hasMoreElements()) {
120                entry = entries.nextElement();
121                entryName = entry.getName();
122                count++;
123            }
124            System.out.println("Number of entries read: " + count);
125            System.out.println("Last entry read is " + entryName);
126            check(!entry.isDirectory());
127            if (check(entryName.equals(lastEntryName))) {
128                ByteArrayOutputStream baos = new ByteArrayOutputStream();
129                InputStream is = zipFile.getInputStream(entry);
130                byte buf[] = new byte[4096];
131                int len;
132                while ((len = is.read(buf)) >= 0) {
133                    baos.write(buf, 0, len);
134                }
135                baos.close();
136                is.close();
137                check(Arrays.equals(data, baos.toByteArray()));
138            }
139        }
140    }
141
142    //--------------------- Infrastructure ---------------------------
143    static volatile int passed = 0, failed = 0;
144    static void pass() {passed++;}
145    static void pass(String msg) {System.out.println(msg); passed++;}
146    static void fail() {failed++; Thread.dumpStack();}
147    static void fail(String msg) {System.out.println(msg); fail();}
148    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
149    static void unexpected(Throwable t, String msg) {
150        System.out.println(msg); failed++; t.printStackTrace();}
151    static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
152    static void equal(Object x, Object y) {
153        if (x == null ? y == null : x.equals(y)) pass();
154        else fail(x + " not equal to " + y);}
155    public static void main(String[] args) throws Throwable {
156        try {realMain(args);} catch (Throwable t) {unexpected(t);}
157        System.out.println("\nPassed = " + passed + " failed = " + failed);
158        if (failed > 0) throw new AssertionError("Some tests failed");}
159}
160