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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 import java.io.*; 27 import java.nio.*; 28 import java.nio.file.*; 29 import java.nio.file.attribute.*; 30 import java.nio.file.spi.*; 31 import java.util.*; 32 import java.util.zip.*; 33 34 import static java.nio.file.StandardCopyOption.*; 35 36 public class LargeZip { 37 // If true, don't delete large ZIP file created for test. 38 static final boolean debug = System.getProperty("debug") != null; 39 40 //static final int DATA_LEN = 1024 * 1024; 41 static final int DATA_LEN = 80 * 1024; 42 static final int DATA_SIZE = 8; 43 44 static long fileSize = 6L * 1024L * 1024L * 1024L; // 6GB 45 46 static boolean userFile = false; 47 static byte[] data; 48 static File largeFile; 49 static String lastEntryName; 50 51 /* args can be empty, in which case check a 3 GB file which is created for 52 * this test (and then deleted). Or it can be a number, in which case 53 * that designates the size of the file that's created for this test (and 54 * then deleted). Or it can be the name of a file to use for the test, in 55 * which case it is *not* deleted. Note that in this last case, the data 56 * comparison might fail. 57 */ 58 static void realMain (String[] args) throws Throwable { 59 if (args.length > 0) { 60 try { 61 fileSize = Long.parseLong(args[0]); 62 System.out.println("Testing with file of size " + fileSize); 63 } catch (NumberFormatException ex) { 64 largeFile = new File(args[0]); 65 if (!largeFile.exists()) { 66 throw new Exception("Specified file " + args[0] + " does not exist"); 67 } 68 userFile = true; 69 System.out.println("Testing with user-provided file " + largeFile); 70 } 71 } 72 File testDir = null; 73 if (largeFile == null) { 74 testDir = new File(System.getProperty("test.scratch", "."), 75 "LargeZip"); 76 if (testDir.exists()) { 77 if (!testDir.delete()) { 78 throw new Exception("Cannot delete already-existing test directory"); 79 } 80 } 81 check(!testDir.exists() && testDir.mkdirs()); 82 largeFile = new File(testDir, "largezip.zip"); 83 createLargeZip(); 84 } else { 85 if (args.length > 1) 86 updateLargeZip(args[1]); // add new entry with zfs 87 } 88 readLargeZip1(); 89 readLargeZip2(); 90 91 if (!userFile && !debug) { 92 check(largeFile.delete()); 93 check(testDir.delete()); 94 } 95 } 96 97 static void createLargeZip() throws Throwable { 98 int iterations = DATA_LEN / DATA_SIZE; 99 ByteBuffer bb = ByteBuffer.allocate(DATA_SIZE); 100 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 101 for (int i = 0; i < iterations; i++) { 102 bb.putDouble(0, Math.random()); 103 baos.write(bb.array(), 0, DATA_SIZE); 104 } 105 data = baos.toByteArray(); 106 107 try (FileOutputStream fos = new FileOutputStream(largeFile); 108 BufferedOutputStream bos = new BufferedOutputStream(fos); 109 ZipOutputStream zos = new ZipOutputStream(bos)) 110 { 111 long length = 0; 112 while (length < fileSize) { 113 ZipEntry ze = new ZipEntry("entry-" + length); 114 lastEntryName = ze.getName(); 115 zos.putNextEntry(ze); 116 zos.write(data, 0, data.length); 117 zos.closeEntry(); 118 length = largeFile.length(); 119 } 120 System.out.println("Last entry written is " + lastEntryName); 121 } 122 } 123 124 private static byte buf[] = new byte[4096]; 125 126 static void checkEntry(ZipEntry e, InputStream is) throws Throwable { 127 long N = 0; 128 int n = 0; 129 while ((n = is.read(buf)) >= 0) { 130 N += n; 131 } 132 check(N == e.getSize()); 133 } 134 135 static void readLargeZip1() throws Throwable { 136 ZipFile zipFile = new ZipFile(largeFile); 137 ZipEntry entry = null; 138 String entryName = null; 139 int count = 0; 140 System.out.println("ZipFile:"); 141 Enumeration<? extends ZipEntry> entries = zipFile.entries(); 142 while (entries.hasMoreElements()) { 143 entry = entries.nextElement(); 144 entryName = entry.getName(); 145 System.out.println(" checking " + entryName); 146 if (!entry.isDirectory()) { 147 try (InputStream zeis = zipFile.getInputStream(entry)) { 148 checkEntry(entry, zeis); 149 } 150 } 151 count++; 152 } 153 System.out.println("Number of entries read: " + count); 154 check(!entry.isDirectory()); 155 if (userFile || check(entryName.equals(lastEntryName))) { 156 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 157 InputStream is = zipFile.getInputStream(entry); 158 int len; 159 while ((len = is.read(buf)) >= 0) { 160 baos.write(buf, 0, len); 161 } 162 baos.close(); 163 is.close(); 164 if (!userFile) 165 check(Arrays.equals(data, baos.toByteArray())); 166 } 167 } 168 169 static void readLargeZip2() throws Throwable { 170 System.out.println("ZipInputStream:"); 171 try (FileInputStream fis = new FileInputStream(largeFile); 172 BufferedInputStream bis = new BufferedInputStream(fis); 173 ZipInputStream zis = new ZipInputStream(bis)) 174 { 175 ZipEntry entry = null; 176 String entryName = null; 177 int count = 0; 178 while ((entry = zis.getNextEntry()) != null) { 179 entryName = entry.getName(); 180 181 System.out.println(" checking " + entryName + 182 ", method=" + entry.getMethod()); 183 if (entryName.equals(lastEntryName)) { 184 break; 185 } 186 if (!entry.isDirectory()) { 187 checkEntry(entry, zis); 188 } 189 count++; 190 } 191 System.out.println("Number of entries read: " + count); 192 System.out.println("Last entry read is " + entryName); 193 if (!userFile) { 194 check(!entry.isDirectory()); 195 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 196 byte buf[] = new byte[4096]; 197 int len; 198 while ((len = zis.read(buf)) >= 0) { 199 baos.write(buf, 0, len); 200 } 201 baos.close(); 202 check(Arrays.equals(data, baos.toByteArray())); 203 check(zis.getNextEntry() == null); 204 } 205 } 206 } 207 208 private static void updateFile(FileSystem fs, Path src) throws IOException { 209 Path dst = fs.getPath(src.toString()); 210 Path parent = dst.getParent(); 211 if (parent != null && Files.notExists(parent)) 212 Files.createDirectories(parent); 213 Files.copy(src, dst, REPLACE_EXISTING); 214 } 215 216 private static FileSystemProvider getZipFSProvider() { 217 for (FileSystemProvider provider : FileSystemProvider.installedProviders()) { 218 if ("jar".equalsIgnoreCase(provider.getScheme())) 219 return provider; 220 } 221 return null; 222 } 223 224 static void updateLargeZip(String pName) throws Throwable { 225 FileSystemProvider provider = getZipFSProvider(); 226 if (provider == null) { 227 System.err.println("ZIP filesystem provider is not installed"); 228 System.exit(1); 229 } 230 Map<String, Object> env = env = new HashMap<>(); 231 try (FileSystem fs = provider.newFileSystem(largeFile.toPath(), env)) { 232 Path path = FileSystems.getDefault().getPath(pName); 233 Files.walkFileTree( 234 path, 235 new SimpleFileVisitor<Path>() { 236 @Override 237 public FileVisitResult visitFile(Path file, 238 BasicFileAttributes attrs) 239 throws IOException 240 { 241 updateFile(fs, file); 242 return FileVisitResult.CONTINUE; 243 } 244 }); 245 } 246 } 247 248 249 //--------------------- Infrastructure --------------------------- 250 static volatile int passed = 0, failed = 0; 251 static void pass() {passed++;} 252 static void pass(String msg) {System.out.println(msg); passed++;} 253 static void fail() {failed++; Thread.dumpStack();} 254 static void fail(String msg) {System.out.println(msg); fail();} 255 static void unexpected(Throwable t) {failed++; t.printStackTrace();} 256 static void unexpected(Throwable t, String msg) { 257 System.out.println(msg); failed++; t.printStackTrace();} 258 static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;} 259 static void equal(Object x, Object y) { 260 if (x == null ? y == null : x.equals(y)) pass(); 261 else fail(x + " not equal to " + y);} 262 public static void main(String[] args) throws Throwable { 263 try {realMain(args);} catch (Throwable t) {unexpected(t);} 264 System.out.println("\nPassed = " + passed + " failed = " + failed); 265 if (failed > 0) throw new AssertionError("Some tests failed");} 266 }