WIP: repositoryLoader and infrastructure

This commit is contained in:
Elias Müller 2024-12-04 23:34:12 +01:00
parent 86677c942f
commit b3c43f1763
8 changed files with 97 additions and 90 deletions

View File

@ -1,5 +1,6 @@
package eu.mhsl.craftattack.spawn; package eu.mhsl.craftattack.spawn;
import eu.mhsl.craftattack.spawn.api.client.RepositoryLoader;
import eu.mhsl.craftattack.spawn.api.server.HttpServer; import eu.mhsl.craftattack.spawn.api.server.HttpServer;
import eu.mhsl.craftattack.spawn.appliance.Appliance; import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.config.Configuration; import eu.mhsl.craftattack.spawn.config.Configuration;
@ -19,6 +20,7 @@ public final class Main extends JavaPlugin {
private static Logger logger; private static Logger logger;
private List<Appliance> appliances; private List<Appliance> appliances;
private final RepositoryLoader repositoryLoader = new RepositoryLoader();
@Override @Override
public void onEnable() { public void onEnable() {
@ -98,6 +100,10 @@ public final class Main extends JavaPlugin {
return appliances; return appliances;
} }
public RepositoryLoader getRepositoryLoader() {
return this.repositoryLoader;
}
public static Main instance() { public static Main instance() {
return instance; return instance;
} }

View File

@ -1,7 +1,8 @@
package eu.mhsl.craftattack.spawn.api.client; package eu.mhsl.craftattack.spawn.api.client;
import com.google.gson.Gson; import eu.mhsl.craftattack.spawn.Main;
import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URIBuilder;
import org.jetbrains.annotations.Nullable;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -12,40 +13,49 @@ import java.net.http.HttpResponse;
import java.util.function.Consumer; import java.util.function.Consumer;
public class HttpRepository extends Repository { public class HttpRepository extends Repository {
Consumer<URIBuilder> baseUriBuilder; private final Consumer<URIBuilder> baseUriBuilder;
public HttpRepository(URI basePath, Consumer<URIBuilder> baseUriBuilder) {
public HttpRepository(URI basePath) {
this(basePath, null);
}
public HttpRepository(URI basePath, @Nullable Consumer<URIBuilder> baseUriBuilder) {
super(basePath); super(basePath);
this.baseUriBuilder = baseUriBuilder;
this.baseUriBuilder = baseUriBuilder == null
? uriBuilder -> {}
: baseUriBuilder;
} }
public record RequestResponse<TData>(int status, TData data) { public record RequestResponse<TData>(int status, TData data) {
} }
protected <TInput, TOutput> RequestResponse<TOutput> post(String command, TInput data, Class<TOutput> clazz) { protected <TInput, TOutput> RequestResponse<TOutput> post(String command, TInput data, Class<TOutput> clazz) {
return this.post(command, uriBuilder -> baseUriBuilder.accept(uriBuilder), data, clazz); return this.post(command, parameters -> {}, data, clazz);
} }
protected <TInput, TOutput> RequestResponse<TOutput> post(String command, Consumer<URIBuilder> parameters, TInput data, Class<TOutput> clazz) { protected <TInput, TOutput> RequestResponse<TOutput> post(String command, Consumer<URIBuilder> parameters, TInput data, Class<TOutput> clazz) {
HttpRequest request = this.getRequestBuilder(this.getUri(command)) HttpRequest request = this.getRequestBuilder(this.getUri(command, parameters))
.POST(HttpRequest.BodyPublishers.ofString(new Gson().toJson(data))) .POST(HttpRequest.BodyPublishers.ofString(this.gson.toJson(data)))
.build(); .build();
RequestResponse<String> rawResponse = this.runRequest(request); return this.execute(request, clazz);
return new RequestResponse<>(rawResponse.status, new Gson().fromJson(rawResponse.data, clazz));
} }
protected <TOutput> RequestResponse<TOutput> get(String command, Class<TOutput> clazz) { protected <TOutput> RequestResponse<TOutput> get(String command, Class<TOutput> clazz) {
HttpRequest request = this.getRequestBuilder(this.getUri(command)) return this.get(command, parameters -> {}, clazz);
}
protected <TOutput> RequestResponse<TOutput> get(String command, Consumer<URIBuilder> parameters, Class<TOutput> clazz) {
HttpRequest request = this.getRequestBuilder(this.getUri(command, parameters))
.GET() .GET()
.build(); .build();
RequestResponse<String> rawResponse = this.runRequest(request); return this.execute(request, clazz);
return new RequestResponse<>(rawResponse.status, new Gson().fromJson(rawResponse.data, clazz));
} }
private URI getUri(String command) { private URI getUri(String command, Consumer<URIBuilder> parameters) {
try { try {
URIBuilder builder = new URIBuilder(this.basePath + "/" + command); URIBuilder builder = new URIBuilder(this.basePath + "/" + command);
this.baseUriBuilder.accept(builder); this.baseUriBuilder.accept(builder);
parameters.accept(builder);
return builder.build(); return builder.build();
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -55,16 +65,22 @@ public class HttpRepository extends Repository {
private HttpRequest.Builder getRequestBuilder(URI endpoint) { private HttpRequest.Builder getRequestBuilder(URI endpoint) {
return HttpRequest.newBuilder() return HttpRequest.newBuilder()
.uri(endpoint) .uri(endpoint)
.header("User-Agent", Main.instance().getServer().getBukkitVersion())
.header("Content-Type", "application/json"); .header("Content-Type", "application/json");
} }
private RequestResponse<String> runRequest(HttpRequest request) { private <TResponse> RequestResponse<TResponse> execute(HttpRequest request, Class<TResponse> clazz) {
RequestResponse<String> rawResponse = this.sendHttp(request);
return new RequestResponse<>(rawResponse.status, this.gson.fromJson(rawResponse.data, clazz));
}
private RequestResponse<String> sendHttp(HttpRequest request) {
try(HttpClient client = HttpClient.newHttpClient()) { try(HttpClient client = HttpClient.newHttpClient()) {
HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString()); HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return new RequestResponse<>(httpResponse.statusCode(), httpResponse.body()); return new RequestResponse<>(httpResponse.statusCode(), httpResponse.body());
} catch(IOException | InterruptedException e) { } catch(IOException | InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
} }

View File

@ -1,11 +1,15 @@
package eu.mhsl.craftattack.spawn.api.client; package eu.mhsl.craftattack.spawn.api.client;
import com.google.gson.Gson;
import java.net.URI; import java.net.URI;
public class Repository { public class Repository {
protected URI basePath; protected URI basePath;
protected Gson gson;
public Repository(URI basePath) { public Repository(URI basePath) {
this.basePath = basePath; this.basePath = basePath;
this.gson = new Gson();
} }
} }

View File

@ -0,0 +1,36 @@
package eu.mhsl.craftattack.spawn.api.client;
import org.apache.commons.lang3.NotImplementedException;
import org.reflections.Reflections;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Set;
public class RepositoryLoader {
private final List<Repository> repositories;
public RepositoryLoader() {
Reflections reflections = new Reflections(this.getClass().getPackageName());
Set<Class<? extends Repository>> repositories = reflections.getSubTypesOf(Repository.class);
this.repositories = repositories.stream()
.map(clazz -> {
try {
return (Repository) clazz.getDeclaredConstructor().newInstance();
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
throw new RuntimeException(e);
}
})
.toList();
}
public <T> T getRepository(Class<T> clazz) {
//noinspection unchecked
return this.repositories.stream()
.filter(clazz::isInstance)
.map(repository -> (T) repository)
.findFirst()
.orElseThrow(() -> new NotImplementedException(String.format("Repository '%s' not found!", clazz.getSimpleName())));
}
}

View File

@ -1,15 +1,13 @@
package eu.mhsl.craftattack.spawn.api.client.repositories; package eu.mhsl.craftattack.spawn.api.client.repositories;
import eu.mhsl.craftattack.spawn.api.client.HttpRepository; import eu.mhsl.craftattack.spawn.api.client.HttpRepository;
import org.apache.http.client.utils.URIBuilder; import eu.mhsl.craftattack.spawn.util.api.ApiUtil;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID; import java.util.UUID;
public class ReportRepository extends HttpRepository { public class ReportRepository extends HttpRepository {
public ReportRepository() throws URISyntaxException { public ReportRepository() {
super(new URI("asdasdas")); super(ApiUtil.getBaseUri());
} }
public record SendReportResponse(UUID user) {} public record SendReportResponse(UUID user) {}

View File

@ -1,6 +1,7 @@
package eu.mhsl.craftattack.spawn.appliance; package eu.mhsl.craftattack.spawn.appliance;
import eu.mhsl.craftattack.spawn.Main; import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.api.client.Repository;
import eu.mhsl.craftattack.spawn.api.server.HttpServer; import eu.mhsl.craftattack.spawn.api.server.HttpServer;
import eu.mhsl.craftattack.spawn.config.Configuration; import eu.mhsl.craftattack.spawn.config.Configuration;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -94,10 +95,14 @@ public abstract class Appliance {
listeners.forEach(HandlerList::unregisterAll); listeners.forEach(HandlerList::unregisterAll);
} }
protected static <T extends Appliance> T queryAppliance(Class<T> clazz) { protected <T extends Appliance> T queryAppliance(Class<T> clazz) {
return Main.instance().getAppliance(clazz); return Main.instance().getAppliance(clazz);
} }
protected <T extends Repository> T queryRepository(Class<T> clazz) {
return Main.instance().getRepositoryLoader().getRepository(clazz);
}
private void setCommandExecutor(JavaPlugin plugin, String name, ApplianceCommand<?> executor) { private void setCommandExecutor(JavaPlugin plugin, String name, ApplianceCommand<?> executor) {
PluginCommand command = plugin.getCommand(name); PluginCommand command = plugin.getCommand(name);
if(command != null && executor != null) { if(command != null && executor != null) {

View File

@ -1,5 +1,6 @@
package eu.mhsl.craftattack.spawn.appliances.settings; package eu.mhsl.craftattack.spawn.appliances.settings;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.appliance.Appliance; import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand; import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.Setting; import eu.mhsl.craftattack.spawn.appliances.settings.datatypes.Setting;
@ -36,7 +37,7 @@ public class Settings extends Appliance {
public static Settings instance() { public static Settings instance() {
if(settingsInstance != null) return settingsInstance; if(settingsInstance != null) return settingsInstance;
Settings.settingsInstance = queryAppliance(Settings.class); Settings.settingsInstance = Main.instance().getAppliance(Settings.class);
return settingsInstance; return settingsInstance;
} }

View File

@ -1,82 +1,23 @@
package eu.mhsl.craftattack.spawn.util.api; package eu.mhsl.craftattack.spawn.util.api;
import com.google.gson.Gson;
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
import eu.mhsl.craftattack.spawn.config.Configuration; import eu.mhsl.craftattack.spawn.config.Configuration;
import eu.mhsl.craftattack.spawn.util.text.DisconnectInfo;
import org.apache.http.client.utils.URIBuilder;
import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Objects; import java.util.Objects;
public class ApiUtil { public class ApiUtil {
private static URI whitelistEndpoint; public final static String basePath = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api"))
private static URI reportEndpoint; .getString("baseurl");
private static String baseUrl;
private static String apiSecret;
public static String getApiSecret() { public final static String apiSecret = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api"))
if(apiSecret == null) { .getString("secret");
apiSecret = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api")).getString("secret");
}
return apiSecret;
}
public static String getBaseUrl() { public static URI getBaseUri() {
if(baseUrl == null) { Objects.requireNonNull(basePath);
baseUrl = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api")).getString("baseurl"); try {
} return new URI(basePath);
return baseUrl; } catch(URISyntaxException e) {
}
public static URI getWhitelistEndpoint() {
if(whitelistEndpoint == null) {
String configValue = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api")).getString("whitelist");
whitelistEndpoint = URI.create(getBaseUrl() + Objects.requireNonNull(configValue));
}
return whitelistEndpoint;
}
public static URI getReportEndpoint() {
if(reportEndpoint == null) {
String configValue = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api")).getString("report");
reportEndpoint = URI.create(getBaseUrl() + Objects.requireNonNull(configValue));
}
return reportEndpoint;
}
public static HttpResponse<String> getHttpResponse(URI endpoint, ) {
URIBuilder uriBuilder = new URIBuilder(endpoint);
uriBuilder.addParameter("secret", apiSecret);
uriBuilder.addParameter("uuid", uuid.toString());
try(HttpClient client = HttpClient.newHttpClient()) {
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(uriBuilder.build())
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if(httpResponse.statusCode() == 404)
throw new DisconnectInfo.Throwable(
"Nicht angemeldet",
"Du bist derzeit nicht als Teilnehmer des CraftAttack-Projektes registriert!",
"Melde Dich bei einem Admin für eine nachträgliche Anmeldung.",
uuid
);
return new Gson().fromJson(httpResponse.body(), Whitelist.UserData.class);
} catch(IOException | InterruptedException | URISyntaxException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }