aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferManager.java')
-rw-r--r--src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferManager.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferManager.java b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferManager.java
new file mode 100644
index 00000000..112aafd1
--- /dev/null
+++ b/src/main/java/de/thedevstack/conversationsplus/services/filetransfer/FileTransferManager.java
@@ -0,0 +1,178 @@
+package de.thedevstack.conversationsplus.services.filetransfer;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import de.thedevstack.android.logcat.Logging;
+import de.thedevstack.conversationsplus.services.FileTransferService;
+import de.thedevstack.conversationsplus.services.filetransfer.http.upload.HttpFileTransferEntity;
+import de.thedevstack.conversationsplus.utils.MessageUtil;
+
+import eu.siacs.conversations.Config;
+import eu.siacs.conversations.entities.Message;
+
+/**
+ *
+ */
+public class FileTransferManager implements FileTransferStatusListener {
+ private SortedSet<WeightedTransferService> transferServices;
+ private static final FileTransferManager INSTANCE = new FileTransferManager();
+ private final HashMap<String, WeightedTransferService> activeTransfers = new HashMap<>();
+
+ private FileTransferManager() {
+ this.transferServices = new TreeSet<>();
+ }
+
+ public static FileTransferManager getInstance() {
+ return INSTANCE;
+ }
+
+ public static void init(FileTransferService... fileTransferServices) {
+ if (null != fileTransferServices && fileTransferServices.length > 0) {
+ for (FileTransferService fts : fileTransferServices) {
+ addFileTransferService(fts);
+ }
+ }
+ }
+
+ public static void init(HashMap<Integer, FileTransferService> fileTransferServices) {
+ for (Map.Entry<Integer, FileTransferService> entry : fileTransferServices.entrySet()) {
+ addFileTransferService(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public static void addFileTransferService(int weight, FileTransferService fts) {
+ fts.addFileTransferStatusListener(INSTANCE);
+ INSTANCE.transferServices.add(new WeightedTransferService(weight, fts));
+ }
+
+ public static void addFileTransferService(FileTransferService fts) {
+ int weight = 1;
+ if (!INSTANCE.transferServices.isEmpty()) {
+ weight = INSTANCE.transferServices.last().weight + 1;
+ }
+ addFileTransferService(weight, fts);
+ }
+
+ /**
+ * Transfers a file for the corresponding message.
+ *
+ * @param message the message containing the file to transfer
+ * @return <code>true</code> if the file transfer was successful, <code>false</code> otherwise
+ */
+ public boolean transferFile(Message message) {
+ return this.transferFile(message, false);
+ }
+
+ /**
+ * Transfers a file for the corresponding message.
+ *
+ * @param message the message containing the file to transfer
+ * @param delay whether the message is delayed or not
+ * @return <code>true</code> if the file transfer was successful, <code>false</code> otherwise
+ */
+ public boolean transferFile(Message message, boolean delay) {
+ Logging.d(Config.LOGTAG, "send file message");
+ boolean transferSuccessfullyStarted = false;
+ for (WeightedTransferService wts : this.transferServices) {
+ try {
+ if (wts.fileTransferService.accept(message)) {
+ transferSuccessfullyStarted = this.startFileTransfer(message, delay, wts);
+ if (transferSuccessfullyStarted) {
+ break;
+ }
+ }
+ } catch (Exception e) {
+ //TODO Do real exception handling!!!!!
+ }
+ }
+ return transferSuccessfullyStarted;
+ }
+
+ /**
+ * Checks whether a message can be sent using this service or not.
+ *
+ * @param message the message to be checked
+ * @return <code>true</code> if the message can be processed, <code>false</code> otherwise
+ */
+ public boolean accept(Message message) {
+ return message.needsUploading();
+ }
+
+ @Override
+ public void onFailure(FileTransferEntity entity, FileTransferFailureReason failureReason) {
+ WeightedTransferService wts = this.activeTransfers.get(entity.getMessage().getUuid());
+ if (null == wts) {
+ return;
+ }
+ boolean delayed = (entity instanceof HttpFileTransferEntity) && ((HttpFileTransferEntity) entity).isDelayed();
+ if (failureReason.isRecoverable()) {
+ wts.fileTransferService.transferFile(entity.getMessage(), delayed);
+ } else {
+ boolean retransferStarted = false;
+ this.activeTransfers.remove(entity.getMessage().getUuid());
+ for (WeightedTransferService newWts : this.transferServices.tailSet(wts)) {
+ if (newWts == wts) { // Same Reference
+ continue;
+ }
+ if (newWts.fileTransferService.accept(entity.getMessage())) {
+ retransferStarted = startFileTransfer(entity.getMessage(), delayed, newWts);
+ if (retransferStarted) {
+ break;
+ }
+ }
+ }
+ if (!retransferStarted) {
+ MessageUtil.markMessage(entity.getMessage(), Message.STATUS_SEND_FAILED);
+ }
+ }
+ }
+
+ @Override
+ public void onCancel(FileTransferEntity entity) {
+ this.activeTransfers.remove(entity.getMessage().getUuid());
+ MessageUtil.markMessage(entity.getMessage(), Message.STATUS_SEND_FAILED); // TODO New Status CANCELED!
+ }
+
+ @Override
+ public void onSuccess(FileTransferEntity entity) {
+ this.activeTransfers.remove(entity.getMessage().getUuid());
+ }
+
+ private boolean startFileTransfer(Message message, boolean delayed, WeightedTransferService wts) {
+ boolean transferSuccessfullyStarted = wts.fileTransferService.transferFile(message, delayed);
+ if (transferSuccessfullyStarted) {
+ this.activeTransfers.put(message.getUuid(), wts);
+ }
+ return transferSuccessfullyStarted;
+ }
+
+ static class WeightedTransferService implements Comparable<WeightedTransferService> {
+ int weight;
+ FileTransferService fileTransferService;
+
+ WeightedTransferService(int weight, FileTransferService service) {
+ this.weight = weight;
+ this.fileTransferService = service;
+ }
+
+ /**
+ * Compares this object to the specified object to determine their relative
+ * order.
+ *
+ * @param another the object to compare to this instance.
+ * @return a negative integer if this instance is less than {@code another};
+ * a positive integer if this instance is greater than
+ * {@code another}; 0 if this instance has the same order as
+ * {@code another}.
+ * @throws ClassCastException if {@code another} cannot be converted into something
+ * comparable to {@code this} instance.
+ */
+ @Override
+ public int compareTo(WeightedTransferService another) {
+ return this.weight - another.weight;
+ }
+ }
+}