1 /*
   2  * Copyright (c) 2009, 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 
  24 import java.io.*;
  25 import java.nio.*;
  26 import java.util.*;
  27 import java.util.zip.*;
  28 
  29 public 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 }