1 /*
   2  * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved.
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  *
   8  *   - Redistributions of source code must retain the above copyright
   9  *     notice, this list of conditions and the following disclaimer.
  10  *
  11  *   - Redistributions in binary form must reproduce the above copyright
  12  *     notice, this list of conditions and the following disclaimer in the
  13  *     documentation and/or other materials provided with the distribution.
  14  *
  15  *   - Neither the name of Oracle nor the names of its
  16  *     contributors may be used to endorse or promote products derived
  17  *     from this software without specific prior written permission.
  18  *
  19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30  */
  31 
  32 /*
  33  * This source code is provided to illustrate the usage of a given feature
  34  * or technique and has been deliberately simplified. Additional steps
  35  * required for a production-quality application, such as security checks,
  36  * input validation and proper error handling, might not be present in
  37  * this sample code.
  38  */
  39 
  40 
  41 import java.io.*;
  42 import java.nio.*;
  43 import java.nio.channels.*;
  44 import java.nio.file.*;
  45 import java.nio.file.spi.*;
  46 import java.nio.file.attribute.*;
  47 import java.net.*;
  48 import java.text.DateFormat;
  49 import java.text.SimpleDateFormat;
  50 import java.util.*;
  51 
  52 import static java.nio.file.StandardOpenOption.*;
  53 import static java.nio.file.StandardCopyOption.*;
  54 /*
  55  * ZipFileSystem usage demo
  56  *
  57  * java Demo action ZipfileName [...]
  58  *
  59  * @author Xueming Shen
  60  */
  61 
  62 public class Demo {
  63 
  64     static enum Action {
  65         rename,          // <java Demo rename zipfile src dst>
  66                          // rename entry src to dst inside zipfile
  67 
  68         movein,          // <java Demo movein zipfile src dst>
  69                          // move an external src file into zipfile
  70                          // as entry dst
  71 
  72         moveout,         // <java Demo moveout zipfile src dst>
  73                          // move a zipfile entry src out to dst
  74 
  75         copy,            // <java Demo copy zipfile src dst>
  76                          // copy entry src to dst inside zipfile
  77 
  78         copyin,          // <java Demo copyin zipfile src dst>
  79                          // copy an external src file into zipfile
  80                          // as entry dst
  81 
  82         copyin_attrs,    // <java Demo copyin_attrs zipfile src dst>
  83                          // copy an external src file into zipfile
  84                          // as entry dst, with attributes (timestamp)
  85 
  86         copyout,         // <java Demo copyout zipfile src dst>
  87                          // copy zipfile entry src" out to file dst
  88 
  89         copyout_attrs,   // <java Demo copyout_attrs zipfile src dst>
  90 
  91         zzmove,          // <java Demo zzmove zfsrc zfdst path>
  92                          // move entry path/dir from zfsrc to zfdst
  93 
  94         zzcopy,          // <java Demo zzcopy zfsrc zfdst path>
  95                          // copy path from zipfile zfsrc to zipfile
  96                          // zfdst
  97 
  98         attrs,           // <java Demo attrs zipfile path>
  99                          // printout the attributes of entry path
 100 
 101         attrsspace,      // <java Demo attrsspace zipfile path>
 102                          // printout the storespace attrs of entry path
 103 
 104         setmtime,        // <java Demo setmtime zipfile "MM/dd/yy-HH:mm:ss" path...>
 105                          // set the lastModifiedTime of entry path
 106 
 107         setatime,        // <java Demo setatime zipfile "MM/dd/yy-HH:mm:ss" path...>
 108         setctime,        // <java Demo setctime zipfile "MM/dd/yy-HH:mm:ss" path...>
 109 
 110         lsdir,           // <java Demo lsdir zipfile dir>
 111                          // list dir's direct child files/dirs
 112 
 113         mkdir,           // <java Demo mkdir zipfile dir>
 114 
 115         mkdirs,          // <java Demo mkdirs zipfile dir>
 116 
 117         rmdirs,          // <java Demo rmdirs zipfile dir>
 118 
 119         list,            // <java Demo list zipfile [dir]>
 120                          // recursively list all entries of dir
 121                          // via DirectoryStream
 122 
 123         tlist,           // <java Demo tlist zipfile [dir]>
 124                          // list with buildDirTree=true
 125 
 126         vlist,           // <java Demo vlist zipfile [dir]>
 127                          // recursively verbose list all entries of
 128                          // dir via DirectoryStream
 129 
 130         walk,            // <java Demo walk zipfile [dir]>
 131                          // recursively walk all entries of dir
 132                          // via Files.walkFileTree
 133 
 134         twalk,           // <java Demo twalk zipfile [dir]>
 135                          // walk with buildDirTree=true
 136 
 137         extract,         // <java Demo extract zipfile file [...]>
 138 
 139         update,          // <java Demo extract zipfile file [...]>
 140 
 141         delete,          // <java Demo delete zipfile file [...]>
 142 
 143         add,             // <java Demo add zipfile file [...]>
 144 
 145         create,          // <java Demo create zipfile file [...]>
 146                          // create a new zipfile if it doesn't exit
 147                          // and then add the file(s) into it.
 148 
 149         attrs2,          // <java Demo attrs2 zipfile file [...]>
 150                          // test different ways to print attrs
 151 
 152         prof,
 153     }
 154 
 155     public static void main(String[] args) throws Throwable {
 156         FileSystemProvider provider = getZipFSProvider();
 157         if (provider == null) {
 158             System.err.println("ZIP filesystem provider is not installed");
 159             System.exit(1);
 160         }
 161 
 162         Action action = Action.valueOf(args[0]);
 163         Map<String, Object> env = env = new HashMap<>();
 164         if (action == Action.create)
 165             env.put("create", "true");
 166         try (FileSystem fs = provider.newFileSystem(Paths.get(args[1]), env)) {
 167             Path path, src, dst;
 168             switch (action) {
 169             case rename:
 170                 src = fs.getPath(args[2]);
 171                 dst = fs.getPath(args[3]);
 172                 Files.move(src, dst);
 173                 break;
 174             case moveout:
 175                 src = fs.getPath(args[2]);
 176                 dst = Paths.get(args[3]);
 177                 Files.move(src, dst);
 178                 break;
 179             case movein:
 180                 src = Paths.get(args[2]);
 181                 dst = fs.getPath(args[3]);
 182                 Files.move(src, dst);
 183                 break;
 184             case copy:
 185                 src = fs.getPath(args[2]);
 186                 dst = fs.getPath(args[3]);
 187                 Files.copy(src, dst);
 188                 break;
 189             case copyout:
 190                 src = fs.getPath(args[2]);
 191                 dst = Paths.get(args[3]);
 192                 Files.copy(src, dst);
 193                 break;
 194             case copyin:
 195                 src = Paths.get(args[2]);
 196                 dst = fs.getPath(args[3]);
 197                 Files.copy(src, dst);
 198                 break;
 199             case copyin_attrs:
 200                 src = Paths.get(args[2]);
 201                 dst = fs.getPath(args[3]);
 202                 Files.copy(src, dst, COPY_ATTRIBUTES);
 203                 break;
 204             case copyout_attrs:
 205                 src = fs.getPath(args[2]);
 206                 dst = Paths.get(args[3]);
 207                 Files.copy(src, dst, COPY_ATTRIBUTES);
 208                 break;
 209             case zzmove:
 210                 try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
 211                     z2zmove(fs, fs2, args[3]);
 212                 }
 213                 break;
 214             case zzcopy:
 215                 try (FileSystem fs2 = provider.newFileSystem(Paths.get(args[2]), env)) {
 216                     z2zcopy(fs, fs2, args[3]);
 217                 }
 218                 break;
 219             case attrs:
 220                 for (int i = 2; i < args.length; i++) {
 221                     path = fs.getPath(args[i]);
 222                     System.out.println(path);
 223                     System.out.println(
 224                         Files.readAttributes(path, BasicFileAttributes.class).toString());
 225                 }
 226                 break;
 227             case setmtime:
 228                 DateFormat df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
 229                 Date newDatetime = df.parse(args[2]);
 230                 for (int i = 3; i < args.length; i++) {
 231                     path = fs.getPath(args[i]);
 232                     Files.setAttribute(path, "lastModifiedTime",
 233                                        FileTime.fromMillis(newDatetime.getTime()));
 234                     System.out.println(
 235                         Files.readAttributes(path, BasicFileAttributes.class).toString());
 236                 }
 237                 break;
 238             case setctime:
 239                 df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
 240                 newDatetime = df.parse(args[2]);
 241                 for (int i = 3; i < args.length; i++) {
 242                     path = fs.getPath(args[i]);
 243                     Files.setAttribute(path, "creationTime",
 244                                        FileTime.fromMillis(newDatetime.getTime()));
 245                     System.out.println(
 246                         Files.readAttributes(path, BasicFileAttributes.class).toString());
 247                 }
 248                 break;
 249             case setatime:
 250                 df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss");
 251                 newDatetime = df.parse(args[2]);
 252                 for (int i = 3; i < args.length; i++) {
 253                     path = fs.getPath(args[i]);
 254                     Files.setAttribute(path, "lastAccessTime",
 255                                        FileTime.fromMillis(newDatetime.getTime()));
 256                     System.out.println(
 257                         Files.readAttributes(path, BasicFileAttributes.class).toString());
 258                 }
 259                 break;
 260             case attrsspace:
 261                 path = fs.getPath("/");
 262                 FileStore fstore = Files.getFileStore(path);
 263                 System.out.printf("filestore[%s]%n", fstore.name());
 264                 System.out.printf("    totalSpace: %d%n",
 265                                   (Long)fstore.getAttribute("totalSpace"));
 266                 System.out.printf("   usableSpace: %d%n",
 267                                   (Long)fstore.getAttribute("usableSpace"));
 268                 System.out.printf("  unallocSpace: %d%n",
 269                                   (Long)fstore.getAttribute("unallocatedSpace"));
 270                 break;
 271             case list:
 272             case tlist:
 273                 if (args.length < 3)
 274                     list(fs.getPath("/"), false);
 275                 else
 276                     list(fs.getPath(args[2]), false);
 277                 break;
 278             case vlist:
 279                 if (args.length < 3)
 280                     list(fs.getPath("/"), true);
 281                 else
 282                     list(fs.getPath(args[2]), true);
 283                 break;
 284             case twalk:
 285             case walk:
 286                 walk(fs.getPath((args.length > 2)? args[2] : "/"));
 287                 break;
 288             case extract:
 289                 if (args.length == 2) {
 290                      extract(fs, "/");
 291                 } else {
 292                     for (int i = 2; i < args.length; i++) {
 293                         extract(fs, args[i]);
 294                     }
 295                 }
 296                 break;
 297             case delete:
 298                 for (int i = 2; i < args.length; i++)
 299                     Files.delete(fs.getPath(args[i]));
 300                 break;
 301             case create:
 302             case add:
 303             case update:
 304                 for (int i = 2; i < args.length; i++) {
 305                     update(fs, args[i]);
 306                 }
 307                 break;
 308             case lsdir:
 309                 path = fs.getPath(args[2]);
 310                 final String fStr = (args.length > 3)?args[3]:"";
 311                 try (DirectoryStream<Path> ds = Files.newDirectoryStream(path,
 312                     new DirectoryStream.Filter<Path>() {
 313                         @Override
 314                         public boolean accept(Path path) {
 315                             return path.toString().contains(fStr);
 316                         }
 317                     }))
 318                 {
 319                     for (Path p : ds)
 320                         System.out.println(p);
 321                 }
 322                 break;
 323             case mkdir:
 324                 Files.createDirectory(fs.getPath(args[2]));
 325                 break;
 326             case mkdirs:
 327                 mkdirs(fs.getPath(args[2]));
 328                 break;
 329             case attrs2:
 330                 for (int i = 2; i < args.length; i++) {
 331                     path = fs.getPath(args[i]);
 332                     System.out.printf("%n%s%n", path);
 333                     System.out.println("-------(1)---------");
 334                     System.out.println(
 335                         Files.readAttributes(path, BasicFileAttributes.class).toString());
 336                     System.out.println("-------(2)---------");
 337                     Map<String, Object> map = Files.readAttributes(path, "zip:*");
 338                     for (Map.Entry<String, Object> e : map.entrySet()) {
 339                         System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
 340                     }
 341                     System.out.println("-------(3)---------");
 342                     map = Files.readAttributes(path, "size,lastModifiedTime,isDirectory");
 343                     for (Map.Entry<String, ?> e : map.entrySet()) {
 344                         System.out.printf("    %s : %s%n", e.getKey(), e.getValue());
 345                     }
 346                 }
 347                 break;
 348             case prof:
 349                 list(fs.getPath("/"), false);
 350                 while (true) {
 351                     Thread.sleep(10000);
 352                     //list(fs.getPath("/"), true);
 353                     System.out.println("sleeping...");
 354                 }
 355             }
 356         } catch (Exception x) {
 357             x.printStackTrace();
 358         }
 359     }
 360 
 361     private static FileSystemProvider getZipFSProvider() {
 362         for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
 363             if ("jar".equals(provider.getScheme()))
 364                 return provider;
 365         }
 366         return null;
 367     }
 368 
 369     @SuppressWarnings("unused")
 370     /**
 371      * Not used in demo, but included for demonstrational purposes.
 372      */
 373     private static byte[] getBytes(String name) {
 374         return name.getBytes();
 375     }
 376 
 377     @SuppressWarnings("unused")
 378     /**
 379      * Not used in demo, but included for demonstrational purposes.
 380      */
 381     private static String getString(byte[] name) {
 382         return new String(name);
 383     }
 384 
 385     private static void walk(Path path) throws IOException
 386     {
 387         Files.walkFileTree(
 388             path,
 389             new SimpleFileVisitor<Path>() {
 390                 private int indent = 0;
 391                 private void indent() {
 392                     int n = 0;
 393                     while (n++ < indent)
 394                         System.out.printf(" ");
 395                 }
 396 
 397                 @Override
 398                 public FileVisitResult visitFile(Path file,
 399                                                  BasicFileAttributes attrs)
 400                 {
 401                     indent();
 402                     System.out.printf("%s%n", file.getFileName().toString());
 403                     return FileVisitResult.CONTINUE;
 404                 }
 405 
 406                 @Override
 407                 public FileVisitResult preVisitDirectory(Path dir,
 408                                                          BasicFileAttributes attrs)
 409                 {
 410                     indent();
 411                     System.out.printf("[%s]%n", dir.toString());
 412                     indent += 2;
 413                     return FileVisitResult.CONTINUE;
 414                 }
 415 
 416                 @Override
 417                 public FileVisitResult postVisitDirectory(Path dir,
 418                                                           IOException ioe)
 419                 {
 420                     indent -= 2;
 421                     return FileVisitResult.CONTINUE;
 422                 }
 423         });
 424     }
 425 
 426     private static void update(FileSystem fs, String path) throws Throwable{
 427         Path src = FileSystems.getDefault().getPath(path);
 428         if (Files.isDirectory(src)) {
 429             try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
 430                 for (Path child : ds)
 431                     update(fs, child.toString());
 432             }
 433         } else {
 434             Path dst = fs.getPath(path);
 435             Path parent = dst.getParent();
 436             if (parent != null && Files.notExists(parent))
 437                 mkdirs(parent);
 438             Files.copy(src, dst, REPLACE_EXISTING);
 439         }
 440     }
 441 
 442     private static void extract(FileSystem fs, String path) throws Throwable{
 443         Path src = fs.getPath(path);
 444         if (Files.isDirectory(src)) {
 445             try (DirectoryStream<Path> ds = Files.newDirectoryStream(src)) {
 446                 for (Path child : ds)
 447                     extract(fs, child.toString());
 448             }
 449         } else {
 450             if (path.startsWith("/"))
 451                 path = path.substring(1);
 452             Path dst = FileSystems.getDefault().getPath(path);
 453             Path parent = dst.getParent();
 454             if (Files.notExists(parent))
 455                 mkdirs(parent);
 456             Files.copy(src, dst, REPLACE_EXISTING);
 457         }
 458     }
 459 
 460     // use DirectoryStream
 461     private static void z2zcopy(FileSystem src, FileSystem dst, String path)
 462         throws IOException
 463     {
 464         Path srcPath = src.getPath(path);
 465         Path dstPath = dst.getPath(path);
 466 
 467         if (Files.isDirectory(srcPath)) {
 468             if (!Files.exists(dstPath)) {
 469                 try {
 470                     mkdirs(dstPath);
 471                 } catch (FileAlreadyExistsException x) {}
 472             }
 473             try (DirectoryStream<Path> ds = Files.newDirectoryStream(srcPath)) {
 474                 for (Path child : ds) {
 475                     z2zcopy(src, dst,
 476                             path + (path.endsWith("/")?"":"/") + child.getFileName());
 477                 }
 478             }
 479         } else {
 480             //System.out.println("copying..." + path);
 481             Files.copy(srcPath, dstPath);
 482         }
 483     }
 484 
 485     // use TreeWalk to move
 486     private static void z2zmove(FileSystem src, FileSystem dst, String path)
 487         throws IOException
 488     {
 489         final Path srcPath = src.getPath(path).toAbsolutePath();
 490         final Path dstPath = dst.getPath(path).toAbsolutePath();
 491 
 492         Files.walkFileTree(srcPath, new SimpleFileVisitor<Path>() {
 493 
 494             @Override
 495             public FileVisitResult visitFile(Path file,
 496                                             BasicFileAttributes attrs)
 497             {
 498                 Path dst = srcPath.relativize(file);
 499                 dst = dstPath.resolve(dst);
 500                 try {
 501                     Path parent = dstPath.getParent();
 502                     if (parent != null && Files.notExists(parent))
 503                         mkdirs(parent);
 504                     Files.move(file, dst);
 505                 } catch (IOException x) {
 506                     x.printStackTrace();
 507                 }
 508                 return FileVisitResult.CONTINUE;
 509             }
 510 
 511             @Override
 512             public FileVisitResult preVisitDirectory(Path dir,
 513                                                      BasicFileAttributes attrs)
 514             {
 515                 Path dst = srcPath.relativize(dir);
 516                 dst = dstPath.resolve(dst);
 517                 try {
 518 
 519                     if (Files.notExists(dst))
 520                         mkdirs(dst);
 521                 } catch (IOException x) {
 522                     x.printStackTrace();
 523                 }
 524                 return FileVisitResult.CONTINUE;
 525             }
 526 
 527             @Override
 528             public FileVisitResult postVisitDirectory(Path dir,
 529                                                       IOException ioe)
 530                 throws IOException
 531             {
 532                 try {
 533                     Files.delete(dir);
 534                 } catch (IOException x) {
 535                     //x.printStackTrace();
 536                 }
 537                 return FileVisitResult.CONTINUE;
 538             }
 539         });
 540 
 541     }
 542 
 543     private static void mkdirs(Path path) throws IOException {
 544         path = path.toAbsolutePath();
 545         Path parent = path.getParent();
 546         if (parent != null) {
 547             if (Files.notExists(parent))
 548                 mkdirs(parent);
 549         }
 550         Files.createDirectory(path);
 551     }
 552 
 553     @SuppressWarnings("unused")
 554     /**
 555      * Not used in demo, but included for demonstrational purposes.
 556      */
 557     private static void rmdirs(Path path) throws IOException {
 558         while (path != null && path.getNameCount() != 0) {
 559             Files.delete(path);
 560             path = path.getParent();
 561         }
 562     }
 563 
 564     private static void list(Path path, boolean verbose ) throws IOException {
 565         if (!"/".equals(path.toString())) {
 566            System.out.printf("  %s%n", path.toString());
 567            if (verbose)
 568                 System.out.println(Files.readAttributes(path, BasicFileAttributes.class).toString());
 569         }
 570         if (Files.notExists(path))
 571             return;
 572         if (Files.isDirectory(path)) {
 573             try (DirectoryStream<Path> ds = Files.newDirectoryStream(path)) {
 574                 for (Path child : ds)
 575                     list(child, verbose);
 576             }
 577         }
 578     }
 579 
 580     @SuppressWarnings("unused")
 581     /**
 582      * Checks that the content of two paths are equal.
 583      * Not used in demo, but included for demonstrational purposes.
 584      */
 585     private static void checkEqual(Path src, Path dst) throws IOException
 586     {
 587         //System.out.printf("checking <%s> vs <%s>...%n",
 588         //                  src.toString(), dst.toString());
 589 
 590         //streams
 591         byte[] bufSrc = new byte[8192];
 592         byte[] bufDst = new byte[8192];
 593         try (InputStream isSrc = Files.newInputStream(src);
 594              InputStream isDst = Files.newInputStream(dst))
 595         {
 596             int nSrc = 0;
 597             while ((nSrc = isSrc.read(bufSrc)) != -1) {
 598                 int nDst = 0;
 599                 while (nDst < nSrc) {
 600                     int n = isDst.read(bufDst, nDst, nSrc - nDst);
 601                     if (n == -1) {
 602                         System.out.printf("checking <%s> vs <%s>...%n",
 603                                           src.toString(), dst.toString());
 604                         throw new RuntimeException("CHECK FAILED!");
 605                     }
 606                     nDst += n;
 607                 }
 608                 while (--nSrc >= 0) {
 609                     if (bufSrc[nSrc] != bufDst[nSrc]) {
 610                         System.out.printf("checking <%s> vs <%s>...%n",
 611                                           src.toString(), dst.toString());
 612                         throw new RuntimeException("CHECK FAILED!");
 613                     }
 614                     nSrc--;
 615                 }
 616             }
 617         }
 618 
 619         // channels
 620 
 621         try (SeekableByteChannel chSrc = Files.newByteChannel(src);
 622              SeekableByteChannel chDst = Files.newByteChannel(dst))
 623         {
 624             if (chSrc.size() != chDst.size()) {
 625                 System.out.printf("src[%s].size=%d, dst[%s].size=%d%n",
 626                                   chSrc.toString(), chSrc.size(),
 627                                   chDst.toString(), chDst.size());
 628                 throw new RuntimeException("CHECK FAILED!");
 629             }
 630             ByteBuffer bbSrc = ByteBuffer.allocate(8192);
 631             ByteBuffer bbDst = ByteBuffer.allocate(8192);
 632 
 633             int nSrc = 0;
 634             while ((nSrc = chSrc.read(bbSrc)) != -1) {
 635                 int nDst = chDst.read(bbDst);
 636                 if (nSrc != nDst) {
 637                     System.out.printf("checking <%s> vs <%s>...%n",
 638                                       src.toString(), dst.toString());
 639                     throw new RuntimeException("CHECK FAILED!");
 640                 }
 641                 while (--nSrc >= 0) {
 642                     if (bbSrc.get(nSrc) != bbDst.get(nSrc)) {
 643                         System.out.printf("checking <%s> vs <%s>...%n",
 644                                           src.toString(), dst.toString());
 645                         throw new RuntimeException("CHECK FAILED!");
 646                     }
 647                     nSrc--;
 648                 }
 649                 bbSrc.flip();
 650                 bbDst.flip();
 651             }
 652         } catch (IOException x) {
 653             x.printStackTrace();
 654         }
 655     }
 656 
 657     private static void fchCopy(Path src, Path dst) throws IOException
 658     {
 659         Set<OpenOption> read = new HashSet<>();
 660         read.add(READ);
 661         Set<OpenOption> openwrite = new HashSet<>();
 662         openwrite.add(CREATE_NEW);
 663         openwrite.add(WRITE);
 664 
 665         try (FileChannel srcFc = src.getFileSystem().provider().newFileChannel(src, read);
 666              FileChannel dstFc = dst.getFileSystem().provider().newFileChannel(dst, openwrite))
 667         {
 668             ByteBuffer bb = ByteBuffer.allocate(8192);
 669             while (srcFc.read(bb) >= 0) {
 670                 bb.flip();
 671                 dstFc.write(bb);
 672                 bb.clear();
 673             }
 674         }
 675     }
 676 
 677     private static void chCopy(Path src, Path dst) throws IOException
 678     {
 679         Set<OpenOption> read = new HashSet<>();
 680         read.add(READ);
 681         Set<OpenOption> openwrite = new HashSet<>();
 682         openwrite.add(CREATE_NEW);
 683         openwrite.add(WRITE);
 684 
 685         try (SeekableByteChannel srcCh = Files.newByteChannel(src, read);
 686              SeekableByteChannel dstCh = Files.newByteChannel(dst, openwrite))
 687         {
 688             ByteBuffer bb = ByteBuffer.allocate(8192);
 689             while (srcCh.read(bb) >= 0) {
 690                 bb.flip();
 691                 dstCh.write(bb);
 692                 bb.clear();
 693             }
 694         }
 695     }
 696 
 697     private static void streamCopy(Path src, Path dst) throws IOException
 698     {
 699         byte[] buf = new byte[8192];
 700         try (InputStream isSrc = Files.newInputStream(src);
 701              OutputStream osDst = Files.newOutputStream(dst))
 702         {
 703             int n = 0;
 704             while ((n = isSrc.read(buf)) != -1) {
 705                 osDst.write(buf, 0, n);
 706             }
 707         }
 708     }
 709 }