summaryrefslogtreecommitdiffstats
path: root/dozentenmodul/src/main/java/ftp/DownloadTask.java
diff options
context:
space:
mode:
Diffstat (limited to 'dozentenmodul/src/main/java/ftp/DownloadTask.java')
-rw-r--r--dozentenmodul/src/main/java/ftp/DownloadTask.java246
1 files changed, 138 insertions, 108 deletions
diff --git a/dozentenmodul/src/main/java/ftp/DownloadTask.java b/dozentenmodul/src/main/java/ftp/DownloadTask.java
index ef95b8da..95e74169 100644
--- a/dozentenmodul/src/main/java/ftp/DownloadTask.java
+++ b/dozentenmodul/src/main/java/ftp/DownloadTask.java
@@ -4,10 +4,9 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@@ -20,6 +19,10 @@ import models.SessionData;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
+import org.openslx.filetransfer.DataReceivedCallback;
+import org.openslx.filetransfer.Downloader;
+import org.openslx.filetransfer.FileRange;
+import org.openslx.filetransfer.WantRangeCallback;
import org.openslx.thrifthelper.ThriftManager;
import util.ResourceLoader;
@@ -37,27 +40,78 @@ public class DownloadTask extends SwingWorker<Void, Void> {
*/
private final static Logger LOGGER = Logger.getLogger(DownloadTask.class);
- private static final int BUFFER_SIZE = 8 * 1024 * 1024;
private static final double UPDATE_INTERVAL_SECONDS = 0.6;
private static final double UPDATE_INTERVAL_MS = UPDATE_INTERVAL_SECONDS * 1000;
private static final double BYTES_PER_MIB = 1024 * 1024;
+ private static final long CHUNK_SIZE = 16 * 1024 * 1024;
- private String host;
- private int port;
- private String username;
- private String password;
- private String downloadPath;
- private String saveDir;
- private int percentCompleted;
+ private final String host;
+ private final int port;
+ private final String downloadToken;
+ private final String saveDir;
+ private final long fileSize;
+ private boolean success = false;
- public DownloadTask(String host, int port, String username, String password,
- String downloadPath, String saveDir) {
+ public DownloadTask(String host, int port, String downloadToken, String saveDir, long fileSize) {
this.host = host;
this.port = port;
- this.username = username;
- this.password = password;
- this.downloadPath = downloadPath;
+ this.downloadToken = downloadToken;
this.saveDir = saveDir;
+ this.fileSize = fileSize;
+ }
+
+ class Callbacks implements WantRangeCallback, DataReceivedCallback {
+ // initialize the counters needed for speed calculations
+ private long currentRequestedOffset = -1;
+ private long totalBytesRead = 0;
+ private long lastUpdate = 0;
+ private long lastBytes = 0;
+ private long currentBytes = 0;
+ private final RandomAccessFile file;
+
+ public Callbacks(RandomAccessFile file) {
+ this.file = file;
+ }
+
+ @Override
+ public FileRange get() {
+ if (currentRequestedOffset == -1)
+ currentRequestedOffset = 0;
+ else
+ currentRequestedOffset += CHUNK_SIZE;
+ if (currentRequestedOffset >= fileSize)
+ return null;
+ long end = currentRequestedOffset + CHUNK_SIZE;
+ if (end > fileSize)
+ end = fileSize;
+ return new FileRange(currentRequestedOffset, end);
+ }
+
+ @Override
+ public boolean dataReceived(final long fileOffset, final int dataLength, final byte[] data) {
+ try {
+ file.seek(fileOffset);
+ file.write(data, 0, dataLength);
+ } catch (Exception e) {
+ LOGGER.error("Could not write to file at offset " + fileOffset, e);
+ return false;
+ }
+ currentBytes += dataLength;
+ totalBytesRead += dataLength;
+ final long now = System.currentTimeMillis();
+ if (lastUpdate + UPDATE_INTERVAL_MS < now) {
+ final int percentCompleted = (int) ((totalBytesRead * 100) / fileSize);
+ setProgress(percentCompleted);
+ lastBytes = (lastBytes * 2 + currentBytes) / 3;
+ final double speed = lastBytes / UPDATE_INTERVAL_SECONDS;
+ firePropertyChange("speed", 0, speed / BYTES_PER_MIB);
+ firePropertyChange("bytesread", 0, totalBytesRead);
+ lastUpdate = now;
+ currentBytes = 0;
+ }
+ return true;
+ }
+
}
/**
@@ -65,61 +119,45 @@ public class DownloadTask extends SwingWorker<Void, Void> {
*/
@Override
protected Void doInBackground() throws Exception {
- FTPUtility util = new FTPUtility(host, port, username, password);
- try {
- util.connect();
+ boolean ret = false;
+ // show filesize in the GUI
+ firePropertyChange("filesize", 0, fileSize);
- // show filesize in the GUI
- long fileSize = util.getFileSize(downloadPath);
- firePropertyChange("filesize", 0, fileSize);
- util.downloadFile(downloadPath);
+ Downloader download = null;
+ RandomAccessFile file = null;
+ try {
+ download = new Downloader(host, port, null, downloadToken); // TODO: SSL
+ try {
+ file = new RandomAccessFile(new File(saveDir), "rw");
+ } catch (Exception e2) {
+ JOptionPane.showMessageDialog(null, "Could not open destination file:\n" + saveDir + "\n"
+ + e2.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+ e2.printStackTrace();
+ setProgress(0);
+ return null;
+ }
- // prepare the input/output streams
- String fileName = new File(downloadPath).getName();
- File downloadFile = new File(saveDir + File.separator + fileName);
- FileOutputStream outputStream = new FileOutputStream(downloadFile);
- InputStream inputStream = util.getInputStream();
+ Callbacks cb = new Callbacks(file);
- // initialize the counters needed for speed calculations
- percentCompleted = 0;
- byte[] buffer = new byte[BUFFER_SIZE];
- int bytesRead = -1;
- long totalBytesRead = 0;
- long lastUpdate = 0;
- long lastBytes = 0;
- long currentBytes = 0;
- while ((bytesRead = inputStream.read(buffer)) != -1 && !isCancelled()) {
- outputStream.write(buffer, 0, bytesRead);
- currentBytes += bytesRead;
- totalBytesRead += bytesRead;
- long now = System.currentTimeMillis();
- if (lastUpdate + UPDATE_INTERVAL_MS < now) {
- percentCompleted = (int) ((totalBytesRead * 100) / fileSize);
- setProgress(percentCompleted);
- lastBytes = (lastBytes * 2 + currentBytes) / 3;
- final double speed = lastBytes / UPDATE_INTERVAL_SECONDS;
- firePropertyChange("speed", 0, speed / BYTES_PER_MIB);
- firePropertyChange("bytesread", 0, totalBytesRead);
- lastUpdate = now;
- currentBytes = 0;
+ ret = download.download(cb, cb);
+ } finally {
+ if (file != null) {
+ try {
+ file.close();
+ } catch (Exception e) {
}
}
- // finalize the download by updating the progress bar one last time
- // (in case we didn't get to do it because of the time interval)
- percentCompleted = (int) ((totalBytesRead * 100) / fileSize);
- setProgress(percentCompleted);
- firePropertyChange("bytesread", 0, totalBytesRead);
- outputStream.close();
- util.finish();
- } catch (FTPException ex) {
- JOptionPane.showMessageDialog(null,
- "Error downloading file: " + ex.getMessage(), "Error",
- JOptionPane.ERROR_MESSAGE);
- ex.printStackTrace();
- setProgress(0);
- cancel(true);
- } finally {
- util.disconnect();
+ if (download != null)
+ download.close(null);
+ }
+
+ // if the download succeeded, set the progress to 100% manually again here to make
+ // sure the GUI knows about it.
+ if (ret) {
+ setProgress(100);
+ firePropertyChange("bytesread", 0, fileSize);
+ firePropertyChange("success", false, true);
+ success = true;
}
return null;
@@ -130,24 +168,26 @@ public class DownloadTask extends SwingWorker<Void, Void> {
*/
@Override
protected void done() {
- if (!isCancelled() && percentCompleted == 100) {
+ if (isCancelled())
+ return;
+ if (success) {
LOGGER.info("Datei erfolgreich heruntergeladen.");
String vmxResult = "";
- vmxResult = generateVmx() ? "Passende VMX generiert."
- : "Keine passende VMX generiert!";
- JOptionPane.showMessageDialog(null, "Datei erfolgreich heruntergeladen. "
- + vmxResult, "Message", JOptionPane.INFORMATION_MESSAGE);
- } else if (!isCancelled() && percentCompleted != 100) {
+ vmxResult = generateVmx() ? "Passende VMX generiert." : "Keine passende VMX generiert!";
+ JOptionPane.showMessageDialog(null, "Datei erfolgreich heruntergeladen. " + vmxResult, "Message",
+ JOptionPane.INFORMATION_MESSAGE);
+ } else {
LOGGER.error("Datei wurde unvollständig heruntergeladen.");
JOptionPane.showMessageDialog(null,
- "Datei wurde unvollständig heruntergeladen. Bitte wiederholen.",
- "Message", JOptionPane.INFORMATION_MESSAGE);
+ "Datei wurde unvollständig heruntergeladen. Bitte wiederholen.", "Message",
+ JOptionPane.INFORMATION_MESSAGE);
}
}
/**
* Helper to generate the vmx for the downloaded image
- *
+ * TODO: Not really related to DownloadTask...
+ *
* @return true|false indicating the success of the file creation
*/
private boolean generateVmx() {
@@ -159,8 +199,7 @@ public class DownloadTask extends SwingWorker<Void, Void> {
LOGGER.debug("Image's ID: " + Image.ImageId);
Map<String, String> imageData = null;
try {
- imageData = ThriftManager.getSatClient().getImageData(
- Image.ImageId, Image.Version,
+ imageData = ThriftManager.getSatClient().getImageData(Image.ImageId, Image.Version,
SessionData.authToken);
} catch (TException e) {
LOGGER.error("Thrift exception during transfer, see trace: ", e);
@@ -177,37 +216,29 @@ public class DownloadTask extends SwingWorker<Void, Void> {
int hardwareVersion = extractHardwareVersion(saveDir + File.separator
+ imageData.get("path").replaceFirst("^prod/", ""));
if (hardwareVersion == 0) {
- LOGGER
- .error("'extractHardwareVersion' returned 0 indicating some problem. See logs.");
+ LOGGER.error("'extractHardwareVersion' returned 0 indicating some problem. See logs.");
LOGGER.error("Falling back to default hardware version of '10'.");
hardwareVersion = 10;
}
// TODO: sanity checks on the content of imageData would be good here...
// use the information we received about the image
- vmxTemplate = vmxTemplate.replace("%VM_DISPLAY_NAME%",
- imageData.get("name"));
+ vmxTemplate = vmxTemplate.replace("%VM_DISPLAY_NAME%", imageData.get("name"));
vmxTemplate = vmxTemplate.replace("%VM_GUEST_OS%", imageData.get("os"));
vmxTemplate = vmxTemplate.replace("%VM_CPU_COUNT%", imageData.get("cpu"));
vmxTemplate = vmxTemplate.replace("%VM_RAM_SIZE%",
String.valueOf(Integer.valueOf(imageData.get("ram")) * 1024));
- vmxTemplate = vmxTemplate.replace("%VM_DISK_PATH%", imageData.get("path")
- .replaceFirst("^prod/", ""));
- vmxTemplate = vmxTemplate.replace("%VM_HW_VERSION%",
- String.valueOf(hardwareVersion));
+ vmxTemplate = vmxTemplate.replace("%VM_DISK_PATH%", imageData.get("path").replaceFirst("^prod/", ""));
+ vmxTemplate = vmxTemplate.replace("%VM_HW_VERSION%", String.valueOf(hardwareVersion));
// build filename for the vmx, basicly the same as the path of the vmdk
// just without the leading "prod/" and "vmx" instead of "vmdk" at the end.
- String targetFilename = saveDir
- + File.separator
- + imageData.get("path").replaceFirst("^prod/", "")
- .replaceFirst("\\.vmdk$", "") + ".vmx";
+ String targetFilename = saveDir + File.separator
+ + imageData.get("path").replaceFirst("^prod/", "").replaceFirst("\\.vmdk$", "") + ".vmx";
try {
// try to write it to file
- FileUtils.writeStringToFile(new File(targetFilename), vmxTemplate,
- StandardCharsets.UTF_8);
+ FileUtils.writeStringToFile(new File(targetFilename), vmxTemplate, StandardCharsets.UTF_8);
} catch (IOException e) {
- LOGGER.error("Could not write vmx-template to '" + targetFilename
- + "'. See trace: ", e);
+ LOGGER.error("Could not write vmx-template to '" + targetFilename + "'. See trace: ", e);
return false;
}
return true;
@@ -216,44 +247,41 @@ public class DownloadTask extends SwingWorker<Void, Void> {
/**
* Helper to extract the hardware version of the VMDK file by inspecting its
* content.
- *
- * @return value of hardware version as integer. A return value of 0 indicates
+ *
+ * @return value of hardware version as integer. A return value of 0
+ * indicates
* an error.
*/
private int extractHardwareVersion(String path) {
BufferedReader br = null;
try {
try {
- br = new BufferedReader(
- new InputStreamReader(new FileInputStream(path)));
+ br = new BufferedReader(new InputStreamReader(new FileInputStream(path)));
String line;
// first 4 characters of a VMDK file start with 'KDMV'
// first lets check if this is the case
line = br.readLine();
if (!line.subSequence(0, 4).equals("KDMV")) {
- LOGGER
- .error("Did not see 'KDMV' as first chars of the VMDK! Returning 0.");
+ LOGGER.error("Did not see 'KDMV' as first chars of the VMDK! Returning 0.");
LOGGER.debug("First line was: " + line);
LOGGER.debug("First 4 characters of it: " + line.subSequence(0, 4));
return 0;
}
- // only read a maximum of 20 lines, just in case...
+ // only read a maximum of 25 lines, just in case...
int round = 0;
- while ((line = br.readLine()) != null && round < 20) {
- if (line.matches("^ddb\\.virtualHWVersion.*")) {
+ while ((line = br.readLine()) != null && round < 25) {
+ if (line.startsWith("ddb.virtualHWVersion")) {
String[] tmp = line.split("=");
// we should get 2 strings only after the split, lets be sure
if (tmp.length != 2) {
- LOGGER
- .debug("Splitting returned more than 2 parts, this should not happen!");
+ LOGGER.debug("Splitting returned more than 2 parts, this should not happen!");
return 0;
}
int candidate = Integer.parseInt(tmp[1].trim().replace("\"", ""));
LOGGER.debug("Considering hardware version: " + candidate);
if (candidate > 0) {
- LOGGER
- .debug("Valid value of the candidate. Using hardware version of: "
- + candidate);
+ LOGGER.debug("Valid value of the candidate. Using hardware version of: "
+ + candidate);
return candidate;
} else {
LOGGER.error("Candidate is not > 0! Returning 0.");
@@ -262,8 +290,10 @@ public class DownloadTask extends SwingWorker<Void, Void> {
}
round++;
}
- LOGGER.error("Failed to find hardware version. Tried " + round
- + " rounds.");
+ LOGGER.error("Failed to find hardware version. Tried " + round + " rounds.");
+ } catch (NumberFormatException e) {
+ // Not a number?
+ return 0;
} finally {
br.close();
}