fnihs work
im so tired rn
This commit is contained in:
parent
9263818e3e
commit
34a3ee1d38
14 changed files with 365 additions and 10 deletions
15
pom.xml
15
pom.xml
|
@ -17,6 +17,21 @@
|
|||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.11.0</version>
|
||||
<optional>true</optional> <!-- only for giteametadatadao -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package eu.m724.jarupdater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import eu.m724.jarupdater.download.Downloader;
|
||||
import eu.m724.jarupdater.environment.Environment;
|
||||
|
@ -26,6 +29,10 @@ public class Updater {
|
|||
return environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the latest available version
|
||||
* @return a future which can throw ioexpception
|
||||
*/
|
||||
public CompletableFuture<Version> getLatestVersion() {
|
||||
CompletableFuture<Version> currentVersionFuture = metadataProvider.getCurrentVersionMetadata();
|
||||
CompletableFuture<Version> latestVersionFuture = metadataProvider.getLatestVersionMetadata();
|
||||
|
@ -34,14 +41,25 @@ public class Updater {
|
|||
Version currentVersion = currentVersionFuture.join();
|
||||
Version latestVersion = latestVersionFuture.join();
|
||||
|
||||
if (currentVersion == null || latestVersion == null)
|
||||
throw new CompletionException(new IOException());
|
||||
|
||||
return latestVersion.getId() > currentVersion.getId() ? latestVersion : null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* get information about this version
|
||||
* @return a future which can throw ioexpception
|
||||
*/
|
||||
public CompletableFuture<Version> getCurrentVersion() {
|
||||
return metadataProvider.getCurrentVersionMetadata();
|
||||
}
|
||||
|
||||
/**
|
||||
* download the latest available version
|
||||
* @return a future which returns the downloaded file, it can also throw ioexpception or signatureexception
|
||||
*/
|
||||
public CompletableFuture<File> downloadLatestVersion() {
|
||||
CompletableFuture<Version> latestVersionFuture = metadataProvider.getLatestVersionMetadata();
|
||||
|
||||
|
|
|
@ -4,6 +4,19 @@ import java.io.File;
|
|||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface Downloader {
|
||||
/**
|
||||
* downloads a file and verifies it
|
||||
* @param url
|
||||
* @param sha256hex
|
||||
* @return a future which can throw ioexception or signatureexception
|
||||
*/
|
||||
public CompletableFuture<File> downloadAndVerify(String url, String sha256hex);
|
||||
|
||||
/**
|
||||
* moves source into destination
|
||||
* @param source
|
||||
* @param destination
|
||||
* @return a future which can throw ioexception
|
||||
*/
|
||||
public CompletableFuture<Void> install(File source, File destination);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public class SimpleDownloader implements Downloader {
|
|||
|
||||
return downloadedFile;
|
||||
|
||||
} catch (IOException | NoSuchAlgorithmException | SignatureException e) {
|
||||
} catch (IOException | NoSuchAlgorithmException | SignatureException e) { // TODO nosuchalgo should not be thrown
|
||||
throw new CompletionException(e);
|
||||
}
|
||||
|
||||
|
|
81
src/main/java/eu/m724/jarupdater/live/GiteaMetadataDAO.java
Normal file
81
src/main/java/eu/m724/jarupdater/live/GiteaMetadataDAO.java
Normal file
|
@ -0,0 +1,81 @@
|
|||
package eu.m724.jarupdater.live;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpClient.Redirect;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
import eu.m724.jarupdater.object.Version;
|
||||
|
||||
public class GiteaMetadataDAO implements MetadataDAO {
|
||||
private String url;
|
||||
private String branch;
|
||||
|
||||
public GiteaMetadataDAO(String url, String branch) {
|
||||
this.url = url;
|
||||
this.branch = branch;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<String>> getChannels() {
|
||||
String url = getFileUrl("channels.txt");
|
||||
|
||||
CompletableFuture<List<String>> channelsFuture =
|
||||
makeRequest(url).thenApply(response -> {
|
||||
if (response.statusCode() != 200)
|
||||
throw new CompletionException(new IOException("Server returned status code %d".formatted(response.statusCode())));
|
||||
|
||||
return response.body().lines().toList();
|
||||
});
|
||||
|
||||
return channelsFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Version> getMetadata(String channel, String versionLabel) {
|
||||
String url = getFileUrl(versionLabel, "meta-v1.json");
|
||||
|
||||
CompletableFuture<Version> metadataFuture =
|
||||
makeRequest(url).thenApply(response -> {
|
||||
if (response.statusCode() != 200)
|
||||
throw new CompletionException(new IOException("Server returned status code %d".formatted(response.statusCode())));
|
||||
// not throwing nosuchversionexecpion because it's not possible to tell if the server is broken or it really doesn't exist
|
||||
|
||||
Version version = new Gson().fromJson(response.body(), Version.class);
|
||||
return version;
|
||||
});
|
||||
|
||||
return metadataFuture;
|
||||
}
|
||||
|
||||
|
||||
private CompletableFuture<HttpResponse<String>> makeRequest(String url) {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.header("User-Agent", "ju/1") // jar updater v1
|
||||
.build();
|
||||
|
||||
CompletableFuture<HttpResponse<String>> responseFuture =
|
||||
HttpClient.newBuilder()
|
||||
.followRedirects(Redirect.NORMAL)
|
||||
.proxy(ProxySelector.getDefault()).build().
|
||||
sendAsync(request, BodyHandlers.ofString());
|
||||
|
||||
return responseFuture;
|
||||
}
|
||||
|
||||
private String getFileUrl(String... paths) {
|
||||
return url + "/raw/branch/" + branch + "/data/" + String.join("/", paths);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,22 @@
|
|||
package eu.m724.jarupdater.live;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import eu.m724.jarupdater.object.Version;
|
||||
|
||||
public interface MetadataDAO {
|
||||
public CompletableFuture<ArrayList<String>> getChannels();
|
||||
public CompletableFuture<Version> getMetadata(String channel, String version);
|
||||
/**
|
||||
* get available channels online
|
||||
* @return a future which can throw ioexception
|
||||
*/
|
||||
public CompletableFuture<List<String>> getChannels();
|
||||
|
||||
/**
|
||||
* get metadata of a version in channel
|
||||
* @param channel
|
||||
* @param versionLabel
|
||||
* @return a future which can throw ioexcpeitons or nosuchfilexxception
|
||||
*/
|
||||
public CompletableFuture<Version> getMetadata(String channel, String versionLabel);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package eu.m724.jarupdater.live;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import eu.m724.jarupdater.environment.Environment;
|
||||
|
@ -12,14 +12,14 @@ public class MetadataFacade {
|
|||
private MetadataDAO metadataDao;
|
||||
|
||||
private HashMap<String, CompletableFuture<Version>> cache = new HashMap<>();
|
||||
private CompletableFuture<ArrayList<String>> channels = null;
|
||||
private CompletableFuture<List<String>> channels = null;
|
||||
|
||||
public MetadataFacade(Environment environment, MetadataDAO metadataDao) {
|
||||
this.environment = environment;
|
||||
this.metadataDao = metadataDao;
|
||||
}
|
||||
|
||||
public CompletableFuture<ArrayList<String>> getChannels() {
|
||||
public CompletableFuture<List<String>> getChannels() {
|
||||
if (channels == null)
|
||||
channels = metadataDao.getChannels();
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package eu.m724.jarupdater.object;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NoSuchVersionException extends IOException {
|
||||
|
||||
private static final long serialVersionUID = 8435964987348892266L;
|
||||
|
||||
public NoSuchVersionException(String version) {
|
||||
super(version);
|
||||
}
|
||||
|
||||
}
|
|
@ -6,6 +6,14 @@ public class Version {
|
|||
*/
|
||||
public static final int SPEC = 1;
|
||||
|
||||
public Version(int id, long timestamp, String label, String fileUrl, String sha256) {
|
||||
this.id = id;
|
||||
this.timestamp = timestamp;
|
||||
this.label = label;
|
||||
this.fileUrl = fileUrl;
|
||||
this.sha256 = sha256;
|
||||
}
|
||||
|
||||
private int id;
|
||||
private long timestamp;
|
||||
private String label;
|
||||
|
|
46
src/test/java/jarupdater/DownloaderTest.java
Normal file
46
src/test/java/jarupdater/DownloaderTest.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
package jarupdater;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.m724.jarupdater.download.Downloader;
|
||||
|
||||
public class DownloaderTest {
|
||||
@Test
|
||||
public void testDownloader() {
|
||||
Downloader downloader = new MockDownloader();
|
||||
|
||||
File file = downloader.downloadAndVerify("good", "a9194ba3e955ba7482c6552894d4ca41b9bbafd86f4d90f3564c02fcb9e917c2").join();
|
||||
assertNotNull(file);
|
||||
|
||||
try {
|
||||
downloader.downloadAndVerify("invalid", "678af2539cb4156f4e092d5e80de23aed7d9355774697267979b94e5cceec1b2").join();
|
||||
fail("this should have thrown");
|
||||
} catch (CompletionException e) {
|
||||
assert e.getCause() instanceof IOException;
|
||||
}
|
||||
|
||||
try {
|
||||
downloader.downloadAndVerify("bad", "1dd7d814fa99d923eee9e483c25a02346c47f84dbc160a1a9f87e9b051e77ee1").join();
|
||||
fail("this should have thrown");
|
||||
} catch (CompletionException e) {
|
||||
assert e.getCause() instanceof SignatureException;
|
||||
}
|
||||
|
||||
downloader.install(file, file).join();
|
||||
try {
|
||||
downloader.install(new File("ialsoexistfortesting"), file).join();
|
||||
fail("this should have thrown");
|
||||
} catch (CompletionException e) {
|
||||
assert e.getCause() instanceof IOException;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
19
src/test/java/jarupdater/EnvironmentTest.java
Normal file
19
src/test/java/jarupdater/EnvironmentTest.java
Normal file
|
@ -0,0 +1,19 @@
|
|||
package jarupdater;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.m724.jarupdater.environment.ConstantEnvironment;
|
||||
import eu.m724.jarupdater.environment.Environment;
|
||||
|
||||
public class EnvironmentTest {
|
||||
@Test
|
||||
public void testConstantEnvironment() {
|
||||
Environment environment = new ConstantEnvironment("1.0", "stable", Path.of("idontexist"));
|
||||
|
||||
assert environment.getRunningVersion().equals("1.0");
|
||||
assert environment.getChannel().equals("stable");
|
||||
assert environment.getRunningJarFilePath().equals(Path.of("idontexist"));
|
||||
}
|
||||
}
|
44
src/test/java/jarupdater/MetadataTest.java
Normal file
44
src/test/java/jarupdater/MetadataTest.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
package jarupdater;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import eu.m724.jarupdater.environment.ConstantEnvironment;
|
||||
import eu.m724.jarupdater.environment.Environment;
|
||||
import eu.m724.jarupdater.live.MetadataDAO;
|
||||
import eu.m724.jarupdater.live.MetadataFacade;
|
||||
import eu.m724.jarupdater.object.Version;
|
||||
|
||||
public class MetadataTest {
|
||||
@Test
|
||||
public void testMetadata() {
|
||||
Environment environment = new ConstantEnvironment("1.0", "stable", Path.of("idontexist"));
|
||||
|
||||
MetadataDAO dao = new MockMetadataDAO();
|
||||
MetadataFacade facade = new MetadataFacade(environment, dao);
|
||||
|
||||
assert facade.getChannels().join().contains(environment.getChannel());
|
||||
|
||||
Version cur = facade.getCurrentVersionMetadata().join();
|
||||
Version lat = facade.getLatestVersionMetadata().join();
|
||||
|
||||
assert cur != null;
|
||||
assert lat != null;
|
||||
|
||||
assertFalse(cur.equals(lat));
|
||||
assertTrue(cur.getLabel().equals(environment.getRunningVersion()));
|
||||
assertTrue(lat.getLabel().equals("1.1"));
|
||||
|
||||
try {
|
||||
facade.getVersionMetadata("invalidversion").join();
|
||||
fail("this should have thrown");
|
||||
} catch (CompletionException e) {
|
||||
assert e.getCause() instanceof IOException;
|
||||
}
|
||||
}
|
||||
}
|
44
src/test/java/jarupdater/MockDownloader.java
Normal file
44
src/test/java/jarupdater/MockDownloader.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
package jarupdater;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.security.SignatureException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import eu.m724.jarupdater.download.Downloader;
|
||||
|
||||
public class MockDownloader implements Downloader {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<File> downloadAndVerify(String url, String sha256hex) {
|
||||
CompletableFuture<File> future = null;
|
||||
|
||||
switch (url) {
|
||||
case "good":
|
||||
future = CompletableFuture.completedFuture(new File("ionlyexistfortesting"));
|
||||
break;
|
||||
case "invalid":
|
||||
future = CompletableFuture.failedFuture(new CompletionException(new IOException()));
|
||||
break;
|
||||
case "bad":
|
||||
future = CompletableFuture.failedFuture(new CompletionException(new SignatureException()));
|
||||
break;
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> install(File source, File destination) {
|
||||
CompletableFuture<Void> future = null;
|
||||
|
||||
if (source.getName().equals("ionlyexistfortesting"))
|
||||
future = CompletableFuture.completedFuture(null);
|
||||
else
|
||||
future = CompletableFuture.failedFuture(new CompletionException(new IOException()));
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
}
|
43
src/test/java/jarupdater/MockMetadataDAO.java
Normal file
43
src/test/java/jarupdater/MockMetadataDAO.java
Normal file
|
@ -0,0 +1,43 @@
|
|||
package jarupdater;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import eu.m724.jarupdater.live.MetadataDAO;
|
||||
import eu.m724.jarupdater.object.Version;
|
||||
|
||||
public class MockMetadataDAO implements MetadataDAO {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<String>> getChannels() {
|
||||
List<String> channels = Arrays.asList("stable", "beta", "alpha");
|
||||
return CompletableFuture.completedFuture(channels);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Version> getMetadata(String channel, String versionLabel) {
|
||||
Version version = null;
|
||||
String fileUrl = "http://127.0.0.1:17357/%s/%s.jar".formatted(channel, versionLabel);
|
||||
|
||||
switch (versionLabel) {
|
||||
case "1.0":
|
||||
version = new Version(1, 100, "1.0", fileUrl, "dd3822ed965b2820aa0800f04b86f26d0b656fca3b97ddd264046076f81e3a24");
|
||||
break;
|
||||
case "1.1":
|
||||
version = new Version(2, 200, "1.1", fileUrl, "4d59994f607b89987d5bff430a4229edbbb045b3da9eaf1c63fa8e5fb208d824");
|
||||
break;
|
||||
case "latest":
|
||||
version = new Version(2, 200, "1.1", fileUrl, "4d59994f607b89987d5bff430a4229edbbb045b3da9eaf1c63fa8e5fb208d824");
|
||||
break;
|
||||
default:
|
||||
return CompletableFuture.failedFuture(new CompletionException(new IOException("no such version")));
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(version);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue