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