1 /*
   2  * Copyright (c) 2010, 2013, 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.*;
  25 import java.nio.*;
  26 import java.nio.channels.*;
  27 import java.nio.file.*;
  28 import java.nio.file.spi.*;
  29 import java.nio.file.attribute.*;
  30 import java.net.*;
  31 import java.util.*;
  32 import java.util.concurrent.TimeUnit;
  33 import java.util.zip.*;
  34 
  35 import static java.nio.file.StandardOpenOption.*;
  36 import static java.nio.file.StandardCopyOption.*;
  37 
  38 /*
  39  * Tests various zipfs operations.
  40  *
  41  * @test
  42  * @bug 6990846 7009092 7009085 7015391 7014948 7005986 7017840 7007596
  43  *      7157656 8002390 7012868 7012856 8015728 8038500
  44  * @summary Test Zip filesystem provider
  45  */
  46 
  47 public class ZipFSTester {
  48 
  49     public static void main(String[] args) throws Throwable {
  50         try (FileSystem fs = newZipFileSystem(
  51                  Paths.get(System.getProperty("test.jdk"), "jre/lib/ext/zipfs.jar"),
  52                  new HashMap<String, Object>()))
  53         {
  54             test0(fs);
  55             test1(fs);
  56             test2(fs);   // more tests
  57         }
  58         testTime(Paths.get(System.getProperty("test.jdk"), "jre/lib/ext/zipfs.jar"));
  59     }
  60 
  61     static void test0(FileSystem fs)
  62         throws Exception
  63     {
  64         List<String> list = new LinkedList<>();
  65         try (ZipFile zf = new ZipFile(fs.toString())) {
  66             Enumeration<? extends ZipEntry> zes = zf.entries();
  67             while (zes.hasMoreElements()) {
  68                 list.add(zes.nextElement().getName());
  69             }
  70             for (String pname : list) {
  71                 Path path = fs.getPath(pname);
  72                 if (!Files.exists(path))
  73                     throw new RuntimeException("path existence check failed!");
  74                 while ((path = path.getParent()) != null) {
  75                     if (!Files.exists(path))
  76                         throw new RuntimeException("parent existence check failed!");
  77                 }
  78             }
  79         }
  80     }
  81 
  82     static void test1(FileSystem fs0)
  83         throws Exception
  84     {
  85         Random rdm = new Random();
  86         // clone a fs and test on it
  87         Path tmpfsPath = getTempPath();
  88         Map<String, Object> env = new HashMap<String, Object>();
  89         env.put("create", "true");
  90         try (FileSystem copy = newZipFileSystem(tmpfsPath, env)) {
  91             z2zcopy(fs0, copy, "/", 0);
  92         }
  93 
  94         try (FileSystem fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>())) {
  95 
  96             FileSystemProvider provider = fs.provider();
  97             // newFileSystem(path...) should not throw exception
  98             try (FileSystem fsPath = provider.newFileSystem(tmpfsPath, new HashMap<String, Object>())){}
  99             try (FileSystem fsUri = provider.newFileSystem(
 100                      new URI("jar", tmpfsPath.toUri().toString(), null),
 101                      new HashMap<String, Object>()))
 102             {
 103               throw new RuntimeException("newFileSystem(uri...) does not throw exception");
 104             } catch (FileSystemAlreadyExistsException fsaee) {}
 105 
 106             // prepare a src
 107             Path src = getTempPath();
 108             String tmpName = src.toString();
 109             OutputStream os = Files.newOutputStream(src);
 110             byte[] bits = new byte[12345];
 111             rdm.nextBytes(bits);
 112             os.write(bits);
 113             os.close();
 114 
 115             try {
 116                 provider.newFileSystem(new File(System.getProperty("test.src", ".")).toPath(),
 117                                        new HashMap<String, Object>());
 118                 throw new RuntimeException("newFileSystem() opens a directory as zipfs");
 119             } catch (UnsupportedOperationException uoe) {}
 120 
 121             try {
 122                 provider.newFileSystem(src, new HashMap<String, Object>());
 123                 throw new RuntimeException("newFileSystem() opens a non-zip file as zipfs");
 124             } catch (UnsupportedOperationException uoe) {}
 125 
 126 
 127             // copyin
 128             Path dst = getPathWithParents(fs, tmpName);
 129             Files.copy(src, dst);
 130             checkEqual(src, dst);
 131 
 132             // copy
 133             Path dst2 = getPathWithParents(fs, "/xyz" + rdm.nextInt(100) +
 134                                            "/efg" + rdm.nextInt(100) + "/foo.class");
 135             Files.copy(dst, dst2);
 136             //dst.moveTo(dst2);
 137             checkEqual(src, dst2);
 138 
 139             // delete
 140             Files.delete(dst);
 141             if (Files.exists(dst))
 142                 throw new RuntimeException("Failed!");
 143 
 144             // moveout
 145             Path dst3 = Paths.get(tmpName + "_Tmp");
 146             Files.move(dst2, dst3);
 147             checkEqual(src, dst3);
 148             if (Files.exists(dst2))
 149                 throw new RuntimeException("Failed!");
 150 
 151             // copyback + move
 152             Files.copy(dst3, dst);
 153             Path dst4 = getPathWithParents(fs, tmpName + "_Tmp0");
 154             Files.move(dst, dst4);
 155             checkEqual(src, dst4);
 156 
 157             // delete
 158             Files.delete(dst4);
 159             if (Files.exists(dst4))
 160                 throw new RuntimeException("Failed!");
 161             Files.delete(dst3);
 162             if (Files.exists(dst3))
 163                 throw new RuntimeException("Failed!");
 164 
 165             // move (existing entry)
 166             Path dst5 = fs.getPath("META-INF/MANIFEST.MF");
 167             if (Files.exists(dst5)) {
 168                 Path dst6 = fs.getPath("META-INF/MANIFEST.MF_TMP");
 169                 Files.move(dst5, dst6);
 170                 walk(fs.getPath("/"));
 171             }
 172 
 173             // newInputStream on dir
 174             Path parent = dst2.getParent();
 175             try {
 176                 Files.newInputStream(parent);
 177                 throw new RuntimeException("Failed");
 178             } catch (FileSystemException e) {
 179                 e.printStackTrace();    // expected fse
 180             }
 181 
 182             // rmdirs
 183             try {
 184                 rmdirs(parent);
 185             } catch (IOException x) {
 186                 x.printStackTrace();
 187             }
 188 
 189             // newFileChannel() copy in, out and verify via fch
 190             fchCopy(src, dst);    // in
 191             checkEqual(src, dst);
 192             Path tmp = Paths.get(tmpName + "_Tmp");
 193             fchCopy(dst, tmp);   //  out
 194             checkEqual(src, tmp);
 195             Files.delete(tmp);
 196 
 197             // test channels
 198             channel(fs, dst);
 199             Files.delete(dst);
 200             Files.delete(src);
 201         } finally {
 202             if (Files.exists(tmpfsPath))
 203                 Files.delete(tmpfsPath);
 204         }
 205     }
 206 
 207     static void test2(FileSystem fs) throws Exception {
 208 
 209         Path fs1Path = getTempPath();
 210         Path fs2Path = getTempPath();
 211         Path fs3Path = getTempPath();
 212 
 213         // create a new filesystem, copy everything from fs
 214         Map<String, Object> env = new HashMap<String, Object>();
 215         env.put("create", "true");
 216         FileSystem fs0 = newZipFileSystem(fs1Path, env);
 217 
 218         final FileSystem fs2 = newZipFileSystem(fs2Path, env);
 219         final FileSystem fs3 = newZipFileSystem(fs3Path, env);
 220 
 221         System.out.println("copy src: fs -> fs0...");
 222         z2zcopy(fs, fs0, "/", 0);   // copy fs -> fs1
 223         fs0.close();                // dump to file
 224 
 225         System.out.println("open fs0 as fs1");
 226         env = new HashMap<String, Object>();
 227         final FileSystem fs1 = newZipFileSystem(fs1Path, env);
 228 
 229         System.out.println("listing...");
 230         final ArrayList<String> files = new ArrayList<>();
 231         final ArrayList<String> dirs = new ArrayList<>();
 232         list(fs1.getPath("/"), files, dirs);
 233 
 234         Thread t0 = new Thread(new Runnable() {
 235             public void run() {
 236                 List<String> list = new ArrayList<>(dirs);
 237                 Collections.shuffle(list);
 238                 for (String path : list) {
 239                     try {
 240                         z2zcopy(fs1, fs2, path, 0);
 241                     } catch (Exception x) {
 242                         x.printStackTrace();
 243                     }
 244                 }
 245             }
 246 
 247         });
 248 
 249         Thread t1 = new Thread(new Runnable() {
 250             public void run() {
 251                 List<String> list = new ArrayList<>(dirs);
 252                 Collections.shuffle(list);
 253                 for (String path : list) {
 254                     try {
 255                         z2zcopy(fs1, fs2, path, 1);
 256                     } catch (Exception x) {
 257                         x.printStackTrace();
 258                     }
 259                 }
 260             }
 261 
 262         });
 263 
 264         Thread t2 = new Thread(new Runnable() {
 265             public void run() {
 266                 List<String> list = new ArrayList<>(dirs);
 267                 Collections.shuffle(list);
 268                 for (String path : list) {
 269                     try {
 270                         z2zcopy(fs1, fs2, path, 2);
 271                     } catch (Exception x) {
 272                         x.printStackTrace();
 273                     }
 274                 }
 275             }
 276 
 277         });
 278 
 279         Thread t3 = new Thread(new Runnable() {
 280             public void run() {
 281                 List<String> list = new ArrayList<>(files);
 282                 Collections.shuffle(list);
 283                 while (!list.isEmpty()) {
 284                     Iterator<String> itr = list.iterator();
 285                     while (itr.hasNext()) {
 286                         String path = itr.next();
 287                         try {
 288                             if (Files.exists(fs2.getPath(path))) {
 289                                 z2zmove(fs2, fs3, path);
 290                                 itr.remove();
 291                             }
 292                         } catch (FileAlreadyExistsException x){
 293                             itr.remove();
 294                         } catch (Exception x) {
 295                             x.printStackTrace();
 296                         }
 297                     }
 298                 }
 299             }
 300 
 301         });
 302 
 303         System.out.println("copying/removing...");
 304         t0.start(); t1.start(); t2.start(); t3.start();
 305         t0.join(); t1.join(); t2.join(); t3.join();
 306 
 307         System.out.println("closing: fs1, fs2");
 308         fs1.close();
 309         fs2.close();
 310 
 311         int failed = 0;
 312         System.out.println("checkEqual: fs vs fs3");
 313         for (String path : files) {
 314             try {
 315                 checkEqual(fs.getPath(path), fs3.getPath(path));
 316             } catch (IOException x) {
 317                 //x.printStackTrace();
 318                 failed++;
 319             }
 320         }
 321         System.out.println("closing: fs3");
 322         fs3.close();
 323 
 324         System.out.println("opening: fs3 as fs4");
 325         FileSystem fs4 = newZipFileSystem(fs3Path, env);
 326 
 327 
 328         ArrayList<String> files2 = new ArrayList<>();
 329         ArrayList<String> dirs2 = new ArrayList<>();
 330         list(fs4.getPath("/"), files2, dirs2);
 331 
 332         System.out.println("checkEqual: fs vs fs4");
 333         for (String path : files2) {
 334             checkEqual(fs.getPath(path), fs4.getPath(path));
 335         }
 336         System.out.println("walking: fs4");
 337         walk(fs4.getPath("/"));
 338         System.out.println("closing: fs4");
 339         fs4.close();
 340         System.out.printf("failed=%d%n", failed);
 341 
 342         Files.delete(fs1Path);
 343         Files.delete(fs2Path);
 344         Files.delete(fs3Path);
 345     }
 346 
 347     // test file stamp
 348     static void testTime(Path src) throws Exception {
 349         BasicFileAttributes attrs = Files
 350                         .getFileAttributeView(src, BasicFileAttributeView.class)
 351                         .readAttributes();
 352         // create a new filesystem, copy this file into it
 353         Map<String, Object> env = new HashMap<String, Object>();
 354         env.put("create", "true");
 355         Path fsPath = getTempPath();
 356         FileSystem fs = newZipFileSystem(fsPath, env);
 357 
 358         System.out.println("test copy with timestamps...");
 359         // copyin
 360         Path dst = getPathWithParents(fs, "me");
 361         Files.copy(src, dst, COPY_ATTRIBUTES);
 362         checkEqual(src, dst);
 363         System.out.println("mtime: " + attrs.lastModifiedTime());
 364         System.out.println("ctime: " + attrs.creationTime());
 365         System.out.println("atime: " + attrs.lastAccessTime());
 366         System.out.println(" ==============>");
 367         BasicFileAttributes dstAttrs = Files
 368                         .getFileAttributeView(dst, BasicFileAttributeView.class)
 369                         .readAttributes();
 370         System.out.println("mtime: " + dstAttrs.lastModifiedTime());
 371         System.out.println("ctime: " + dstAttrs.creationTime());
 372         System.out.println("atime: " + dstAttrs.lastAccessTime());
 373 
 374         // 1-second granularity
 375         if (attrs.lastModifiedTime().to(TimeUnit.SECONDS) !=
 376             dstAttrs.lastModifiedTime().to(TimeUnit.SECONDS) ||
 377             attrs.lastAccessTime().to(TimeUnit.SECONDS) !=
 378             dstAttrs.lastAccessTime().to(TimeUnit.SECONDS) ||
 379             attrs.creationTime().to(TimeUnit.SECONDS) !=
 380             dstAttrs.creationTime().to(TimeUnit.SECONDS)) {
 381             throw new RuntimeException("Timestamp Copy Failed!");
 382         }
 383         Files.delete(fsPath);
 384     }
 385 
 386     private static FileSystem newZipFileSystem(Path path, Map<String, ?> env)
 387         throws Exception
 388     {
 389         return FileSystems.newFileSystem(
 390             new URI("jar", path.toUri().toString(), null), env, null);
 391     }
 392 
 393     private static Path getTempPath() throws IOException
 394     {
 395         File tmp = File.createTempFile("testzipfs_", "zip");
 396         tmp.delete();    // we need a clean path, no file
 397         return tmp.toPath();
 398     }
 399 
 400     private static void list(Path path, List<String> files, List<String> dirs )
 401         throws IOException
 402     {
 403         if (Files.isDirectory(path)) {
 404             try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
 405                 for (Path child : ds)
 406                     list(child, files, dirs);
 407             }
 408             dirs.add(path.toString());
 409         } else {
 410             files.add(path.toString());
 411         }
 412     }
 413 
 414     private static void z2zcopy(FileSystem src, FileSystem dst, String path,
 415                                 int method)
 416         throws IOException
 417     {
 418         Path srcPath = src.getPath(path);
 419         Path dstPath = dst.getPath(path);
 420 
 421         if (Files.isDirectory(srcPath)) {
 422             if (!Files.exists(dstPath)) {
 423                 try {
 424                     mkdirs(dstPath);
 425                 } catch (FileAlreadyExistsException x) {}
 426             }
 427             try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
 428                 for (Path child : ds) {
 429                     z2zcopy(src, dst,
 430                            path + (path.endsWith("/")?"":"/") + child.getFileName(),
 431                            method);
 432                 }
 433             }
 434         } else {
 435             try {
 436                 if (Files.exists(dstPath))
 437                     return;
 438                 switch (method) {
 439                 case 0:
 440                     Files.copy(srcPath, dstPath);
 441                     break;
 442                 case 1:
 443                     chCopy(srcPath, dstPath);
 444                     break;
 445                 case 2:
 446                     //fchCopy(srcPath, dstPath);
 447                     streamCopy(srcPath, dstPath);
 448                     break;
 449                 }
 450             } catch (FileAlreadyExistsException x) {}
 451         }
 452     }
 453 
 454     private static void z2zmove(FileSystem src, FileSystem dst, String path)
 455         throws IOException
 456     {
 457         Path srcPath = src.getPath(path);
 458         Path dstPath = dst.getPath(path);
 459 
 460         if (Files.isDirectory(srcPath)) {
 461             if (!Files.exists(dstPath))
 462                 mkdirs(dstPath);
 463             try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
 464                 for (Path child : ds) {
 465                     z2zmove(src, dst,
 466                             path + (path.endsWith("/")?"":"/") + child.getFileName());
 467                 }
 468             }
 469         } else {
 470             //System.out.println("moving..." + path);
 471             Path parent = dstPath.getParent();
 472             if (parent != null && Files.notExists(parent))
 473                 mkdirs(parent);
 474             Files.move(srcPath, dstPath);
 475         }
 476     }
 477 
 478     private static void walk(Path path) throws IOException
 479     {
 480         Files.walkFileTree(
 481             path,
 482             new SimpleFileVisitor<Path>() {
 483                 private int indent = 0;
 484                 private void indent() {
 485                     int n = 0;
 486                     while (n++ < indent)
 487                         System.out.printf(" ");
 488                 }
 489 
 490                 @Override
 491                 public FileVisitResult visitFile(Path file,
 492                                                  BasicFileAttributes attrs)
 493                 {
 494                     indent();
 495                     System.out.printf("%s%n", file.getFileName().toString());
 496                     return FileVisitResult.CONTINUE;
 497                 }
 498 
 499                 @Override
 500                 public FileVisitResult preVisitDirectory(Path dir,
 501                                                          BasicFileAttributes attrs)
 502                 {
 503                     indent();
 504                     System.out.printf("[%s]%n", dir.toString());
 505                     indent += 2;
 506                     return FileVisitResult.CONTINUE;
 507                 }
 508 
 509                 @Override
 510                 public FileVisitResult postVisitDirectory(Path dir,
 511                                                           IOException ioe)
 512                     throws IOException
 513                 {
 514                     indent -= 2;
 515                     return FileVisitResult.CONTINUE;
 516                 }
 517         });
 518     }
 519 
 520     private static void mkdirs(Path path) throws IOException {
 521         if (Files.exists(path))
 522             return;
 523         path = path.toAbsolutePath();
 524         Path parent = path.getParent();
 525         if (parent != null) {
 526             if (Files.notExists(parent))
 527                 mkdirs(parent);
 528         }
 529         Files.createDirectory(path);
 530     }
 531 
 532     private static void rmdirs(Path path) throws IOException {
 533         while (path != null && path.getNameCount() != 0) {
 534             Files.delete(path);
 535             path = path.getParent();
 536         }
 537     }
 538 
 539     // check the content of two paths are equal
 540     private static void checkEqual(Path src, Path dst) throws IOException
 541     {
 542         //System.out.printf("checking <%s> vs <%s>...%n",
 543         //                  src.toString(), dst.toString());
 544 
 545         //streams
 546         byte[] bufSrc = new byte[8192];
 547         byte[] bufDst = new byte[8192];
 548         try (InputStream isSrc = Files.newInputStream(src);
 549              InputStream isDst = Files.newInputStream(dst))
 550         {
 551             int nSrc = 0;
 552             while ((nSrc = isSrc.read(bufSrc)) != -1) {
 553                 int nDst = 0;
 554                 while (nDst < nSrc) {
 555                     int n = isDst.read(bufDst, nDst, nSrc - nDst);
 556                     if (n == -1) {
 557                         System.out.printf("checking <%s> vs <%s>...%n",
 558                                           src.toString(), dst.toString());
 559                         throw new RuntimeException("CHECK FAILED!");
 560                     }
 561                     nDst += n;
 562                 }
 563                 while (--nSrc >= 0) {
 564                     if (bufSrc[nSrc] != bufDst[nSrc]) {
 565                         System.out.printf("checking <%s> vs <%s>...%n",
 566                                           src.toString(), dst.toString());
 567                         throw new RuntimeException("CHECK FAILED!");
 568                     }
 569                     nSrc--;
 570                 }
 571             }
 572         }
 573 
 574         // channels
 575         try (SeekableByteChannel chSrc = Files.newByteChannel(src);
 576              SeekableByteChannel chDst = Files.newByteChannel(dst))
 577         {
 578             if (chSrc.size() != chDst.size()) {
 579                 System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
 580                                   chSrc.toString(), chSrc.size(),
 581                                   chDst.toString(), chDst.size());
 582                 throw new RuntimeException("CHECK FAILED!");
 583             }
 584             ByteBuffer bbSrc = ByteBuffer.allocate(8192);
 585             ByteBuffer bbDst = ByteBuffer.allocate(8192);
 586 
 587             int nSrc = 0;
 588             while ((nSrc = chSrc.read(bbSrc)) != -1) {
 589                 int nDst = chDst.read(bbDst);
 590                 if (nSrc != nDst) {
 591                     System.out.printf("checking <%s> vs <%s>...%n",
 592                                       src.toString(), dst.toString());
 593                     throw new RuntimeException("CHECK FAILED!");
 594                 }
 595                 while (--nSrc >= 0) {
 596                     if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
 597                         System.out.printf("checking <%s> vs <%s>...%n",
 598                                           src.toString(), dst.toString());
 599                         throw new RuntimeException("CHECK FAILED!");
 600                     }
 601                     nSrc--;
 602                 }
 603                 bbSrc.flip();
 604                 bbDst.flip();
 605             }
 606 
 607             // Check if source read position is at the end
 608             if (chSrc.position() != chSrc.size()) {
 609                 System.out.printf("src[%s]: size=%d, position=%d%n",
 610                                   chSrc.toString(), chSrc.size(), chSrc.position());
 611                 throw new RuntimeException("CHECK FAILED!");
 612             }
 613 
 614             // Check if destination read position is at the end
 615             if (chDst.position() != chDst.size()) {
 616                 System.out.printf("dst[%s]: size=%d, position=%d%n",
 617                                   chDst.toString(), chDst.size(), chDst.position());
 618                 throw new RuntimeException("CHECK FAILED!");
 619             }
 620         } catch (IOException x) {
 621             x.printStackTrace();
 622         }
 623     }
 624 
 625     private static void fchCopy(Path src, Path dst) throws IOException
 626     {
 627         Set<OpenOption> read = new HashSet<>();
 628         read.add(READ);
 629         Set<OpenOption> openwrite = new HashSet<>();
 630         openwrite.add(CREATE_NEW);
 631         openwrite.add(WRITE);
 632 
 633         try (FileChannel srcFc = src.getFileSystem()
 634                                     .provider()
 635                                     .newFileChannel(src, read);
 636              FileChannel dstFc = dst.getFileSystem()
 637                                     .provider()
 638                                     .newFileChannel(dst, openwrite))
 639         {
 640             ByteBuffer bb = ByteBuffer.allocate(8192);
 641             while (srcFc.read(bb) >= 0) {
 642                 bb.flip();
 643                 dstFc.write(bb);
 644                 bb.clear();
 645             }
 646         }
 647     }
 648 
 649     private static void chCopy(Path src, Path dst) throws IOException
 650     {
 651         Set<OpenOption> read = new HashSet<>();
 652         read.add(READ);
 653         Set<OpenOption> openwrite = new HashSet<>();
 654         openwrite.add(CREATE_NEW);
 655         openwrite.add(WRITE);
 656 
 657         try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
 658              SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
 659         {
 660 
 661             ByteBuffer bb = ByteBuffer.allocate(8192);
 662             while (srcCh.read(bb) >= 0) {
 663                 bb.flip();
 664                 dstCh.write(bb);
 665                 bb.clear();
 666             }
 667 
 668             // Check if source read position is at the end
 669             if (srcCh.position() != srcCh.size()) {
 670                 System.out.printf("src[%s]: size=%d, position=%d%n",
 671                                   srcCh.toString(), srcCh.size(), srcCh.position());
 672                 throw new RuntimeException("CHECK FAILED!");
 673             }
 674 
 675             // Check if destination write position is at the end
 676             if (dstCh.position() != dstCh.size()) {
 677                 System.out.printf("dst[%s]: size=%d, position=%d%n",
 678                                   dstCh.toString(), dstCh.size(), dstCh.position());
 679                 throw new RuntimeException("CHECK FAILED!");
 680             }
 681         }
 682     }
 683 
 684     private static void streamCopy(Path src, Path dst) throws IOException
 685     {
 686         byte[] buf = new byte[8192];
 687         try (InputStream isSrc = Files.newInputStream(src);
 688              OutputStream osDst = Files.newOutputStream(dst))
 689         {
 690             int n = 0;
 691             while ((n = isSrc.read(buf)) != -1) {
 692                 osDst.write(buf, 0, n);
 693             }
 694         }
 695     }
 696 
 697     static void channel(FileSystem fs, Path path)
 698         throws Exception
 699     {
 700         System.out.println("test ByteChannel...");
 701         Set<OpenOption> read = new HashSet<>();
 702         read.add(READ);
 703         int n = 0;
 704         ByteBuffer bb = null;
 705         ByteBuffer bb2 = null;
 706         int N = 120;
 707 
 708         try (SeekableByteChannel sbc = Files.newByteChannel(path)) {
 709             System.out.printf("   sbc[0]: pos=%d, size=%d%n", sbc.position(), sbc.size());
 710             if (sbc.position() != 0) {
 711                 throw new RuntimeException("CHECK FAILED!");
 712             }
 713 
 714             bb = ByteBuffer.allocate((int)sbc.size());
 715             n = sbc.read(bb);
 716             System.out.printf("   sbc[1]: read=%d, pos=%d, size=%d%n",
 717                               n, sbc.position(), sbc.size());
 718             if (sbc.position() != sbc.size()) {
 719                 throw new RuntimeException("CHECK FAILED!");
 720             }
 721             bb2 = ByteBuffer.allocate((int)sbc.size());
 722         }
 723 
 724         // sbc.position(pos) is not supported in current version
 725         // try the FileChannel
 726         try (SeekableByteChannel sbc = fs.provider().newFileChannel(path, read)) {
 727             sbc.position(N);
 728             System.out.printf("   sbc[2]: pos=%d, size=%d%n",
 729                               sbc.position(), sbc.size());
 730             if (sbc.position() != N) {
 731                 throw new RuntimeException("CHECK FAILED!");
 732             }
 733             bb2.limit(100);
 734             n = sbc.read(bb2);
 735             System.out.printf("   sbc[3]: read=%d, pos=%d, size=%d%n",
 736                               n, sbc.position(), sbc.size());
 737             if (n < 0 || sbc.position() != (N + n)) {
 738                 throw new RuntimeException("CHECK FAILED!");
 739             }
 740             System.out.printf("   sbc[4]: bb[%d]=%d, bb1[0]=%d%n",
 741                               N, bb.get(N) & 0xff, bb2.get(0) & 0xff);
 742         }
 743     }
 744 
 745     // create parents if does not exist
 746     static Path getPathWithParents(FileSystem fs, String name)
 747         throws Exception
 748     {
 749         Path path = fs.getPath(name);
 750         Path parent = path.getParent();
 751         if (parent != null && Files.notExists(parent))
 752             mkdirs(parent);
 753         return path;
 754     }
 755 }