tikhomirov@617: /* tikhomirov@617: * Copyright (c) 2013 TMate Software Ltd tikhomirov@617: * tikhomirov@617: * This program is free software; you can redistribute it and/or modify tikhomirov@617: * it under the terms of the GNU General Public License as published by tikhomirov@617: * the Free Software Foundation; version 2 of the License. tikhomirov@617: * tikhomirov@617: * This program is distributed in the hope that it will be useful, tikhomirov@617: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@617: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@617: * GNU General Public License for more details. tikhomirov@617: * tikhomirov@617: * For information on how to redistribute this software under tikhomirov@617: * the terms of a license other than GNU General Public License tikhomirov@617: * contact TMate Software at support@hg4j.com tikhomirov@617: */ tikhomirov@617: package org.tmatesoft.hg.internal; tikhomirov@617: tikhomirov@617: import static org.tmatesoft.hg.util.LogFacility.Severity.Debug; tikhomirov@617: tikhomirov@617: import java.io.Closeable; tikhomirov@617: import java.io.File; tikhomirov@617: import java.io.FileInputStream; tikhomirov@617: import java.io.FileOutputStream; tikhomirov@617: import java.io.IOException; tikhomirov@617: import java.nio.channels.FileChannel; tikhomirov@617: tikhomirov@617: import org.tmatesoft.hg.core.HgIOException; tikhomirov@617: import org.tmatesoft.hg.util.LogFacility; tikhomirov@617: import org.tmatesoft.hg.util.LogFacility.Severity; tikhomirov@617: tikhomirov@617: /** tikhomirov@617: * tikhomirov@617: * @author Artem Tikhomirov tikhomirov@617: * @author TMate Software Ltd. tikhomirov@617: */ tikhomirov@617: final class FileUtils { tikhomirov@617: tikhomirov@617: private final LogFacility log; tikhomirov@617: tikhomirov@617: public static void copyFile(File from, File to) throws HgIOException { tikhomirov@617: new FileUtils(new StreamLogFacility(Debug, true, System.err)).copy(from, to); tikhomirov@617: } tikhomirov@617: tikhomirov@617: public FileUtils(LogFacility logFacility) { tikhomirov@617: log = logFacility; tikhomirov@617: } tikhomirov@617: tikhomirov@617: public void copy(File from, File to) throws HgIOException { tikhomirov@617: FileInputStream fis = null; tikhomirov@617: FileOutputStream fos = null; tikhomirov@617: try { tikhomirov@617: fis = new FileInputStream(from); tikhomirov@617: fos = new FileOutputStream(to); tikhomirov@617: FileChannel input = fis.getChannel(); tikhomirov@617: FileChannel output = fos.getChannel(); tikhomirov@617: long count = input.size(); tikhomirov@617: long pos = 0; tikhomirov@617: int zeroCopied = 0; // flag to prevent hang-up tikhomirov@617: do { tikhomirov@617: long c = input.transferTo(pos, count, output); tikhomirov@617: pos += c; tikhomirov@617: count -= c; tikhomirov@617: if (c == 0) { tikhomirov@617: if (++zeroCopied == 3) { tikhomirov@617: String m = String.format("Can't copy %s to %s, transferTo copies 0 bytes. Position: %d, bytes left:%d", from.getName(), to.getName(), pos, count); tikhomirov@617: throw new IOException(m); tikhomirov@617: } tikhomirov@617: } else { tikhomirov@617: // reset tikhomirov@617: zeroCopied = 0; tikhomirov@617: } tikhomirov@617: } while (count > 0); tikhomirov@617: fos.close(); tikhomirov@617: fos = null; tikhomirov@617: fis.close(); tikhomirov@617: fis = null; tikhomirov@617: } catch (IOException ex) { tikhomirov@617: // not in finally because I don't want to loose exception from fos.close() tikhomirov@617: closeQuietly(fis); tikhomirov@617: closeQuietly(fos); tikhomirov@617: String m = String.format("Failed to copy %s to %s", from.getName(), to.getName()); tikhomirov@617: throw new HgIOException(m, ex, from); tikhomirov@617: } tikhomirov@617: } tikhomirov@617: tikhomirov@617: public void closeQuietly(Closeable stream) { tikhomirov@617: if (stream != null) { tikhomirov@617: try { tikhomirov@617: stream.close(); tikhomirov@617: } catch (IOException ex) { tikhomirov@617: // ignore tikhomirov@617: log.dump(getClass(), Severity.Warn, ex, "Exception while closing stream quietly"); tikhomirov@617: } tikhomirov@617: } tikhomirov@617: } tikhomirov@617: tikhomirov@617: }