예제 #1
0
  /**
   * Copies a source file to a destination file, optionally preserving the source's last
   * modification time. We already have an input stream to read the source file, but we know nothing
   * about the destination file yet. Note that this method <em>never</em> closes the given input
   * stream!
   *
   * @throws FileNotFoundException If either the source or the destination cannot get accessed.
   * @throws InputIOException If copying the data fails because of an IOException in the source.
   * @throws IOException If copying the data fails because of an IOException in the destination.
   */
  private static void cp0(
      final boolean preserve, final java.io.File src, final InputStream in, final java.io.File dst)
      throws IOException {
    try {
      if (dst instanceof File) {
        final File dstFile = (File) dst;
        dstFile.ensureNotVirtualRoot("cannot write");
        final String dstEntryName = dstFile.getEnclEntryName();
        if (dstEntryName != null) {
          cp0(preserve, src, in, dstFile.getEnclArchive().getArchiveController(), dstEntryName);
          return;
        }
      }
    } catch (RfsEntryFalsePositiveException dstIsNotArchive) {
    }

    // Treat the destination like a regular file.
    final OutputStream out = new java.io.FileOutputStream(dst);
    try {
      Streams.cat(in, out);
    } finally {
      out.close();
    }
    if (preserve && !dst.setLastModified(src.lastModified()))
      throw new IOException(dst.getPath() + " (cannot preserve last modification time)");
  }
예제 #2
0
  /** Unchecked parameters version. */
  private static void cp0(final boolean preserve, final java.io.File src, final java.io.File dst)
      throws IOException {
    assert src != null;
    assert dst != null;

    try {
      try {
        if (src instanceof File) {
          final File srcFile = (File) src;
          srcFile.ensureNotVirtualRoot("cannot read");
          final String srcEntryName = srcFile.getEnclEntryName();
          if (srcEntryName != null) {
            cp0(preserve, srcFile.getEnclArchive().getArchiveController(), srcEntryName, dst);
            return;
          }
        }
      } catch (RfsEntryFalsePositiveException srcIsNotArchive) {
      }

      // Treat the source like a regular file.
      final InputStream in = new java.io.FileInputStream(src);
      try {
        cp0(preserve, src, in, dst);
      } finally {
        try {
          in.close();
        } catch (IOException ex) {
          throw new InputIOException(ex);
        }
      }
    } catch (FileNotFoundException ex) {
      throw ex;
    } catch (ArchiveBusyException ex) {
      throw new FileBusyException(ex);
    } catch (ArchiveFileSystemException afse) {
      final FileNotFoundException fnfe = new FileNotFoundException(afse.toString());
      fnfe.initCause(afse);
      throw fnfe;
    } catch (IOException ex) {
      dst.delete();
      throw ex;
    }
  }
예제 #3
0
  /**
   * Copies a source file to a destination file, optionally preserving the source's last
   * modification time. We know that the source file appears to be an entry in an archive file, but
   * we know nothing about the destination file yet.
   *
   * <p>Note that this method synchronizes on the class object in order to prevent dead locks by two
   * threads copying archive entries to the other's source archive concurrently!
   *
   * @throws FalsePositiveException If the source or the destination is a false positive and the
   *     exception cannot get resolved within this method.
   * @throws InputIOException If copying the data fails because of an IOException in the source.
   * @throws IOException If copying the data fails because of an IOException in the destination.
   */
  private static void cp0(
      final boolean preserve,
      final ArchiveController srcController,
      final String srcEntryName,
      final java.io.File dst)
      throws IOException {
    // Do not assume anything about the lock status of the controller:
    // This method may be called from a subclass while a lock is acquired!
    // assert !srcController.readLock().isLocked();
    // assert !srcController.writeLock().isLocked();

    try {
      try {
        if (dst instanceof File) {
          final File dstFile = (File) dst;
          dstFile.ensureNotVirtualRoot("cannot write");
          final String dstEntryName = dstFile.getEnclEntryName();
          if (dstEntryName != null) {
            cp0(
                preserve,
                srcController,
                srcEntryName,
                dstFile.getEnclArchive().getArchiveController(),
                dstEntryName);
            return;
          }
        }
      } catch (RfsEntryFalsePositiveException isNotArchive) {
        // Both the source and/or the destination may be false positives,
        // so we need to use the exception's additional information to
        // find out which controller actually detected the false positive.
        if (isNotArchive.getController() == srcController)
          throw isNotArchive; // not my job - pass on!
      }

      final InputStream in;
      final long time;
      srcController.readLock().lock();
      try {
        in = srcController.createInputStream0(srcEntryName); // detects false positives!
        time = srcController.lastModified(srcEntryName);
      } finally {
        srcController.readLock().unlock();
      }

      // Treat the destination like a regular file.
      final OutputStream out;
      try {
        out = new java.io.FileOutputStream(dst);
      } catch (IOException ex) {
        try {
          in.close();
        } catch (IOException inFailure) {
          throw new InputIOException(inFailure);
        }
        throw ex;
      }

      cp(in, out);
      if (preserve && !dst.setLastModified(time))
        throw new IOException(dst.getPath() + " (cannot preserve last modification time)");
    } catch (ArchiveEntryFalsePositiveException ex) {
      assert srcController == ex.getController();
      // Reroute call to the source's enclosing archive controller.
      cp0(
          preserve,
          srcController.getEnclController(),
          srcController.enclEntryName(srcEntryName),
          dst);
    }
  }