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