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 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 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 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 e.printStackTrace(); // 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 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 422 static Object[][] getEntries() { 423 Object[][] entries = new Object[10 + rdm.nextInt(20)][3]; 424 for (int i = 0; i < entries.length; i++) { 425 entries[i][0] = "entries" + i; 426 entries[i][1] = rdm.nextInt(10) % 2 == 0 ? 427 METHOD_STORED : METHOD_DEFLATED; 428 entries[i][2] = new byte[rdm.nextInt(8192)]; 429 rdm.nextBytes((byte[])entries[i][2]); 430 } 431 return entries; 432 } 433 434 // check the content of read from zipfs is equal to the "bytes" 435 private static void checkRead(Path path, byte[] expected) throws IOException { 436 437 // fileAttribute 438 CRC32 crc32 = new CRC32(); 439 crc32.update(expected); 440 441 if (((Long)Files.getAttribute(path, "zip:crc")).intValue() != 442 (int)crc32.getValue()) { 443 System.out.printf(" getAttribute.crc <%s> failed %x vs %x ...%n", 444 path.toString(), 445 ((Long)Files.getAttribute(path, "zip:crc")).intValue(), 446 (int)crc32.getValue()); 447 throw new RuntimeException("CHECK FAILED!"); 448 } 449 450 if (((Long)Files.getAttribute(path, "zip:size")).intValue() != expected.length) { 451 System.out.printf(" getAttribute.size <%s> failed %x vs %x ...%n", 452 path.toString(), 453 ((Long)Files.getAttribute(path, "zip:size")).intValue(), 454 expected.length); 455 throw new RuntimeException("CHECK FAILED!"); 456 } 457 458 //streams 459 try (InputStream is = Files.newInputStream(path)) { 460 if (!Arrays.equals(is.readAllBytes(), expected)) { 461 System.out.printf(" newInputStream <%s> failed...%n", path.toString()); 462 throw new RuntimeException("CHECK FAILED!"); 463 } 464 } 465 466 // channels -- via sun.nio.ch.ChannelInputStream 467 try (SeekableByteChannel sbc = Files.newByteChannel(path); 468 InputStream is = Channels.newInputStream(sbc)) { 469 470 // check all bytes match 471 if (!Arrays.equals(is.readAllBytes(), expected)) { 472 System.out.printf(" newByteChannel <%s> failed...%n", path.toString()); 473 throw new RuntimeException("CHECK FAILED!"); 474 } 475 476 // Check if read position is at the end 477 if (sbc.position() != expected.length) { 478 System.out.printf("pos [%s]: size=%d, position=%d%n", 479 path.toString(), expected.length, sbc.position()); 480 throw new RuntimeException("CHECK FAILED!"); 481 } 482 483 // Check position(x) + read() at the random/specific pos/len 484 byte[] buf = new byte[1024]; 485 ByteBuffer bb = ByteBuffer.wrap(buf); 486 for (int i = 0; i < 10; i++) { 487 int pos = 0; 488 int len = 0; 489 if (expected.length > 0) { 490 pos = rdm.nextInt((int) sbc.size()); 491 len = rdm.nextInt(Math.min(buf.length, expected.length - pos)); 492 } 493 // System.out.printf(" --> %d, %d%n", pos, len); 494 bb.position(0).limit(len); // bb.flip().limit(len); 495 if (sbc.position(pos).position() != pos || 496 sbc.read(bb) != len || 497 !Arrays.equals(buf, 0, bb.position(), expected, pos, pos + len)) { 498 System.out.printf("read()/position() failed%n"); 499 } 500 } 501 } catch (IOException x) { 502 x.printStackTrace(); 503 throw new RuntimeException("CHECK FAILED!"); 504 } 505 } 506 507 // test entry stream/channel reading 508 static void testStreamChannel() throws Exception { 509 Path zpath = getTempPath(); 510 try { 511 var crc = new CRC32(); 512 Object[][] entries = getEntries(); 513 514 // [1] create zip via ZipOutputStream 515 try (var os = Files.newOutputStream(zpath); 516 var zos = new ZipOutputStream(os)) { 517 for (Object[] entry : entries) { 518 var ze = new ZipEntry((String)entry[0]); 519 int method = (int)entry[1]; 520 byte[] bytes = (byte[])entry[2]; 521 if (method == METHOD_STORED) { 522 ze.setSize(bytes.length); 523 crc.reset(); 524 crc.update(bytes); 525 ze.setCrc(crc.getValue()); 526 } 527 ze.setMethod(method); 528 zos.putNextEntry(ze); 529 zos.write(bytes); 530 zos.closeEntry(); 531 } 532 } 533 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 534 for (Object[] e : entries) { 535 Path path = zfs.getPath((String)e[0]); 536 int method = (int)e[1]; 537 byte[] bytes = (byte[])e[2]; 538 // System.out.printf("checking read [%s, %d, %d]%n", 539 // path.toString(), bytes.length, method); 540 checkRead(path, bytes); 541 } 542 } 543 Files.deleteIfExists(zpath); 544 545 // [2] create zip via zfs.newByteChannel 546 try (var zfs = newZipFileSystem(zpath, Map.of("create", "true"))) { 547 for (Object[] e : entries) { 548 // tbd: method is not used 549 try (var sbc = Files.newByteChannel(zfs.getPath((String)e[0]), 550 CREATE_NEW, WRITE)) { 551 sbc.write(ByteBuffer.wrap((byte[])e[2])); 552 } 553 } 554 } 555 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 556 for (Object[] e : entries) { 557 checkRead(zfs.getPath((String)e[0]), (byte[])e[2]); 558 } 559 } 560 Files.deleteIfExists(zpath); 561 562 // [3] create zip via Files.write()/newoutputStream/ 563 try (var zfs = newZipFileSystem(zpath, Map.of("create", "true"))) { 564 for (Object[] e : entries) { 565 Files.write(zfs.getPath((String)e[0]), (byte[])e[2]); 566 } 567 } 568 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 569 for (Object[] e : entries) { 570 checkRead(zfs.getPath((String)e[0]), (byte[])e[2]); 571 } 572 } 573 Files.deleteIfExists(zpath); 574 575 // [4] create zip via zfs.newByteChannel, with "method_stored" 576 try (var zfs = newZipFileSystem(zpath, 577 Map.of("create", true, "noCompression", true))) { 578 for (Object[] e : entries) { 579 try (var sbc = Files.newByteChannel(zfs.getPath((String)e[0]), 580 CREATE_NEW, WRITE)) { 581 sbc.write(ByteBuffer.wrap((byte[])e[2])); 582 } 583 } 584 } 585 try (var zfs = newZipFileSystem(zpath, Collections.emptyMap())) { 586 for (Object[] e : entries) { 587 checkRead(zfs.getPath((String)e[0]), (byte[])e[2]); 588 } 589 } 590 Files.deleteIfExists(zpath); 591 592 } finally { 593 Files.deleteIfExists(zpath); 594 } 595 } 596 597 // test file stamp 598 static void testTime(Path src) throws Exception { 599 BasicFileAttributes attrs = Files 600 .getFileAttributeView(src, BasicFileAttributeView.class) 601 .readAttributes(); 602 // create a new filesystem, copy this file into it 603 Map<String, Object> env = new HashMap<String, Object>(); 604 env.put("create", "true"); 605 Path fsPath = getTempPath(); 606 try (FileSystem fs = newZipFileSystem(fsPath, env)) { 607 System.out.println("test copy with timestamps..."); 608 // copyin 609 Path dst = getPathWithParents(fs, "me"); 610 Files.copy(src, dst, COPY_ATTRIBUTES); 611 checkEqual(src, dst); 612 System.out.println("mtime: " + attrs.lastModifiedTime()); 613 System.out.println("ctime: " + attrs.creationTime()); 614 System.out.println("atime: " + attrs.lastAccessTime()); 615 System.out.println(" ==============>"); 616 BasicFileAttributes dstAttrs = Files 617 .getFileAttributeView(dst, BasicFileAttributeView.class) 618 .readAttributes(); 619 System.out.println("mtime: " + dstAttrs.lastModifiedTime()); 620 System.out.println("ctime: " + dstAttrs.creationTime()); 621 System.out.println("atime: " + dstAttrs.lastAccessTime()); 622 623 // 1-second granularity 624 if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) != 625 dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) || 626 attrs.lastAccessTime().to(TimeUnit.SECONDS) != 627 dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) || 628 attrs.creationTime().to(TimeUnit.SECONDS) != 629 dstAttrs.creationTime().to(TimeUnit.SECONDS)) { 630 throw new RuntimeException("Timestamp Copy Failed!"); 631 } 632 } finally { 633 Files.delete(fsPath); 634 } 635 } 636 637 static void test8069211() throws Exception { 638 // create a new filesystem, copy this file into it 639 Map<String, Object> env = new HashMap<String, Object>(); 640 env.put("create", "true"); 641 Path fsPath = getTempPath(); 642 try (FileSystem fs = newZipFileSystem(fsPath, env);) { 643 OutputStream out = Files.newOutputStream(fs.getPath("/foo")); 644 out.write("hello".getBytes()); 645 out.close(); 646 out.close(); 647 } 648 try (FileSystem fs = newZipFileSystem(fsPath, new HashMap<String, Object>())) { 649 if (!Arrays.equals(Files.readAllBytes(fs.getPath("/foo")), 650 "hello".getBytes())) { 651 throw new RuntimeException("entry close() failed"); 652 } 653 } catch (Exception x) { 654 throw new RuntimeException("entry close() failed", x); 655 } finally { 656 Files.delete(fsPath); 657 } 658 } 659 660 static void test8131067() throws Exception { 661 Map<String, Object> env = new HashMap<String, Object>(); 662 env.put("create", "true"); 663 664 // file name with space character for URI to quote it 665 File tmp = File.createTempFile("test zipfs", "zip"); 666 tmp.delete(); // we need a clean path, no file 667 Path fsPath = tmp.toPath(); 668 try (FileSystem fs = newZipFileSystem(fsPath, env);) { 669 Files.write(fs.getPath("/foo"), "hello".getBytes()); 670 URI fooUri = fs.getPath("/foo").toUri(); 671 if (!Arrays.equals(Files.readAllBytes(Paths.get(fooUri)), 672 "hello".getBytes())) { 673 throw new RuntimeException("entry close() failed"); 674 } 675 } finally { 676 Files.delete(fsPath); 677 } 678 } 679 680 private static FileSystem newZipFileSystem(Path path, Map<String, ?> env) 681 throws Exception 682 { 683 // Use URLDecoder (for test only) to remove the double escaped space 684 // character 685 return FileSystems.newFileSystem( 686 new URI("jar", URLDecoder.decode(path.toUri().toString(), "utf8"), 687 null), env, null); 688 } 689 690 private static Path getTempPath() throws IOException 691 { 692 File tmp = File.createTempFile("testzipfs_", "zip"); 693 tmp.delete(); // we need a clean path, no file 694 return tmp.toPath(); 695 } 696 697 private static void list(Path path, List<String> files, List<String> dirs ) 698 throws IOException 699 { 700 if (Files.isDirectory(path)) { 701 try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) { 702 for (Path child : ds) 703 list(child, files, dirs); 704 } 705 dirs.add(path.toString()); 706 } else { 707 files.add(path.toString()); 708 } 709 } 710 711 private static void z2zcopy(FileSystem src, FileSystem dst, String path, 712 int method) 713 throws IOException 714 { 715 Path srcPath = src.getPath(path); 716 Path dstPath = dst.getPath(path); 717 718 if (Files.isDirectory(srcPath)) { 719 if (!Files.exists(dstPath)) { 720 try { 721 mkdirs(dstPath); 722 } catch (FileAlreadyExistsException x) {} 723 } 724 try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) { 725 for (Path child : ds) { 726 z2zcopy(src, dst, 727 path + (path.endsWith("/")?"":"/") + child.getFileName(), 728 method); 729 } 730 } 731 } else { 732 try { 733 if (Files.exists(dstPath)) 734 return; 735 switch (method) { 736 case 0: 737 Files.copy(srcPath, dstPath); 738 break; 739 case 1: 740 chCopy(srcPath, dstPath); 741 break; 742 case 2: 743 //fchCopy(srcPath, dstPath); 744 streamCopy(srcPath, dstPath); 745 break; 746 } 747 } catch (FileAlreadyExistsException x) {} 748 } 749 } 750 751 private static void z2zmove(FileSystem src, FileSystem dst, String path) 752 throws IOException 753 { 754 Path srcPath = src.getPath(path); 755 Path dstPath = dst.getPath(path); 756 757 if (Files.isDirectory(srcPath)) { 758 if (!Files.exists(dstPath)) 759 mkdirs(dstPath); 760 try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) { 761 for (Path child : ds) { 762 z2zmove(src, dst, 763 path + (path.endsWith("/")?"":"/") + child.getFileName()); 764 } 765 } 766 } else { 767 //System.out.println("moving..." + path); 768 Path parent = dstPath.getParent(); 769 if (parent != null && Files.notExists(parent)) 770 mkdirs(parent); 771 Files.move(srcPath, dstPath); 772 } 773 } 774 775 private static void walk(Path path) throws IOException 776 { 777 Files.walkFileTree( 778 path, 779 new SimpleFileVisitor<Path>() { 780 private int indent = 0; 781 private void indent() { 782 int n = 0; 783 while (n++ < indent) 784 System.out.printf(" "); 785 } 786 787 @Override 788 public FileVisitResult visitFile(Path file, 789 BasicFileAttributes attrs) 790 { 791 indent(); 792 System.out.printf("%s%n", file.getFileName().toString()); 793 return FileVisitResult.CONTINUE; 794 } 795 796 @Override 797 public FileVisitResult preVisitDirectory(Path dir, 798 BasicFileAttributes attrs) 799 { 800 indent(); 801 System.out.printf("[%s]%n", dir.toString()); 802 indent += 2; 803 return FileVisitResult.CONTINUE; 804 } 805 806 @Override 807 public FileVisitResult postVisitDirectory(Path dir, 808 IOException ioe) 809 throws IOException 810 { 811 indent -= 2; 812 return FileVisitResult.CONTINUE; 813 } 814 }); 815 } 816 817 private static void mkdirs(Path path) throws IOException { 818 if (Files.exists(path)) 819 return; 820 path = path.toAbsolutePath(); 821 Path parent = path.getParent(); 822 if (parent != null) { 823 if (Files.notExists(parent)) 824 mkdirs(parent); 825 } 826 Files.createDirectory(path); 827 } 828 829 private static void rmdirs(Path path) throws IOException { 830 while (path != null && path.getNameCount() != 0) { 831 Files.delete(path); 832 path = path.getParent(); 833 } 834 } 835 836 // check the content of two paths are equal 837 private static void checkEqual(Path src, Path dst) throws IOException 838 { 839 System.out.printf("checking <%s> vs <%s>...%n", 840 src.toString(), dst.toString()); 841 842 //streams 843 byte[] bufSrc = new byte[8192]; 844 byte[] bufDst = new byte[8192]; 845 try (InputStream isSrc = Files.newInputStream(src); 846 InputStream isDst = Files.newInputStream(dst)) 847 { 848 int nSrc = 0; 849 while ((nSrc = isSrc.read(bufSrc)) != -1) { 850 int nDst = 0; 851 while (nDst < nSrc) { 852 int n = isDst.read(bufDst, nDst, nSrc - nDst); 853 if (n == -1) { 854 System.out.printf("checking <%s> vs <%s>...%n", 855 src.toString(), dst.toString()); 856 throw new RuntimeException("CHECK FAILED!"); 857 } 858 nDst += n; 859 } 860 while (--nSrc >= 0) { 861 if (bufSrc[nSrc] != bufDst[nSrc]) { 862 System.out.printf("checking <%s> vs <%s>...%n", 863 src.toString(), dst.toString()); 864 throw new RuntimeException("CHECK FAILED!"); 865 } 866 nSrc--; 867 } 868 } 869 } 870 871 // channels 872 try (SeekableByteChannel chSrc = Files.newByteChannel(src); 873 SeekableByteChannel chDst = Files.newByteChannel(dst)) 874 { 875 if (chSrc.size() != chDst.size()) { 876 System.out.printf("src[%s].size=%d, dst[%s].size=%d%n", 877 chSrc.toString(), chSrc.size(), 878 chDst.toString(), chDst.size()); 879 throw new RuntimeException("CHECK FAILED!"); 880 } 881 ByteBuffer bbSrc = ByteBuffer.allocate(8192); 882 ByteBuffer bbDst = ByteBuffer.allocate(8192); 883 884 int nSrc = 0; 885 while ((nSrc = chSrc.read(bbSrc)) != -1) { 886 int nDst = chDst.read(bbDst); 887 if (nSrc != nDst) { 888 System.out.printf("checking <%s> vs <%s>...%n", 889 src.toString(), dst.toString()); 890 throw new RuntimeException("CHECK FAILED!"); 891 } 892 while (--nSrc >= 0) { 893 if (bbSrc.get(nSrc) != bbDst.get(nSrc)) { 894 System.out.printf("checking <%s> vs <%s>...%n", 895 src.toString(), dst.toString()); 896 throw new RuntimeException("CHECK FAILED!"); 897 } 898 nSrc--; 899 } 900 bbSrc.flip(); 901 bbDst.flip(); 902 } 903 904 // Check if source read position is at the end 905 if (chSrc.position() != chSrc.size()) { 906 System.out.printf("src[%s]: size=%d, position=%d%n", 907 chSrc.toString(), chSrc.size(), chSrc.position()); 908 throw new RuntimeException("CHECK FAILED!"); 909 } 910 911 // Check if destination read position is at the end 912 if (chDst.position() != chDst.size()) { 913 System.out.printf("dst[%s]: size=%d, position=%d%n", 914 chDst.toString(), chDst.size(), chDst.position()); 915 throw new RuntimeException("CHECK FAILED!"); 916 } 917 918 // Check position(x) + read() at the specific pos/len 919 for (int i = 0; i < 10; i++) { 920 int pos = rdm.nextInt((int)chSrc.size()); 921 int limit = rdm.nextInt(1024); 922 if (chSrc.position(pos).position() != chDst.position(pos).position()) { 923 System.out.printf("dst/src.position(pos failed%n"); 924 } 925 bbSrc.clear().limit(limit); 926 bbDst.clear().limit(limit); 927 if (chSrc.read(bbSrc) != chDst.read(bbDst) || 928 !bbSrc.flip().equals(bbDst.flip())) { 929 System.out.printf("dst/src.read() failed%n"); 930 } 931 } 932 } catch (IOException x) { 933 x.printStackTrace(); 934 } 935 } 936 937 private static void fchCopy(Path src, Path dst) throws IOException 938 { 939 Set<OpenOption> read = new HashSet<>(); 940 read.add(READ); 941 Set<OpenOption> openwrite = new HashSet<>(); 942 openwrite.add(CREATE_NEW); 943 openwrite.add(WRITE); 944 945 try (FileChannel srcFc = src.getFileSystem() 946 .provider() 947 .newFileChannel(src, read); 948 FileChannel dstFc = dst.getFileSystem() 949 .provider() 950 .newFileChannel(dst, openwrite)) 951 { 952 ByteBuffer bb = ByteBuffer.allocate(8192); 953 while (srcFc.read(bb) >= 0) { 954 bb.flip(); 955 dstFc.write(bb); 956 bb.clear(); 957 } 958 } 959 } 960 961 private static void chCopy(Path src, Path dst) throws IOException 962 { 963 Set<OpenOption> read = new HashSet<>(); 964 read.add(READ); 965 Set<OpenOption> openwrite = new HashSet<>(); 966 openwrite.add(CREATE_NEW); 967 openwrite.add(WRITE); 968 969 try (SeekableByteChannel srcCh = Files.newByteChannel(src, read); 970 SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite)) 971 { 972 973 ByteBuffer bb = ByteBuffer.allocate(8192); 974 while (srcCh.read(bb) >= 0) { 975 bb.flip(); 976 dstCh.write(bb); 977 bb.clear(); 978 } 979 980 // Check if source read position is at the end 981 if (srcCh.position() != srcCh.size()) { 982 System.out.printf("src[%s]: size=%d, position=%d%n", 983 srcCh.toString(), srcCh.size(), srcCh.position()); 984 throw new RuntimeException("CHECK FAILED!"); 985 } 986 987 // Check if destination write position is at the end 988 if (dstCh.position() != dstCh.size()) { 989 System.out.printf("dst[%s]: size=%d, position=%d%n", 990 dstCh.toString(), dstCh.size(), dstCh.position()); 991 throw new RuntimeException("CHECK FAILED!"); 992 } 993 } 994 } 995 996 private static void streamCopy(Path src, Path dst) throws IOException 997 { 998 byte[] buf = new byte[8192]; 999 try (InputStream isSrc = Files.newInputStream(src); 1000 OutputStream osDst = Files.newOutputStream(dst)) 1001 { 1002 int n = 0; 1003 while ((n = isSrc.read(buf)) != -1) { 1004 osDst.write(buf, 0, n); 1005 } 1006 } 1007 } 1008 1009 static void channel(FileSystem fs, Path path) 1010 throws Exception 1011 { 1012 System.out.println("test ByteChannel..."); 1013 Set<OpenOption> read = new HashSet<>(); 1014 read.add(READ); 1015 int n = 0; 1016 ByteBuffer bb = null; 1017 ByteBuffer bb2 = null; 1018 int N = 120; 1019 1020 try (SeekableByteChannel sbc = Files.newByteChannel(path)) { 1021 System.out.printf(" sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size()); 1022 if (sbc.position() != 0) { 1023 throw new RuntimeException("CHECK FAILED!"); 1024 } 1025 1026 bb = ByteBuffer.allocate((int)sbc.size()); 1027 n = sbc.read(bb); 1028 System.out.printf(" sbc[1]: read=%d, pos=%d, size=%d%n", 1029 n, sbc.position(), sbc.size()); 1030 if (sbc.position() != sbc.size()) { 1031 throw new RuntimeException("CHECK FAILED!"); 1032 } 1033 bb2 = ByteBuffer.allocate((int)sbc.size()); 1034 } 1035 1036 // sbc.position(pos) is not supported in current version 1037 // try the FileChannel 1038 try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) { 1039 sbc.position(N); 1040 System.out.printf(" sbc[2]: pos=%d, size=%d%n", 1041 sbc.position(), sbc.size()); 1042 if (sbc.position() != N) { 1043 throw new RuntimeException("CHECK FAILED!"); 1044 } 1045 bb2.limit(100); 1046 n = sbc.read(bb2); 1047 System.out.printf(" sbc[3]: read=%d, pos=%d, size=%d%n", 1048 n, sbc.position(), sbc.size()); 1049 if (n < 0 || sbc.position() != (N + n)) { 1050 throw new RuntimeException("CHECK FAILED!"); 1051 } 1052 System.out.printf(" sbc[4]: bb[%d]=%d, bb1[0]=%d%n", 1053 N, bb.get(N) & 0xff, bb2.get(0) & 0xff); 1054 } 1055 } 1056 1057 // create parents if does not exist 1058 static Path getPathWithParents(FileSystem fs, String name) 1059 throws Exception 1060 { 1061 Path path = fs.getPath(name); 1062 Path parent = path.getParent(); 1063 if (parent != null && Files.notExists(parent)) 1064 mkdirs(parent); 1065 return path; 1066 } 1067 }