Skip to content

Commit c32dba7

Browse files
committed
download and FLUProgression
1 parent 217e741 commit c32dba7

File tree

6 files changed

+269
-3
lines changed

6 files changed

+269
-3
lines changed

src/main/java/fr/formiko/utils/FLUFiles.java

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.formiko.utils;
22

3+
import fr.formiko.utils.progressions.FLUProgression;
34
import java.io.File;
45
import java.io.IOException;
56
import java.io.InputStream;
@@ -22,13 +23,18 @@
2223
*
2324
* @author Hydrolien
2425
* @since 0.0.3
25-
* @version 0.0.3
26+
* @version 0.0.4
2627
*/
2728
public class FLUFiles {
2829
private static FLUFilesInternal internal = new FLUFilesInternal();
30+
private static FLUProgression progression;
2931

3032
private FLUFiles() {} // hide constructor
3133

34+
// GET SET ----------------------------------------------------------------------
35+
public static FLUProgression getProgression() { return progression; }
36+
public static void setProgression(FLUProgression progression) { FLUFiles.progression = progression; }
37+
3238
public static boolean isAValidePath(String path) { return internal.isAValidePath(path); }
3339
public static boolean createFile(String path) { return internal.createFile(path); }
3440
public static boolean createDirectory(String path) { return internal.createDirectory(path); }
@@ -50,8 +56,7 @@ public static boolean unzip(String source, String destination, String directoryI
5056
}
5157
public static boolean unzip(String source, String destination) { return unzip(source, destination, ""); }
5258

53-
public static boolean download(String url, String destination, boolean withProgressInfo) { return false; }
54-
public static boolean download(String url, String destination) { return download(url, destination, false); }
59+
public static boolean download(String url, String destination) { return internal.download(url, destination); }
5560
public static boolean downloadAndUnzip(String url, String destination, String directoryInsideZipToGet) { return false; }
5661
public static boolean downloadAndUnzip(String url, String destination) { return downloadAndUnzip(url, destination, ""); }
5762
public static String downloadAndRead(String url) { return null; }
@@ -325,7 +330,82 @@ private void createZipEntry(String destination, String directoryInsideZipToGet,
325330
Files.copy(zis, Paths.get(absoluteDestinationPath + entryName));
326331
}
327332
}
333+
}
334+
}
335+
336+
private boolean download(String url, String destination) {
337+
if (isAValidePath(url) && isAValidePath(destination)) {
338+
try {
339+
URL urlObject = URI.create(url).toURL();
340+
InputStream is = urlObject.openStream();
341+
File destinationFile = new File(destination);
342+
createParents(destinationFile);
343+
Files.copy(is, destinationFile.toPath());
344+
return true;
345+
} catch (IOException e) {
346+
return false;
347+
}
348+
} else {
349+
return false;
350+
}
351+
}
352+
}
353+
354+
class FLUProgressionThread extends Thread {
355+
private File fileOut;
356+
private long fileToDowloadSize;
357+
private boolean running;
358+
private String downloadName;
359+
private FLUProgression progressionInstance;
360+
/**
361+
* {@summary Main constructor.}<br>
362+
*
363+
* @param fileOut file that we are curently filling by the downloading file
364+
* @param fileToDowloadSize size that we should reach when download will end
365+
*/
366+
public FLUProgressionThread(File fileOut, long fileToDowloadSize, String downloadName, FLUProgression progressionInstance) {
367+
this.fileOut = fileOut;
368+
this.fileToDowloadSize = fileToDowloadSize;
369+
this.downloadName = downloadName;
370+
this.progressionInstance = progressionInstance;
371+
running = true;
372+
}
373+
374+
public void stopRuning() { running = false; }
375+
/**
376+
* {@summary Main function that print every second %age of download done.}<br>
377+
*/
378+
public void run() {
379+
long fileOutSize = 0;
380+
long lastFileOutSize = 0;
381+
long timeStart = System.currentTimeMillis();
382+
long timeFromLastBitDownload = timeStart;
383+
while (fileOutSize < fileToDowloadSize && running) {
384+
fileOutSize = fileOut.length();
385+
double progression = ((double) fileOutSize) / (double) fileToDowloadSize;
386+
int percent = (int) (100 * progression);
387+
long curentTime = System.currentTimeMillis();
388+
long timeElapsed = curentTime - timeStart;
389+
long timeLeft = (long) ((double) ((timeElapsed / progression) - timeElapsed));
390+
String sTimeLeft = FLUTime.msToTime(timeLeft) + " left";
391+
String message = "Downloading " + downloadName + " - " + percent + "% - ";
392+
if (fileOutSize != lastFileOutSize) {// update watcher of working download
393+
timeFromLastBitDownload = curentTime;
394+
}
395+
if (timeFromLastBitDownload + 10000 < curentTime) {
396+
message += (((curentTime - timeFromLastBitDownload) / 1000) + "s untill a new bit haven't been download");
397+
if (timeFromLastBitDownload + 60000 < curentTime) {
398+
stopRuning();
399+
// TODO stop the IO opperation.
400+
}
401+
} else {
402+
message += sTimeLeft;
403+
}
404+
progressionInstance.setDownloadingValue(percent);
405+
progressionInstance.setDownloadingMessage(message);
328406

407+
lastFileOutSize = fileOutSize;
408+
FLUTime.sleep(50);
329409
}
330410
}
331411
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package fr.formiko.utils;
2+
3+
/**
4+
* {@summary Time functions.}<br>
5+
*
6+
* @author Hydrolien
7+
*/
8+
public class FLUTime {
9+
/**
10+
* {@summary return time with as specify number of unit.}<br>
11+
* If language file is not initialize, it will use french letter: 3j 23h 59min 10,1267s
12+
*
13+
* @param ms times in ms.
14+
* @param nbrOfUnit number of units to include in the return string.
15+
* @param dayOn enable or disable day as a unit.
16+
* @since 0.0.4
17+
*/
18+
public static String msToTime(long ms, int nbrOfUnit, boolean dayOn) {
19+
if (nbrOfUnit < 1) {
20+
return "";
21+
}
22+
String ts[] = {"t.d", "t.h", "t.min", "t.s", "t.ms"};
23+
long tl[] = msToTimeLongArray(ms, dayOn);
24+
int k = 0;
25+
int i = 0;
26+
String r = "";
27+
while (k < nbrOfUnit && i < 5) {
28+
if (tl[i] > 0) {
29+
if (!r.equals("")) {
30+
r += " ";
31+
}
32+
if (i == 3 && k + 1 < nbrOfUnit && tl[i + 1] > 0) { // si on doit traiter les s et les ms ensembles.
33+
String s = "" + tl[i + 1];
34+
while (s.length() < 3) {
35+
s = "0" + s;
36+
}
37+
while (s.length() > 1 && s.charAt(s.length() - 1) == '0') {
38+
s = s.substring(0, s.length() - 1);
39+
}
40+
r += tl[i] + "," + s + ts[i].substring(2);
41+
k++;
42+
i++;
43+
} else {
44+
r += tl[i] + ts[i].substring(2);
45+
}
46+
k++;
47+
}
48+
i++;// pour ne pas sortir du tableau.
49+
}
50+
if (r.equals("")) {
51+
r = tl[4] + ts[4].substring(2);
52+
}
53+
return r;
54+
}
55+
public static String msToTime(long ms) { return msToTime(ms, 2, true); }
56+
57+
/**
58+
* {@summary return time on a long [].}
59+
*
60+
* @param ms times in ms.
61+
* @param dayOn enable or disable day as a unit.
62+
*/
63+
public static long[] msToTimeLongArray(long ms, boolean dayOn) {
64+
long tr[] = new long[5];
65+
if (ms < 0) {
66+
tr[4] = -1;
67+
return tr;
68+
}
69+
int nbrMsD = 86400000;
70+
int nbrMsH = 3600000;
71+
int nbrMsM = 60000;
72+
int nbrMsS = 1000;
73+
long d, h, m, s;
74+
if (dayOn) {
75+
d = ms / nbrMsD;
76+
h = (ms % nbrMsD) / nbrMsH;
77+
} else {
78+
d = 0;
79+
h = ms / nbrMsH;
80+
}
81+
m = (ms % nbrMsH) / nbrMsM;
82+
s = (ms % nbrMsM) / nbrMsS;
83+
ms = ms % nbrMsS;
84+
tr[0] = d;
85+
tr[1] = h;
86+
tr[2] = m;
87+
tr[3] = s;
88+
tr[4] = ms;
89+
return tr;
90+
}
91+
92+
/**
93+
* {@summary Try to stop execution of the programme during some ms.}
94+
*
95+
* @param ms number of ms to wait before continue.
96+
*/
97+
public static void sleep(int ms) {
98+
if (ms < 1) {
99+
return;
100+
}
101+
try {
102+
Thread.sleep(ms);
103+
} catch (InterruptedException ie) {
104+
return;
105+
}
106+
}
107+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package fr.formiko.utils.progressions;
2+
3+
/**
4+
* {@summary Update a progression state.}
5+
*
6+
* @since 0.0.4
7+
* @author Hydrolien
8+
*/
9+
public interface FLUProgression {
10+
/***
11+
* {@summary Update downloading message.}
12+
*
13+
* @param message the message
14+
*/
15+
default void setDownloadingMessage(String message) {}
16+
/***
17+
* {@summary Update downloading %age.}
18+
*
19+
* @param state the state as a %age
20+
*/
21+
default void setDownloadingValue(int state) {}
22+
/***
23+
* {@summary Initialize the game launcher.}
24+
*/
25+
default void iniLauncher() {}
26+
/***
27+
* {@summary Close the game launcher.}
28+
*/
29+
default void closeLauncher() {}
30+
/***
31+
* {@summary Hide or show buttonRetry of FFrameLauncher.}
32+
*/
33+
default void setButtonRetryVisible(boolean visible) {}
34+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package fr.formiko.utils.progressions;
2+
3+
import fr.formiko.utils.FLUFiles;
4+
5+
/**
6+
* {@summary Simple CLI view that are update as a progression for downloading files.}<br>
7+
*/
8+
public class FLUProgressionCLI implements FLUProgression {
9+
@Override
10+
public void iniLauncher() { FLUFiles.setProgression(this); }
11+
@Override
12+
public void setDownloadingMessage(String message) { System.out.println("Dowload: " + message); }
13+
@Override
14+
public void setDownloadingValue(int value) { System.out.println(value + "% done"); }
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package fr.formiko.utils.progressions;
2+
3+
4+
/**
5+
* {@summary A null implementation.}<br>
6+
* It allow to avoid error of null implementation.<br>
7+
*
8+
* @author Hydrolien
9+
* @since 0.0.4
10+
*/
11+
public class FLUProgressionNull implements FLUProgression {
12+
13+
}

src/test/java/fr/formiko/utils/FLUFilesTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,23 @@ private static Stream<Arguments> testUnzipSource() {
316316
TEST_PATH_TEMPORARY + "existingFile.txt"));
317317
}
318318

319+
@ParameterizedTest
320+
@MethodSource("testDownloadSource")
321+
void testDownload(String url, boolean shouldWork, String destination, String fileToCheck) {
322+
assertEquals(shouldWork, FLUFiles.download(url, destination));
323+
if (shouldWork) {
324+
assertTrue(new File(fileToCheck).exists());
325+
assertEquals(true, FLUFiles.delete(destination));
326+
}
327+
}
328+
329+
private static Stream<Arguments> testDownloadSource() {
330+
return Stream.of(Arguments.of(
331+
"https://gist.githubusercontent.com/HydrolienF/0dc21ed2c0788b4de206102871410d4b/raw/a85c8bcf47ae0c081841df756c68122c83151747/fr.json",
332+
true, TEST_PATH_TEMPORARY + "fr.json", TEST_PATH_TEMPORARY + "fr.json"),
333+
Arguments.of("https://unexisting.url", false, TEST_PATH_TEMPORARY + "unexisting.url", null));
334+
}
335+
319336
public static void main(String[] args) {
320337
new FLUFilesTest().testUnzip(TEST_PATH + "existingDir/", true, TEST_PATH_TEMPORARY + "createdZip", "",
321338
TEST_PATH_TEMPORARY + "existingDir/");

0 commit comments

Comments
 (0)