Package slash.navigation.download

Source Code of slash.navigation.download.DownloadExecutor$ModelUpdater

/*
    This file is part of RouteConverter.

    RouteConverter is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    RouteConverter is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with RouteConverter; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    Copyright (C) 2007 Christian Pesch. All Rights Reserved.
*/

package slash.navigation.download;

import slash.navigation.download.actions.Copier;
import slash.navigation.download.actions.CopierListener;
import slash.navigation.download.actions.Extractor;
import slash.navigation.download.actions.Validator;
import slash.navigation.rest.Get;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

import static java.lang.String.format;
import static java.util.logging.Logger.getLogger;
import static slash.common.io.Directories.ensureDirectory;
import static slash.common.io.Files.setLastModified;
import static slash.common.type.CompactCalendar.fromMillis;
import static slash.navigation.download.State.*;

/**
* Performs the {@link Download} of an URL to local file.
*
* @author Christian Pesch
*/

public class DownloadExecutor implements Runnable {
    private static final Logger log = getLogger(DownloadExecutor.class.getName());

    private final Download download;
    private final DownloadManager downloadManager;

    private Get get;

    public DownloadExecutor(Download download, DownloadManager downloadManager) {
        this.download = download;
        this.downloadManager = downloadManager;
        download.setState(Queued);
    }

    public Download getDownload() {
        return download;
    }

    public void run() {
        updateState(download, Running);

        try {
            boolean success = false;
            if (canResume())
                success = resume();
            if (!success)
                success = download();

            if (success) {
                if (postProcess())
                    succeeded(get.isNotModified());
                else
                    downloadManager.fireDownloadFailed(download);

            } else if (get.isNotModified()) {
                updateState(download, NotModified);

            } else
                failed();
        } catch (Exception e) {
            e.printStackTrace();
            log.severe(format("Could not download content from %s: %s", download.getUrl(), e));
            failed();
        }
    }

    private boolean canResume() {
        Checksum checksum = download.getFile().getExpectedChecksum();
        return download.getTempFile().exists() && download.getTempFile().length() > 0 &&
                checksum != null && checksum.getContentLength() != null &&
                checksum.getContentLength() > download.getTempFile().length();
    }

    private void updateState(Download download, State state) {
        download.setState(state);
        downloadManager.getModel().updateDownload(download);
        log.fine(format("State for download from %s changed to %s", download.getUrl(), state));
    }

    private void failed() {
        updateState(download, Failed);
        downloadManager.fireDownloadFailed(download);
    }

    private void succeeded(boolean notModified) {
        updateState(download, Succeeded);
        if (!notModified)
            downloadManager.fireDownloadSucceeded(download);
    }

    private class ModelUpdater implements CopierListener {
        public void expectingBytes(long byteCount) {
            download.setExpectedBytes(byteCount);
        }

        public void processedBytes(long byteCount) {
            download.setProcessedBytes(byteCount);
            downloadManager.getModel().updateDownload(download);
            if (download.getState().equals(Downloading))
                downloadManager.fireDownloadProgressed(download);
        }
    }

    private ModelUpdater modelUpdater = new ModelUpdater();

    private boolean resume() throws IOException {
        updateState(download, Resuming);
        long fileSize = download.getTempFile().length();
        Long contentLength = download.getFile().getExpectedChecksum() != null ? download.getFile().getExpectedChecksum().getContentLength() : null;
        log.info(format("Resuming bytes %d-%d from %s", fileSize, contentLength, download.getUrl()));

        get = new Get(download.getUrl());
        get.setRange(fileSize, contentLength);

        InputStream inputStream = get.executeAsStream();
        log.info(format("Resume from %s returned with status code %s", download.getUrl(), get.getStatusCode()));
        if (get.isPartialContent()) {
            modelUpdater.expectingBytes(contentLength != null ? contentLength : get.getContentLength() != null ? get.getContentLength() : 0);
            new Copier(modelUpdater).copyAndClose(inputStream, new FileOutputStream(download.getTempFile(), true), fileSize, contentLength);
            return true;
        }
        return false;
    }

    private boolean download() throws IOException {
        updateState(download, Downloading);
        Long contentLength = download.getFile().getExpectedChecksum() != null ? download.getFile().getExpectedChecksum().getContentLength() : null;
        log.info(format("Downloading %d bytes from %s with ETag %s", contentLength, download.getUrl(), download.getETag()));

        get = new Get(download.getUrl());
        if (new Validator(download).existTargets() && download.getETag() != null)
            get.setIfNoneMatch(download.getETag());

        InputStream inputStream = get.executeAsStream();
        log.info(format("Download from %s returned with status code %s", download.getUrl(), get.getStatusCode()));
        if (get.isSuccessful() && inputStream != null) {
            if(contentLength == null)
                contentLength = get.getContentLength();
            modelUpdater.expectingBytes(contentLength != null ? contentLength : 0);
            new Copier(modelUpdater).copyAndClose(inputStream, new FileOutputStream(download.getTempFile()), 0, contentLength);
            download.setETag(get.getETag());
            return true;
        }
        return false;
    }

    private boolean postProcess() throws IOException {
        updateState(download, Processing);

        bringToTarget();

        if (!validate())
            return false;

        if (download.getTempFile().exists())
            if (!download.getTempFile().delete())
                throw new IOException(format("Cannot delete temp file %s", download.getTempFile()));

        log.fine(format("Postprocess from %s successful: %s", download.getUrl(), get.isSuccessful()));
        return true;
    }

    private void bringToTarget() throws IOException {
        Action action = download.getAction();
        switch (action) {
            case Copy:
                copy();
                break;
            case Flatten:
                flatten();
                break;
            case Extract:
                extract();
                break;
            default:
                throw new IllegalArgumentException("Unknown Action " + action);
        }
    }

    private void copy() throws IOException {
        File target = download.getFile().getFile();
        ensureDirectory(target.getParent());
        new Copier(modelUpdater).copyAndClose(download.getTempFile(), target);
        setLastModified(target, fromMillis(get.getLastModified()));
    }

    private void flatten() throws IOException {
        File target = download.getFile().getFile();
        new Extractor(modelUpdater).flatten(download.getTempFile(), target);
        setLastModified(download.getTempFile(), fromMillis(get.getLastModified()));
    }

    private void extract() throws IOException {
        File target = download.getFile().getFile();
        new Extractor(modelUpdater).extract(download.getTempFile(), target);
        setLastModified(download.getTempFile(), fromMillis(get.getLastModified()));
    }

    private boolean validate() throws IOException {
        updateState(download, Validating);

        Validator validator = new Validator(download);
        validator.validate();

        if (!validator.existTargets()) {
            updateState(download, NoFileError);
            return false;
        } else if (!validator.isChecksumValid()) {
            updateState(download, ChecksumError);
            return false;
        }
        return true;
    }
}
TOP

Related Classes of slash.navigation.download.DownloadExecutor$ModelUpdater

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.