mirror of https://github.com/noisymime/Arduino.git
Added FileDownloader
This commit is contained in:
parent
915c9d6f8f
commit
b249be46c7
Binary file not shown.
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
package cc.arduino.packages.contributions;
|
||||||
|
|
||||||
|
import static processing.app.I18n._;
|
||||||
|
import static processing.app.I18n.format;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Observable;
|
||||||
|
import java.util.Observer;
|
||||||
|
|
||||||
|
import cc.arduino.utils.FileHash;
|
||||||
|
import cc.arduino.utils.Progress;
|
||||||
|
import cc.arduino.utils.network.FileDownloader;
|
||||||
|
|
||||||
|
public class DownloadableContributionsDownloader {
|
||||||
|
|
||||||
|
private File stagingFolder;
|
||||||
|
|
||||||
|
public DownloadableContributionsDownloader(File _stagingFolder) {
|
||||||
|
stagingFolder = _stagingFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File download(DownloadableContribution contribution,
|
||||||
|
final Progress progress, final String statusText)
|
||||||
|
throws Exception {
|
||||||
|
URL url = new URL(contribution.getUrl());
|
||||||
|
final File outputFile = new File(stagingFolder, contribution.getArchiveFileName());
|
||||||
|
|
||||||
|
// Ensure the existence of staging folder
|
||||||
|
stagingFolder.mkdirs();
|
||||||
|
|
||||||
|
// Need to download or resume downloading?
|
||||||
|
if (!outputFile.isFile() || (outputFile.length() < contribution.getSize())) {
|
||||||
|
download(url, outputFile, progress, statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test checksum
|
||||||
|
progress.setStatus(_("Verifying archive integrity..."));
|
||||||
|
onProgress(progress);
|
||||||
|
String checksum = contribution.getChecksum();
|
||||||
|
String algo = checksum.split(":")[0];
|
||||||
|
if (!FileHash.hash(outputFile, algo).equals(checksum))
|
||||||
|
throw new Exception(_("CRC doesn't match. File is corrupted."));
|
||||||
|
|
||||||
|
contribution.setDownloaded(true);
|
||||||
|
contribution.setDownloadedFile(outputFile);
|
||||||
|
return outputFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void download(URL url, File tmpFile, final Progress progress,
|
||||||
|
final String statusText) throws Exception {
|
||||||
|
FileDownloader downloader = new FileDownloader(url, tmpFile);
|
||||||
|
downloader.addObserver(new Observer() {
|
||||||
|
@Override
|
||||||
|
public void update(Observable o, Object arg) {
|
||||||
|
FileDownloader me = (FileDownloader) o;
|
||||||
|
String msg = "";
|
||||||
|
if (me.getDownloadSize() != null) {
|
||||||
|
long downloaded = me.getInitialSize() + me.getDownloaded() / 1000;
|
||||||
|
long total = me.getInitialSize() + me.getDownloadSize() / 1000;
|
||||||
|
msg = format(_("Downloaded {0}kb of {1}kb."), downloaded, total);
|
||||||
|
}
|
||||||
|
progress.setStatus(statusText + " " + msg);
|
||||||
|
progress.setProgress(me.getProgress());
|
||||||
|
onProgress(progress);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
downloader.download();
|
||||||
|
if (!downloader.isCompleted())
|
||||||
|
throw new Exception(format(_("Error dowloading {0}"), url),
|
||||||
|
downloader.getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onProgress(Progress progress) {
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* This file is part of Arduino.
|
||||||
|
*
|
||||||
|
* Copyright 2014 Arduino LLC (http://www.arduino.cc/)
|
||||||
|
*
|
||||||
|
* Arduino 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* As a special exception, you may use this file as part of a free software
|
||||||
|
* library without restriction. Specifically, if other files instantiate
|
||||||
|
* templates or use macros or inline functions from this file, or you compile
|
||||||
|
* this file and link it with other files to produce an executable, this
|
||||||
|
* file does not by itself cause the resulting executable to be covered by
|
||||||
|
* the GNU General Public License. This exception does not however
|
||||||
|
* invalidate any other reasons why the executable file might be covered by
|
||||||
|
* the GNU General Public License.
|
||||||
|
*/
|
||||||
|
package cc.arduino.utils.network;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.SocketTimeoutException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Observable;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
public class FileDownloader extends Observable {
|
||||||
|
|
||||||
|
public enum Status {
|
||||||
|
CONNECTING, //
|
||||||
|
CONNECTION_TIMEOUT_ERROR, //
|
||||||
|
DOWNLOADING, //
|
||||||
|
COMPLETE, //
|
||||||
|
CANCELLED, //
|
||||||
|
ERROR, //
|
||||||
|
};
|
||||||
|
|
||||||
|
private Status status;
|
||||||
|
private long initialSize;
|
||||||
|
private Long downloadSize = null;
|
||||||
|
private long downloaded;
|
||||||
|
private URL downloadUrl;
|
||||||
|
|
||||||
|
private File outputFile;
|
||||||
|
private InputStream stream = null;
|
||||||
|
private Exception error;
|
||||||
|
|
||||||
|
public FileDownloader(URL url, File file) {
|
||||||
|
downloadUrl = url;
|
||||||
|
outputFile = file;
|
||||||
|
downloaded = 0;
|
||||||
|
initialSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInitialSize() {
|
||||||
|
return initialSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDownloadSize() {
|
||||||
|
return downloadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDownloadSize(Long downloadSize) {
|
||||||
|
this.downloadSize = downloadSize;
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getDownloaded() {
|
||||||
|
return downloaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDownloaded(long downloaded) {
|
||||||
|
this.downloaded = downloaded;
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getProgress() {
|
||||||
|
if (downloadSize == null)
|
||||||
|
return 0;
|
||||||
|
if (downloadSize == 0)
|
||||||
|
return 100;
|
||||||
|
return ((float) downloaded / downloadSize) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
setChanged();
|
||||||
|
notifyObservers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void download() throws InterruptedException {
|
||||||
|
RandomAccessFile file = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Open file and seek to the end of it
|
||||||
|
file = new RandomAccessFile(outputFile, "rw");
|
||||||
|
initialSize = file.length();
|
||||||
|
file.seek(initialSize);
|
||||||
|
|
||||||
|
setStatus(Status.CONNECTING);
|
||||||
|
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) downloadUrl
|
||||||
|
.openConnection();
|
||||||
|
|
||||||
|
if (downloadUrl.getUserInfo() != null) {
|
||||||
|
String auth = "Basic "
|
||||||
|
+ new String(new Base64().encode(downloadUrl
|
||||||
|
.getUserInfo().getBytes()));
|
||||||
|
connection.setRequestProperty("Authorization", auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.setRequestProperty("Range", "bytes=" + initialSize + "-");
|
||||||
|
connection.setConnectTimeout(5000);
|
||||||
|
setDownloaded(0);
|
||||||
|
|
||||||
|
// Connect
|
||||||
|
connection.connect();
|
||||||
|
int resp = connection.getResponseCode();
|
||||||
|
if (resp < 200 || resp >= 300)
|
||||||
|
throw new IOException(
|
||||||
|
"Recevied invalid http status code from server: " + resp);
|
||||||
|
|
||||||
|
// Check for valid content length.
|
||||||
|
long len = connection.getContentLength();
|
||||||
|
if (len >= 0)
|
||||||
|
setDownloadSize(len);
|
||||||
|
setStatus(Status.DOWNLOADING);
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
stream = connection.getInputStream();
|
||||||
|
}
|
||||||
|
byte buffer[] = new byte[10240];
|
||||||
|
while (status == Status.DOWNLOADING) {
|
||||||
|
int read = stream.read(buffer);
|
||||||
|
if (read == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
file.write(buffer, 0, read);
|
||||||
|
setDownloaded(getDownloaded() + read);
|
||||||
|
|
||||||
|
if (Thread.interrupted())
|
||||||
|
throw new InterruptedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getDownloadSize() != null) {
|
||||||
|
if (getDownloaded() < getDownloadSize())
|
||||||
|
throw new Exception("Incomplete download");
|
||||||
|
}
|
||||||
|
setStatus(Status.COMPLETE);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
setStatus(Status.CANCELLED);
|
||||||
|
// lets InterruptedException go up to the caller
|
||||||
|
throw e;
|
||||||
|
|
||||||
|
} catch (SocketTimeoutException e) {
|
||||||
|
setStatus(Status.CONNECTION_TIMEOUT_ERROR);
|
||||||
|
setError(e);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
setStatus(Status.ERROR);
|
||||||
|
setError(e);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
if (file != null) {
|
||||||
|
try {
|
||||||
|
file.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setError(Exception e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Exception getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompleted() {
|
||||||
|
return status == Status.COMPLETE;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue