1 /* 2 * Copyright (c) 2010, 2018, 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.File; 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.io.OutputStream; 28 import java.net.URI; 29 import java.net.URLDecoder; 30 import java.nio.ByteBuffer; 31 import java.nio.channels.Channels; 32 import java.nio.channels.FileChannel; 33 import java.nio.channels.SeekableByteChannel; 34 import java.nio.file.DirectoryStream; 35 import java.nio.file.FileAlreadyExistsException; 36 import java.nio.file.FileSystem; 37 import java.nio.file.FileSystemAlreadyExistsException; 38 import java.nio.file.FileSystemException; 39 import java.nio.file.FileSystems; 40 import java.nio.file.FileVisitResult; 41 import java.nio.file.Files; 42 import java.nio.file.OpenOption; 43 import java.nio.file.Path; 44 import java.nio.file.Paths; 45 import java.nio.file.SimpleFileVisitor; 46 import java.nio.file.attribute.BasicFileAttributeView; 47 import java.nio.file.attribute.BasicFileAttributes; 48 import java.nio.file.spi.FileSystemProvider; 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.Collections; 52 import java.util.Enumeration; 53 import java.util.HashMap; 54 import java.util.HashSet; 55 import java.util.Iterator; 56 import java.util.LinkedList; 57 import java.util.List; 58 import java.util.Map; 59 import java.util.Random; 60 import java.util.Set; 61 import java.util.concurrent.TimeUnit; 62 import java.util.zip.CRC32; 63 import java.util.zip.ZipEntry; 64 import java.util.zip.ZipFile; 65 import java.util.zip.ZipOutputStream; 66 67 import static java.nio.file.StandardOpenOption.*; 68 import static java.nio.file.StandardCopyOption.*; 69 70 /* 71 * Tests various zipfs operations. 72 * 73 * @test 74 * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596 75 * 7157656 8002390 7012868 7012856 8015728 8038500 8040059 8069211 76 * 8131067 8034802 8210899 77 * @summary Test Zip filesystem provider 78 * @modules jdk.zipfs 79 * @run main ZipFSTester 80 * @run main/othervm/java.security.policy=test.policy ZipFSTester 81 */ 82 83 public class ZipFSTester { 84 main(String[] args)85 public static void main(String[] args) throws Exception { 86 // create JAR file for test, actual contents don't matter 87 Path jarFile = Utils.createJarFile("tester.jar", 88 "META-INF/MANIFEST.MF", 89 "dir1/foo", 90 "dir2/bar", 91 "dir1/dir3/fooo"); 92 93 try (FileSystem fs = newZipFileSystem(jarFile, Collections.emptyMap())) { 94 test0(fs); 95 test1(fs); 96 test2(fs); // more tests 97 } 98 testStreamChannel(); 99 testTime(jarFile); 100 test8069211(); 101 test8131067(); 102 } 103 104 private static Random rdm = new Random(); 105 test0(FileSystem fs)106 static void test0(FileSystem fs) 107 throws Exception 108 { 109 List<String> list = new LinkedList<>(); 110 try (ZipFile zf = new ZipFile(fs.toString())) { 111 Enumeration<? extends ZipEntry> zes = zf.entries(); 112 while (zes.hasMoreElements()) { 113 list.add(zes.nextElement().getName()); 114 } 115 for (String pname : list) { 116 Path path = fs.getPath(pname); 117 if (!Files.exists(path)) 118 throw new RuntimeException("path existence check failed!"); 119 while ((path = path.getParent()) != null) { 120 if (!Files.exists(path)) 121 throw new RuntimeException("parent existence check failed!"); 122 } 123 } 124 } 125 } 126 test1(FileSystem fs0)127 static void test1(FileSystem fs0) 128 throws Exception 129 { 130 // prepare a src for testing 131 Path src = getTempPath(); 132 String tmpName = src.toString(); 133 try (OutputStream os = Files.newOutputStream(src)) { 134 byte[] bits = new byte[12345]; 135 rdm.nextBytes(bits); 136 os.write(bits); 137 } 138 139 // clone a fs from fs0 and test on it 140 Path tmpfsPath = getTempPath(); 141 Map<String, Object> env = new HashMap<String, Object>(); 142 env.put("create", "true"); 143 try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) { 144 z2zcopy(fs0, copy, "/", 0); 145 146 // copy the test jar itself in 147 Files.copy(Paths.get(fs0.toString()), copy.getPath("/foo.jar")); 148 Path zpath = copy.getPath("/foo.jar"); 149 try (FileSystem zzfs = FileSystems.newFileSystem(zpath, null)) { 150 Files.copy(src, zzfs.getPath("/srcInjarjar")); 151 } 152 } 153 154 try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) { 155 156 FileSystemProvider provider = fs.provider(); 157 // newFileSystem(path...) should not throw exception 158 try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap<String, Object>())){} 159 try (FileSystem fsUri = provider.newFileSystem( 160 new URI("jar", tmpfsPath.toUri().toString(), null), 161 new HashMap<String, Object>())) 162 { 163 throw new RuntimeException("newFileSystem(URI...) does not throw exception"); 164 } catch (FileSystemAlreadyExistsException fsaee) {} 165 166 try { 167 provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(), 168 new HashMap<String, Object>()); 169 throw new RuntimeException("newFileSystem() opens a directory as zipfs"); 170 } catch (UnsupportedOperationException uoe) {} 171 172 try { 173 provider.newFileSystem(src, new HashMap<String, Object>()); 174 throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs"); 175 } catch (UnsupportedOperationException uoe) {} 176 177 // walk 178 walk(fs.getPath("/")); 179 180 // copyin 181 Path dst = getPathWithParents(fs, tmpName); 182 Files.copy(src, dst); 183 checkEqual(src, dst); 184 185 // copy 186 Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) + 187 "/efg" + rdm.nextInt(100) + "/foo.class"); 188 Files.copy(dst, dst2); 189 //dst.moveTo(dst2); 190 checkEqual(src, dst2); 191 192 // delete 193 Files.delete(dst); 194 if (Files.exists(dst)) 195 throw new RuntimeException("Failed!"); 196 197 // moveout 198 Path dst3 = Paths.get(tmpName + "_Tmp"); 199 Files.move(dst2, dst3); 200 checkEqual(src, dst3); 201 if (Files.exists(dst2)) 202 throw new RuntimeException("Failed!"); 203 204 // copyback + move 205 Files.copy(dst3, dst); 206 Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0"); 207 Files.move(dst, dst4); 208 checkEqual(src, dst4); 209 210 // delete 211 Files.delete(dst4); 212 if (Files.exists(dst4)) 213 throw new RuntimeException("Failed!"); 214 Files.delete(dst3); 215 if (Files.exists(dst3)) 216 throw new RuntimeException("Failed!"); 217 218 // move (existing entry) 219 Path dst5 = fs.getPath("META-INF/MANIFEST.MF"); 220 if (Files.exists(dst5)) { 221 Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP"); 222 Files.move(dst5, dst6); 223 walk(fs.getPath("/")); 224 } 225 226 // newInputStream on dir 227 Path parent = dst2.getParent(); 228 try { 229 Files.newInputStream(parent); 230 throw new RuntimeException("Failed"); 231 } catch (FileSystemException e) { 232 // expected fse 233 } 234 235 // rmdirs 236 try { 237 rmdirs(parent); 238 } catch (IOException x) { 239 x.printStackTrace(); 240 } 241 242 // newFileChannel() copy in, out and verify via fch 243 fchCopy(src, dst); // in 244 checkEqual(src, dst); 245 Path tmp = Paths.get(tmpName + "_Tmp"); 246 fchCopy(dst, tmp); // out 247 checkEqual(src, tmp); 248 Files.delete(tmp); 249 250 // test channels 251 channel(fs, dst); 252 Files.delete(dst); 253 254 // test foo.jar in jar/zipfs #8034802 255 Path jpath = fs.getPath("/foo.jar"); 256 System.out.println("walking: " + jpath); 257 try (FileSystem zzfs = FileSystems.newFileSystem(jpath, null)) { 258 walk(zzfs.getPath("/")); 259 // foojar:/srcInjarjar 260 checkEqual(src, zzfs.getPath("/srcInjarjar")); 261 262 dst = getPathWithParents(zzfs, tmpName); 263 fchCopy(src, dst); 264 checkEqual(src, dst); 265 tmp = Paths.get(tmpName + "_Tmp"); 266 fchCopy(dst, tmp); // out 267 checkEqual(src, tmp); 268 Files.delete(tmp); 269 270 channel(zzfs, dst); 271 Files.delete(dst); 272 } 273 } finally { 274 Files.deleteIfExists(tmpfsPath); 275 Files.deleteIfExists(src); 276 } 277 } 278 test2(FileSystem fs)279 static void test2(FileSystem fs) throws Exception { 280 281 Path fs1Path = getTempPath(); 282 Path fs2Path = getTempPath(); 283 Path fs3Path = getTempPath(); 284 285 // create a new filesystem, copy everything from fs 286 Map<String, Object> env = new HashMap<String, Object>(); 287 env.put("create", "true"); 288 FileSystem fs0 = newZipFileSystem(fs1Path, env); 289 290 final FileSystem fs2 = newZipFileSystem(fs2Path, env); 291 final FileSystem fs3 = newZipFileSystem(fs3Path, env); 292 293 System.out.println("copy src: fs -> fs0..."); 294 z2zcopy(fs, fs0, "/", 0); // copy fs -> fs1 295 fs0.close(); // dump to file 296 297 System.out.println("open fs0 as fs1"); 298 env = new HashMap<String, Object>(); 299 final FileSystem fs1 = newZipFileSystem(fs1Path, env); 300 301 System.out.println("listing..."); 302 final ArrayList<String> files = new ArrayList<>(); 303 final ArrayList<String> dirs = new ArrayList<>(); 304 list(fs1.getPath("/"), files, dirs); 305 306 Thread t0 = new Thread(new Runnable() { 307 public void run() { 308 List<String> list = new ArrayList<>(dirs); 309 Collections.shuffle(list); 310 for (String path : list) { 311 try { 312 z2zcopy(fs1, fs2, path, 0); 313 } catch (Exception x) { 314 x.printStackTrace(); 315 } 316 } 317 } 318 319 }); 320 321 Thread t1 = new Thread(new Runnable() { 322 public void run() { 323 List<String> list = new ArrayList<>(dirs); 324 Collections.shuffle(list); 325 for (String path : list) { 326 try { 327 z2zcopy(fs1, fs2, path, 1); 328 } catch (Exception x) { 329 x.printStackTrace(); 330 } 331 } 332 } 333 334 }); 335 336 Thread t2 = new Thread(new Runnable() { 337 public void run() { 338 List<String> list = new ArrayList<>(dirs); 339 Collections.shuffle(list); 340 for (String path : list) { 341 try { 342 z2zcopy(fs1, fs2, path, 2); 343 } catch (Exception x) { 344 x.printStackTrace(); 345 } 346 } 347 } 348 349 }); 350 351 Thread t3 = new Thread(new Runnable() { 352 public void run() { 353 List<String> list = new ArrayList<>(files); 354 Collections.shuffle(list); 355 while (!list.isEmpty()) { 356 Iterator<String> itr = list.iterator(); 357 while (itr.hasNext()) { 358 String path = itr.next(); 359 try { 360 if (Files.exists(fs2.getPath(path))) { 361 z2zmove(fs2, fs3, path); 362 itr.remove(); 363 } 364 } catch (FileAlreadyExistsException x){ 365 itr.remove(); 366 } catch (Exception x) { 367 x.printStackTrace(); 368 } 369 } 370 } 371 } 372 373 }); 374 375 System.out.println("copying/removing..."); 376 t0.start(); t1.start(); t2.start(); t3.start(); 377 t0.join(); t1.join(); t2.join(); t3.join(); 378 379 System.out.println("closing: fs1, fs2"); 380 fs1.close(); 381 fs2.close(); 382 383 int failed = 0; 384 System.out.println("checkEqual: fs vs fs3"); 385 for (String path : files) { 386 try { 387 checkEqual(fs.getPath(path), fs3.getPath(path)); 388 } catch (IOException x) { 389 //x.printStackTrace(); 390 failed++; 391 } 392 } 393 System.out.println("closing: fs3"); 394 fs3.close(); 395 396 System.out.println("opening: fs3 as fs4"); 397 FileSystem fs4 = newZipFileSystem(fs3Path, env); 398 399 400 ArrayList<String> files2 = new ArrayList<>(); 401 ArrayList<String> dirs2 = new ArrayList<>(); 402 list(fs4.getPath("/"), files2, dirs2); 403 404 System.out.println("checkEqual: fs vs fs4"); 405 for (String path : files2) { 406 checkEqual(fs.getPath(path), fs4.getPath(path)); 407 } 408 System.out.println("walking: fs4"); 409 walk(fs4.getPath("/")); 410 System.out.println("closing: fs4"); 411 fs4.close(); 412 System.out.printf("failed=%d%n", failed); 413 414 Files.delete(fs1Path); 415 Files.delete(fs2Path); 416 Files.delete(fs3Path); 417 } 418 419 static final int METHOD_STORED = 0; 420 static final int METHOD_DEFLATED = 8; 421 getEntries()422 static Object[][] getEntries() { 423 Object[][] entries = new Object[10 + rdm.nextInt(20)][3]; 424 // first entries shall test the corner case of 0 bytes of data 425 entries[0][0] = "entries" + 0; 426 entries[0][1] = METHOD_STORED; 427 entries[0][2] = new byte[0]; 428 entries[1][0] = "entries" + 1; 429 entries[1][1] = METHOD_DEFLATED; 430 entries[1][2] = new byte[0]; 431 // the rest is random data 432 for (int i = 2; i < entries.length; i++) { 433 entries[i][0] = "entries" + i; 434 entries[i][1] = rdm.nextInt(10) % 2 == 0 ? 435 METHOD_STORED : METHOD_DEFLATED; 436 entries[i][2] = new byte[rdm.nextInt(8192)]; 437 rdm.nextBytes((byte[])entries[i][2]); 438 } 439 return entries; 440 } 441 442 // check the content of read from zipfs is equal to the "bytes" checkRead(Path path, byte[] expected)443 private static void checkRead(Path path, byte[] expected) throws IOException { 444 445 // fileAttribute 446 CRC32 crc32 = new CRC32(); 447 crc32.update(expected); 448 449 if (((Long)Files.getAttribute(path, "zip:crc")).intValue() != 450 (int)crc32.getValue()) { 451 System.out.printf(" getAttribute.crc <%s> failed %x vs %x ...%n", 452 path.toString(), 453 ((Long)Files.getAttribute(path, "zip:crc")).intValue(), 454 (int)crc32.getValue()); 455 throw new RuntimeException("CHECK FAILED!"); 456 } 457 458 if (((Long)Files.getAttribute(path, "zip:size")).intValue() != expected.length) { 459 System.out.printf(" getAttribute.size <%s> failed %x vs %x ...%n", 460 path.toString(), 461 ((Long)Files.getAttribute(path, "zip:size")).intValue(), 462 expected.length); 463 throw new RuntimeException("CHECK FAILED!"); 464 } 465 466 //streams 467 try (InputStream is = Files.newInputStream(path)) { 468 if (!Arrays.equals(is.readAllBytes(), expected)) { 469 System.out.printf(" newInputStream <%s> failed...%n", path.toString()); 470 throw new RuntimeException("CHECK FAILED!"); 471 } 472 } 473 474 // channels -- via sun.nio.ch.ChannelInputStream 475 try (SeekableByteChannel sbc = Files.newByteChannel(path); 476 InputStream is = Channels.newInputStream(sbc)) { 477 478 // check all bytes match 479 if (!Arrays.equals(is.readAllBytes(), expected)) { 480 System.out.printf(" newByteChannel <%s> failed...%n", path.toString()); 481 throw new RuntimeException("CHECK FAILED!"); 482 } 483 484 // Check if read position is at the end 485 if (sbc.position() != expected.length) { 486 System.out.printf("pos [%s]: size=%d, position=%d%n", 487 path.toString(), expected.length, sbc.position()); 488 throw new RuntimeException("CHECK FAILED!"); 489 } 490 491 // Check position(x) + read() at the random/specific pos/len 492 byte[] buf = new byte[1024]; 493 ByteBuffer bb = ByteBuffer.wrap(buf); 494 for (int i = 0; i < 10; i++) { 495 int pos = 0; 496 int len = 0; 497 if (expected.length > 0) { 498 pos = rdm.nextInt((int) sbc.size()); 499 len = rdm.nextInt(Math.min(buf.length, expected.length - pos)); 500 } 501 // System.out.printf(" --> %d, %d%n", pos, len); 502 bb.position(0).limit(len); // bb.flip().limit(len); 503 if (sbc.position(pos).position() != pos || 504 sbc.read(bb) != len || 505 !Arrays.equals(buf, 0, bb.position(), expected, pos, pos + len)) { 506 System.out.printf("read()/position() failed%n"); 507 } 508 } 509 } catch (IOException x) { 510 x.printStackTrace(); 511 throw new RuntimeException("CHECK FAILED!"); 512 } 513 } 514 515 // test entry stream/channel reading testStreamChannel()516 static void testStreamChannel() throws Exception { 517 Path zpath = getTempPath(); 518 try { 519 var crc = new CRC32(); 520 Object[][] entries = getEntries(); 521 522 // [1] create zip via ZipOutputStream 523 try (var os = Files.newOutputStream(zpath); 524 var zos = new ZipOutputStream(os)) { 525 for (Object[] entry : entries) { 526 var ze = new ZipEntry((String)entry[0]); 527 int method = (int)entry[1]; 528 byte[] bytes = (byte[])entry[2]; 529 if (method == METHOD_STORED) { 530 ze.setSize(bytes.length); 531 crc.reset(); 532 crc.update(bytes); 533 ze.setCrc(crc.getValue()); 534 } 535 ze.setMethod(method); 536 zos.putNextEntry(ze); 537 zos.write(bytes); 538 zos.closeEntry(); 539 } 540 } 541 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 542 for (Object[] e : entries) { 543 Path path = zfs.getPath((String)e[0]); 544 int method = (int)e[1]; 545 byte[] bytes = (byte[])e[2]; 546 // System.out.printf("checking read [%s, %d, %d]%n", 547 // path.toString(), bytes.length, method); 548 checkRead(path, bytes); 549 } 550 } 551 Files.deleteIfExists(zpath); 552 553 // [2] create zip via zfs.newByteChannel 554 try (var zfs = newZipFileSystem(zpath, Map.of("create", "true"))) { 555 for (Object[] e : entries) { 556 // tbd: method is not used 557 try (var sbc = Files.newByteChannel(zfs.getPath((String)e[0]), 558 CREATE_NEW, WRITE)) { 559 sbc.write(ByteBuffer.wrap((byte[])e[2])); 560 } 561 } 562 } 563 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 564 for (Object[] e : entries) { 565 checkRead(zfs.getPath((String)e[0]), (byte[])e[2]); 566 } 567 } 568 Files.deleteIfExists(zpath); 569 570 // [3] create zip via Files.write()/newoutputStream/ 571 try (var zfs = newZipFileSystem(zpath, Map.of("create", "true"))) { 572 for (Object[] e : entries) { 573 Files.write(zfs.getPath((String)e[0]), (byte[])e[2]); 574 } 575 } 576 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 577 for (Object[] e : entries) { 578 checkRead(zfs.getPath((String)e[0]), (byte[])e[2]); 579 } 580 } 581 Files.deleteIfExists(zpath); 582 583 // [4] create zip via zfs.newByteChannel, with "method_stored" 584 try (var zfs = newZipFileSystem(zpath, 585 Map.of("create", true, "noCompression", true))) { 586 for (Object[] e : entries) { 587 try (var sbc = Files.newByteChannel(zfs.getPath((String)e[0]), 588 CREATE_NEW, WRITE)) { 589 sbc.write(ByteBuffer.wrap((byte[])e[2])); 590 } 591 } 592 } 593 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 594 for (Object[] e : entries) { 595 checkRead(zfs.getPath((String)e[0]), (byte[])e[2]); 596 } 597 } 598 Files.deleteIfExists(zpath); 599 600 } finally { 601 Files.deleteIfExists(zpath); 602 } 603 } 604 605 // test file stamp testTime(Path src)606 static void testTime(Path src) throws Exception { 607 BasicFileAttributes attrs = Files 608 .getFileAttributeView(src, BasicFileAttributeView.class) 609 .readAttributes(); 610 // create a new filesystem, copy this file into it 611 Map<String, Object> env = new HashMap<String, Object>(); 612 env.put("create", "true"); 613 Path fsPath = getTempPath(); 614 try (FileSystem fs = newZipFileSystem(fsPath, env)) { 615 System.out.println("test copy with timestamps..."); 616 // copyin 617 Path dst = getPathWithParents(fs, "me"); 618 Files.copy(src, dst, COPY_ATTRIBUTES); 619 checkEqual(src, dst); 620 System.out.println("mtime: " + attrs.lastModifiedTime()); 621 System.out.println("ctime: " + attrs.creationTime()); 622 System.out.println("atime: " + attrs.lastAccessTime()); 623 System.out.println(" ==============>"); 624 BasicFileAttributes dstAttrs = Files 625 .getFileAttributeView(dst, BasicFileAttributeView.class) 626 .readAttributes(); 627 System.out.println("mtime: " + dstAttrs.lastModifiedTime()); 628 System.out.println("ctime: " + dstAttrs.creationTime()); 629 System.out.println("atime: " + dstAttrs.lastAccessTime()); 630 631 // 1-second granularity 632 if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) != 633 dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) || 634 attrs.lastAccessTime().to(TimeUnit.SECONDS) != 635 dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) || 636 attrs.creationTime().to(TimeUnit.SECONDS) != 637 dstAttrs.creationTime().to(TimeUnit.SECONDS)) { 638 throw new RuntimeException("Timestamp Copy Failed!"); 639 } 640 } finally { 641 Files.delete(fsPath); 642 } 643 } 644 test8069211()645 static void test8069211() throws Exception { 646 // create a new filesystem, copy this file into it 647 Map<String, Object> env = new HashMap<String, Object>(); 648 env.put("create", "true"); 649 Path fsPath = getTempPath(); 650 try (FileSystem fs = newZipFileSystem(fsPath, env);) { 651 OutputStream out = Files.newOutputStream(fs.getPath("/foo")); 652 out.write("hello".getBytes()); 653 out.close(); 654 out.close(); 655 } 656 try (FileSystem fs = newZipFileSystem(fsPath, new HashMap<String, Object>())) { 657 if (!Arrays.equals(Files.readAllBytes(fs.getPath("/foo")), 658 "hello".getBytes())) { 659 throw new RuntimeException("entry close() failed"); 660 } 661 } catch (Exception x) { 662 throw new RuntimeException("entry close() failed", x); 663 } finally { 664 Files.delete(fsPath); 665 } 666 } 667 test8131067()668 static void test8131067() throws Exception { 669 Map<String, Object> env = new HashMap<String, Object>(); 670 env.put("create", "true"); 671 672 // file name with space character for URI to quote it 673 File tmp = File.createTempFile("test zipfs", "zip"); 674 tmp.delete(); // we need a clean path, no file 675 Path fsPath = tmp.toPath(); 676 try (FileSystem fs = newZipFileSystem(fsPath, env);) { 677 Files.write(fs.getPath("/foo"), "hello".getBytes()); 678 URI fooUri = fs.getPath("/foo").toUri(); 679 if (!Arrays.equals(Files.readAllBytes(Paths.get(fooUri)), 680 "hello".getBytes())) { 681 throw new RuntimeException("entry close() failed"); 682 } 683 } finally { 684 Files.delete(fsPath); 685 } 686 } 687 newZipFileSystem(Path path, Map<String, ?> env)688 private static FileSystem newZipFileSystem(Path path, Map<String, ?> env) 689 throws Exception 690 { 691 // Use URLDecoder (for test only) to remove the double escaped space 692 // character 693 return FileSystems.newFileSystem( 694 new URI("jar", URLDecoder.decode(path.toUri().toString(), "utf8"), 695 null), env, null); 696 } 697 getTempPath()698 private static Path getTempPath() throws IOException 699 { 700 File tmp = File.createTempFile("testzipfs_", "zip"); 701 tmp.delete(); // we need a clean path, no file 702 return tmp.toPath(); 703 } 704 list(Path path, List<String> files, List<String> dirs )705 private static void list(Path path, List<String> files, List<String> dirs ) 706 throws IOException 707 { 708 if (Files.isDirectory(path)) { 709 try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) { 710 for (Path child : ds) 711 list(child, files, dirs); 712 } 713 dirs.add(path.toString()); 714 } else { 715 files.add(path.toString()); 716 } 717 } 718 z2zcopy(FileSystem src, FileSystem dst, String path, int method)719 private static void z2zcopy(FileSystem src, FileSystem dst, String path, 720 int method) 721 throws IOException 722 { 723 Path srcPath = src.getPath(path); 724 Path dstPath = dst.getPath(path); 725 726 if (Files.isDirectory(srcPath)) { 727 if (!Files.exists(dstPath)) { 728 try { 729 mkdirs(dstPath); 730 } catch (FileAlreadyExistsException x) {} 731 } 732 try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) { 733 for (Path child : ds) { 734 z2zcopy(src, dst, 735 path + (path.endsWith("/")?"":"/") + child.getFileName(), 736 method); 737 } 738 } 739 } else { 740 try { 741 if (Files.exists(dstPath)) 742 return; 743 switch (method) { 744 case 0: 745 Files.copy(srcPath, dstPath); 746 break; 747 case 1: 748 chCopy(srcPath, dstPath); 749 break; 750 case 2: 751 //fchCopy(srcPath, dstPath); 752 streamCopy(srcPath, dstPath); 753 break; 754 } 755 } catch (FileAlreadyExistsException x) {} 756 } 757 } 758 z2zmove(FileSystem src, FileSystem dst, String path)759 private static void z2zmove(FileSystem src, FileSystem dst, String path) 760 throws IOException 761 { 762 Path srcPath = src.getPath(path); 763 Path dstPath = dst.getPath(path); 764 765 if (Files.isDirectory(srcPath)) { 766 if (!Files.exists(dstPath)) 767 mkdirs(dstPath); 768 try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) { 769 for (Path child : ds) { 770 z2zmove(src, dst, 771 path + (path.endsWith("/")?"":"/") + child.getFileName()); 772 } 773 } 774 } else { 775 //System.out.println("moving..." + path); 776 Path parent = dstPath.getParent(); 777 if (parent != null && Files.notExists(parent)) 778 mkdirs(parent); 779 Files.move(srcPath, dstPath); 780 } 781 } 782 walk(Path path)783 private static void walk(Path path) throws IOException 784 { 785 Files.walkFileTree( 786 path, 787 new SimpleFileVisitor<Path>() { 788 private int indent = 0; 789 private void indent() { 790 int n = 0; 791 while (n++ < indent) 792 System.out.printf(" "); 793 } 794 795 @Override 796 public FileVisitResult visitFile(Path file, 797 BasicFileAttributes attrs) 798 { 799 indent(); 800 System.out.printf("%s%n", file.getFileName().toString()); 801 return FileVisitResult.CONTINUE; 802 } 803 804 @Override 805 public FileVisitResult preVisitDirectory(Path dir, 806 BasicFileAttributes attrs) 807 { 808 indent(); 809 System.out.printf("[%s]%n", dir.toString()); 810 indent += 2; 811 return FileVisitResult.CONTINUE; 812 } 813 814 @Override 815 public FileVisitResult postVisitDirectory(Path dir, 816 IOException ioe) 817 throws IOException 818 { 819 indent -= 2; 820 return FileVisitResult.CONTINUE; 821 } 822 }); 823 } 824 mkdirs(Path path)825 private static void mkdirs(Path path) throws IOException { 826 if (Files.exists(path)) 827 return; 828 path = path.toAbsolutePath(); 829 Path parent = path.getParent(); 830 if (parent != null) { 831 if (Files.notExists(parent)) 832 mkdirs(parent); 833 } 834 Files.createDirectory(path); 835 } 836 rmdirs(Path path)837 private static void rmdirs(Path path) throws IOException { 838 while (path != null && path.getNameCount() != 0) { 839 Files.delete(path); 840 path = path.getParent(); 841 } 842 } 843 844 // check the content of two paths are equal checkEqual(Path src, Path dst)845 private static void checkEqual(Path src, Path dst) throws IOException 846 { 847 System.out.printf("checking <%s> vs <%s>...%n", 848 src.toString(), dst.toString()); 849 850 //streams 851 byte[] bufSrc = new byte[8192]; 852 byte[] bufDst = new byte[8192]; 853 try (InputStream isSrc = Files.newInputStream(src); 854 InputStream isDst = Files.newInputStream(dst)) 855 { 856 int nSrc = 0; 857 while ((nSrc = isSrc.read(bufSrc)) != -1) { 858 int nDst = 0; 859 while (nDst < nSrc) { 860 int n = isDst.read(bufDst, nDst, nSrc - nDst); 861 if (n == -1) { 862 System.out.printf("checking <%s> vs <%s>...%n", 863 src.toString(), dst.toString()); 864 throw new RuntimeException("CHECK FAILED!"); 865 } 866 nDst += n; 867 } 868 while (--nSrc >= 0) { 869 if (bufSrc[nSrc] != bufDst[nSrc]) { 870 System.out.printf("checking <%s> vs <%s>...%n", 871 src.toString(), dst.toString()); 872 throw new RuntimeException("CHECK FAILED!"); 873 } 874 nSrc--; 875 } 876 } 877 } 878 879 // channels 880 try (SeekableByteChannel chSrc = Files.newByteChannel(src); 881 SeekableByteChannel chDst = Files.newByteChannel(dst)) 882 { 883 if (chSrc.size() != chDst.size()) { 884 System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", 885 chSrc.toString(), chSrc.size(), 886 chDst.toString(), chDst.size()); 887 throw new RuntimeException("CHECK FAILED!"); 888 } 889 ByteBuffer bbSrc = ByteBuffer.allocate(8192); 890 ByteBuffer bbDst = ByteBuffer.allocate(8192); 891 892 int nSrc = 0; 893 while ((nSrc = chSrc.read(bbSrc)) != -1) { 894 int nDst = chDst.read(bbDst); 895 if (nSrc != nDst) { 896 System.out.printf("checking <%s> vs <%s>...%n", 897 src.toString(), dst.toString()); 898 throw new RuntimeException("CHECK FAILED!"); 899 } 900 while (--nSrc >= 0) { 901 if (bbSrc.get(nSrc) != bbDst.get(nSrc)) { 902 System.out.printf("checking <%s> vs <%s>...%n", 903 src.toString(), dst.toString()); 904 throw new RuntimeException("CHECK FAILED!"); 905 } 906 nSrc--; 907 } 908 bbSrc.flip(); 909 bbDst.flip(); 910 } 911 912 // Check if source read position is at the end 913 if (chSrc.position() != chSrc.size()) { 914 System.out.printf("src[%s]: size=%d, position=%d%n", 915 chSrc.toString(), chSrc.size(), chSrc.position()); 916 throw new RuntimeException("CHECK FAILED!"); 917 } 918 919 // Check if destination read position is at the end 920 if (chDst.position() != chDst.size()) { 921 System.out.printf("dst[%s]: size=%d, position=%d%n", 922 chDst.toString(), chDst.size(), chDst.position()); 923 throw new RuntimeException("CHECK FAILED!"); 924 } 925 926 // Check position(x) + read() at the specific pos/len 927 for (int i = 0; i < 10; i++) { 928 int pos = rdm.nextInt((int)chSrc.size()); 929 int limit = rdm.nextInt(1024); 930 if (chSrc.position(pos).position() != chDst.position(pos).position()) { 931 System.out.printf("dst/src.position(pos failed%n"); 932 } 933 bbSrc.clear().limit(limit); 934 bbDst.clear().limit(limit); 935 if (chSrc.read(bbSrc) != chDst.read(bbDst) || 936 !bbSrc.flip().equals(bbDst.flip())) { 937 System.out.printf("dst/src.read() failed%n"); 938 } 939 } 940 } catch (IOException x) { 941 x.printStackTrace(); 942 } 943 } 944 fchCopy(Path src, Path dst)945 private static void fchCopy(Path src, Path dst) throws IOException 946 { 947 Set<OpenOption> read = new HashSet<>(); 948 read.add(READ); 949 Set<OpenOption> openwrite = new HashSet<>(); 950 openwrite.add(CREATE_NEW); 951 openwrite.add(WRITE); 952 953 try (FileChannel srcFc = src.getFileSystem() 954 .provider() 955 .newFileChannel(src, read); 956 FileChannel dstFc = dst.getFileSystem() 957 .provider() 958 .newFileChannel(dst, openwrite)) 959 { 960 ByteBuffer bb = ByteBuffer.allocate(8192); 961 while (srcFc.read(bb) >= 0) { 962 bb.flip(); 963 dstFc.write(bb); 964 bb.clear(); 965 } 966 } 967 } 968 chCopy(Path src, Path dst)969 private static void chCopy(Path src, Path dst) throws IOException 970 { 971 Set<OpenOption> read = new HashSet<>(); 972 read.add(READ); 973 Set<OpenOption> openwrite = new HashSet<>(); 974 openwrite.add(CREATE_NEW); 975 openwrite.add(WRITE); 976 977 try (SeekableByteChannel srcCh = Files.newByteChannel(src, read); 978 SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite)) 979 { 980 981 ByteBuffer bb = ByteBuffer.allocate(8192); 982 while (srcCh.read(bb) >= 0) { 983 bb.flip(); 984 dstCh.write(bb); 985 bb.clear(); 986 } 987 988 // Check if source read position is at the end 989 if (srcCh.position() != srcCh.size()) { 990 System.out.printf("src[%s]: size=%d, position=%d%n", 991 srcCh.toString(), srcCh.size(), srcCh.position()); 992 throw new RuntimeException("CHECK FAILED!"); 993 } 994 995 // Check if destination write position is at the end 996 if (dstCh.position() != dstCh.size()) { 997 System.out.printf("dst[%s]: size=%d, position=%d%n", 998 dstCh.toString(), dstCh.size(), dstCh.position()); 999 throw new RuntimeException("CHECK FAILED!"); 1000 } 1001 } 1002 } 1003 streamCopy(Path src, Path dst)1004 private static void streamCopy(Path src, Path dst) throws IOException 1005 { 1006 byte[] buf = new byte[8192]; 1007 try (InputStream isSrc = Files.newInputStream(src); 1008 OutputStream osDst = Files.newOutputStream(dst)) 1009 { 1010 int n = 0; 1011 while ((n = isSrc.read(buf)) != -1) { 1012 osDst.write(buf, 0, n); 1013 } 1014 } 1015 } 1016 channel(FileSystem fs, Path path)1017 static void channel(FileSystem fs, Path path) 1018 throws Exception 1019 { 1020 System.out.println("test ByteChannel..."); 1021 Set<OpenOption> read = new HashSet<>(); 1022 read.add(READ); 1023 int n = 0; 1024 ByteBuffer bb = null; 1025 ByteBuffer bb2 = null; 1026 int N = 120; 1027 1028 try (SeekableByteChannel sbc = Files.newByteChannel(path)) { 1029 System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size()); 1030 if (sbc.position() != 0) { 1031 throw new RuntimeException("CHECK FAILED!"); 1032 } 1033 1034 bb = ByteBuffer.allocate((int)sbc.size()); 1035 n = sbc.read(bb); 1036 System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n", 1037 n, sbc.position(), sbc.size()); 1038 if (sbc.position() != sbc.size()) { 1039 throw new RuntimeException("CHECK FAILED!"); 1040 } 1041 bb2 = ByteBuffer.allocate((int)sbc.size()); 1042 } 1043 1044 // sbc.position(pos) is not supported in current version 1045 // try the FileChannel 1046 try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) { 1047 sbc.position(N); 1048 System.out.printf(" sbc[2]: pos=%d, size=%d%n", 1049 sbc.position(), sbc.size()); 1050 if (sbc.position() != N) { 1051 throw new RuntimeException("CHECK FAILED!"); 1052 } 1053 bb2.limit(100); 1054 n = sbc.read(bb2); 1055 System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n", 1056 n, sbc.position(), sbc.size()); 1057 if (n < 0 || sbc.position() != (N + n)) { 1058 throw new RuntimeException("CHECK FAILED!"); 1059 } 1060 System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n", 1061 N, bb.get(N) & 0xff, bb2.get(0) & 0xff); 1062 } 1063 } 1064 1065 // create parents if does not exist getPathWithParents(FileSystem fs, String name)1066 static Path getPathWithParents(FileSystem fs, String name) 1067 throws Exception 1068 { 1069 Path path = fs.getPath(name); 1070 Path parent = path.getParent(); 1071 if (parent != null && Files.notExists(parent)) 1072 mkdirs(parent); 1073 return path; 1074 } 1075 } 1076