package com.wouterbreukink.onedrive.tasks; import com.google.api.client.util.Preconditions; import com.wouterbreukink.onedrive.client.OneDriveItem; import com.wouterbreukink.onedrive.client.downloader.ResumableDownloader; import com.wouterbreukink.onedrive.client.downloader.ResumableDownloaderProgressListener; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import static com.wouterbreukink.onedrive.LogUtils.readableFileSize; import static com.wouterbreukink.onedrive.LogUtils.readableTime; public class DownloadTask extends Task { private static final Logger log = LogManager.getLogger(UploadTask.class.getName()); private final File parent; private final OneDriveItem remoteFile; private final boolean replace; public DownloadTask(TaskOptions options, File parent, OneDriveItem remoteFile, boolean replace) { super(options); this.parent = Preconditions.checkNotNull(parent); this.remoteFile = Preconditions.checkNotNull(remoteFile); this.replace = Preconditions.checkNotNull(replace); if (!parent.isDirectory()) { throw new IllegalArgumentException("Specified parent is not a folder"); } } public int priority() { return 50; } @Override public String toString() { return "Download " + remoteFile.getFullName(); } @Override protected void taskBody() throws IOException { if (isIgnored(remoteFile)) { reporter.skipped(); return; } if (remoteFile.isDirectory()) { File newParent = fileSystem.createFolder(parent, remoteFile.getName()); queue.add(new UpdatePropertiesTask(getTaskOptions(), remoteFile, newParent)); for (OneDriveItem item : api.getChildren(remoteFile)) { queue.add(new DownloadTask(getTaskOptions(), newParent, item, false)); } } else { if (isSizeInvalid(remoteFile)) { reporter.skipped(); return; } final long startTime = System.currentTimeMillis(); File downloadFile = null; try { downloadFile = fileSystem.createFile(parent, remoteFile.getName() + ".tmp"); // The progress reporter ResumableDownloaderProgressListener progressListener = new ResumableDownloaderProgressListener() { private long startTimeInner = System.currentTimeMillis(); @Override public void progressChanged(ResumableDownloader downloader) throws IOException { switch (downloader.getDownloadState()) { case MEDIA_IN_PROGRESS: long elapsedTimeInner = System.currentTimeMillis() - startTimeInner; log.info(String.format("Downloaded chunk (progress %.1f%%) of %s (%s/s) for file %s", downloader.getProgress() * 100, readableFileSize(downloader.getChunkSize()), elapsedTimeInner > 0 ? readableFileSize(downloader.getChunkSize() / (elapsedTimeInner / 1000d)) : 0, remoteFile.getFullName())); startTimeInner = System.currentTimeMillis(); break; case MEDIA_COMPLETE: long elapsedTime = System.currentTimeMillis() - startTime; log.info(String.format("Downloaded %s in %s (%s/s) of %s file %s", readableFileSize(remoteFile.getSize()), readableTime(elapsedTime), elapsedTime > 0 ? readableFileSize(remoteFile.getSize() / (elapsedTime / 1000d)) : 0, replace ? "replaced" : "new", remoteFile.getFullName())); } } }; api.download(remoteFile, downloadFile, progressListener); // Do a CRC check on the downloaded file if (!fileSystem.verifyCrc(downloadFile, remoteFile.getCrc32())) { throw new IOException(String.format("Download of file '%s' failed", remoteFile.getFullName())); } fileSystem.setAttributes( downloadFile, remoteFile.getCreatedDateTime(), remoteFile.getLastModifiedDateTime()); fileSystem.replaceFile(new File(parent, remoteFile.getName()), downloadFile); reporter.fileDownloaded(replace, remoteFile.getSize()); } catch (Throwable e) { if (downloadFile != null) { if (!downloadFile.delete()) { log.warn("Unable to remove temporary file " + downloadFile.getPath()); } } throw e; } } } }