/** * 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)"); }
/** 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; } }
/** * 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); } }