| 1 | package net.oni2.aeinstaller.backend.packages.download; | 
 
 
 
 
 | 2 |  | 
 
 
 
 
 | 3 | import java.util.Date; | 
 
 
 
 
 | 4 | import java.util.TreeSet; | 
 
 
 
 
 | 5 | import java.util.Vector; | 
 
 
 
 
 | 6 |  | 
 
 
 
 
 | 7 | import net.oni2.aeinstaller.backend.packages.Package; | 
 
 
 
 
 | 8 | import net.oni2.aeinstaller.backend.packages.download.ModDownload.ModDownloadState; | 
 
 
 
 
 | 9 |  | 
 
 
 
 
 | 10 | /** | 
 
 
 
 
 | 11 | * @author Christian Illy | 
 
 
 
 
 | 12 | */ | 
 
 
 
 
 | 13 | public class ModDownloader implements ModDownloadListener { | 
 
 
 
 
 | 14 | /** | 
 
 
 
 
 | 15 | * @author Christian Illy | 
 
 
 
 
 | 16 | */ | 
 
 
 
 
 | 17 | public enum State { | 
 
 
 
 
 | 18 | /** | 
 
 
 
 
 | 19 | * Downloads running | 
 
 
 
 
 | 20 | */ | 
 
 
 
 
 | 21 | RUNNING, | 
 
 
 
 
 | 22 | /** | 
 
 
 
 
 | 23 | * Aborted because of an error | 
 
 
 
 
 | 24 | */ | 
 
 
 
 
 | 25 | ERROR, | 
 
 
 
 
 | 26 | /** | 
 
 
 
 
 | 27 | * Downloads interrupted | 
 
 
 
 
 | 28 | */ | 
 
 
 
 
 | 29 | INTERRUPTED, | 
 
 
 
 
 | 30 | /** | 
 
 
 
 
 | 31 | * When the last file was downloaded and only unpacking is left | 
 
 
 
 
 | 32 | */ | 
 
 
 
 
 | 33 | LAST_FILE_DOWNLOADED, | 
 
 
 
 
 | 34 | /** | 
 
 
 
 
 | 35 | * Everything completed | 
 
 
 
 
 | 36 | */ | 
 
 
 
 
 | 37 | FINISHED | 
 
 
 
 
 | 38 | }; | 
 
 
 
 
 | 39 |  | 
 
 
 
 
 | 40 | private int currentDownload = -1; | 
 
 
 
 
 | 41 | private int unpacked = 0; | 
 
 
 
 
 | 42 | private Vector<ModDownload> downloads = new Vector<ModDownload>(); | 
 
 
 
 
 | 43 | private int totalSize = 0; | 
 
 
 
 
 | 44 | private int downloadedComplete = 0; | 
 
 
 
 
 | 45 | private int downloadedCurrent = 0; | 
 
 
 
 
 | 46 | private long startMS; | 
 
 
 
 
 | 47 | private State state = State.RUNNING; | 
 
 
 
 
 | 48 | private ModDownloaderListener listener; | 
 
 
 
 
 | 49 |  | 
 
 
 
 
 | 50 | /** | 
 
 
 
 
 | 51 | * Create a mods-download-process | 
 
 
 
 
 | 52 | * | 
 
 
 
 
 | 53 | * @param mods | 
 
 
 
 
 | 54 | *            Mods to download | 
 
 
 
 
 | 55 | * @param listener | 
 
 
 
 
 | 56 | *            Listener for status updates | 
 
 
 
 
 | 57 | */ | 
 
 
 
 
 | 58 | public ModDownloader(TreeSet<Package> mods, ModDownloaderListener listener) { | 
 
 
 
 
 | 59 | this.listener = listener; | 
 
 
 
 
 | 60 | for (Package m : mods) { | 
 
 
 
 
 | 61 | downloads.add(new ModDownload(m, this)); | 
 
 
 
 
 | 62 | totalSize += m.getZipSize(); | 
 
 
 
 
 | 63 | } | 
 
 
 
 
 | 64 | startMS = new Date().getTime(); | 
 
 
 
 
 | 65 | startNextDownload(); | 
 
 
 
 
 | 66 | } | 
 
 
 
 
 | 67 |  | 
 
 
 
 
 | 68 | private void startNextDownload() { | 
 
 
 
 
 | 69 | if (currentDownload >= 0) | 
 
 
 
 
 | 70 | downloadedComplete += downloads.get(currentDownload).getSize(); | 
 
 
 
 
 | 71 | currentDownload++; | 
 
 
 
 
 | 72 | downloadedCurrent = 0; | 
 
 
 
 
 | 73 | if ((state == State.RUNNING) && (currentDownload < downloads.size())) { | 
 
 
 
 
 | 74 | downloads.get(currentDownload).start(); | 
 
 
 
 
 | 75 | } else if (state == State.RUNNING) { | 
 
 
 
 
 | 76 | state = State.LAST_FILE_DOWNLOADED; | 
 
 
 
 
 | 77 | notifyListener(); | 
 
 
 
 
 | 78 | } else { | 
 
 
 
 
 | 79 | notifyListener(); | 
 
 
 
 
 | 80 | } | 
 
 
 
 
 | 81 | } | 
 
 
 
 
 | 82 |  | 
 
 
 
 
 | 83 | private int getTimeElapsed() { | 
 
 
 
 
 | 84 | int total = (int) (new Date().getTime() - startMS); | 
 
 
 
 
 | 85 | return total; | 
 
 
 
 
 | 86 | } | 
 
 
 
 
 | 87 |  | 
 
 
 
 
 | 88 | private int getDownloadSpeed() { | 
 
 
 
 
 | 89 | int elap = getTimeElapsed(); | 
 
 
 
 
 | 90 | long down = downloadedComplete + downloadedCurrent; | 
 
 
 
 
 | 91 | if (elap > 0) | 
 
 
 
 
 | 92 | return (int)(down * 1000 / elap); | 
 
 
 
 
 | 93 | else | 
 
 
 
 
 | 94 | return 1; | 
 
 
 
 
 | 95 | } | 
 
 
 
 
 | 96 |  | 
 
 
 
 
 | 97 | private int getTimeRemaining() { | 
 
 
 
 
 | 98 | int remainingSize = totalSize | 
 
 
 
 
 | 99 | - (downloadedComplete + downloadedCurrent); | 
 
 
 
 
 | 100 | return remainingSize / getDownloadSpeed(); | 
 
 
 
 
 | 101 | } | 
 
 
 
 
 | 102 |  | 
 
 
 
 
 | 103 | private void notifyListener() { | 
 
 
 
 
 | 104 | if (currentDownload < downloads.size()) { | 
 
 
 
 
 | 105 | listener.updateStatus(this, | 
 
 
 
 
 | 106 | downloads.get(currentDownload).getMod(), state, unpacked, | 
 
 
 
 
 | 107 | downloads.size(), downloadedComplete + downloadedCurrent, | 
 
 
 
 
 | 108 | totalSize, getTimeElapsed() / 1000, getTimeRemaining(), | 
 
 
 
 
 | 109 | getDownloadSpeed()); | 
 
 
 
 
 | 110 | } else { | 
 
 
 
 
 | 111 | listener.updateStatus(this, null, state, unpacked, | 
 
 
 
 
 | 112 | downloads.size(), downloadedComplete + downloadedCurrent, | 
 
 
 
 
 | 113 | totalSize, getTimeElapsed() / 1000, getTimeRemaining(), | 
 
 
 
 
 | 114 | getDownloadSpeed()); | 
 
 
 
 
 | 115 | } | 
 
 
 
 
 | 116 | } | 
 
 
 
 
 | 117 |  | 
 
 
 
 
 | 118 | /** | 
 
 
 
 
 | 119 | * @return total download size | 
 
 
 
 
 | 120 | */ | 
 
 
 
 
 | 121 | public int getTotalSize() { | 
 
 
 
 
 | 122 | return totalSize; | 
 
 
 
 
 | 123 | } | 
 
 
 
 
 | 124 |  | 
 
 
 
 
 | 125 | /** | 
 
 
 
 
 | 126 | * @return Is this process finished | 
 
 
 
 
 | 127 | */ | 
 
 
 
 
 | 128 | public boolean isFinished() { | 
 
 
 
 
 | 129 | return state == State.FINISHED; | 
 
 
 
 
 | 130 | } | 
 
 
 
 
 | 131 |  | 
 
 
 
 
 | 132 | @Override | 
 
 
 
 
 | 133 | public void modDownloadStatusUpdate(ModDownload source, | 
 
 
 
 
 | 134 | ModDownloadState state, int done, int total) { | 
 
 
 
 
 | 135 | switch (state) { | 
 
 
 
 
 | 136 | case RUNNING: | 
 
 
 
 
 | 137 | downloadedCurrent = done; | 
 
 
 
 
 | 138 | notifyListener(); | 
 
 
 
 
 | 139 | break; | 
 
 
 
 
 | 140 | case ERROR: | 
 
 
 
 
 | 141 | this.state = State.ERROR; | 
 
 
 
 
 | 142 | break; | 
 
 
 
 
 | 143 | case DOWNLOADED: | 
 
 
 
 
 | 144 | if (source == downloads.get(currentDownload)) | 
 
 
 
 
 | 145 | startNextDownload(); | 
 
 
 
 
 | 146 | break; | 
 
 
 
 
 | 147 | case UNPACKED: | 
 
 
 
 
 | 148 | source.getMod().updateLocalData(); | 
 
 
 
 
 | 149 | unpacked++; | 
 
 
 
 
 | 150 | if (unpacked >= downloads.size()) | 
 
 
 
 
 | 151 | this.state = State.FINISHED; | 
 
 
 
 
 | 152 | notifyListener(); | 
 
 
 
 
 | 153 | break; | 
 
 
 
 
 | 154 | case INIT: | 
 
 
 
 
 | 155 | break; | 
 
 
 
 
 | 156 | case INTERRUPTED: | 
 
 
 
 
 | 157 | break; | 
 
 
 
 
 | 158 | } | 
 
 
 
 
 | 159 | } | 
 
 
 
 
 | 160 |  | 
 
 
 
 
 | 161 | /** | 
 
 
 
 
 | 162 | * Abort download process | 
 
 
 
 
 | 163 | */ | 
 
 
 
 
 | 164 | public void abort() { | 
 
 
 
 
 | 165 | if (currentDownload < downloads.size()) { | 
 
 
 
 
 | 166 | state = State.INTERRUPTED; | 
 
 
 
 
 | 167 | ModDownload md = downloads.get(currentDownload); | 
 
 
 
 
 | 168 | md.abort(); | 
 
 
 
 
 | 169 | } | 
 
 
 
 
 | 170 | } | 
 
 
 
 
 | 171 |  | 
 
 
 
 
 | 172 | } |