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

View File

@ -1,7 +1,8 @@
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.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.net.URI;
@ -12,40 +13,49 @@ import java.net.http.HttpResponse;
import java.util.function.Consumer;
public class HttpRepository extends Repository {
Consumer<URIBuilder> baseUriBuilder;
public HttpRepository(URI basePath, Consumer<URIBuilder> baseUriBuilder) {
private final Consumer<URIBuilder> baseUriBuilder;
public HttpRepository(URI basePath) {
this(basePath, null);
}
public HttpRepository(URI basePath, @Nullable Consumer<URIBuilder> baseUriBuilder) {
super(basePath);
this.baseUriBuilder = baseUriBuilder;
this.baseUriBuilder = baseUriBuilder == null
? uriBuilder -> {}
: baseUriBuilder;
}
public record RequestResponse<TData>(int status, TData data) {
}
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) {
HttpRequest request = this.getRequestBuilder(this.getUri(command))
.POST(HttpRequest.BodyPublishers.ofString(new Gson().toJson(data)))
HttpRequest request = this.getRequestBuilder(this.getUri(command, parameters))
.POST(HttpRequest.BodyPublishers.ofString(this.gson.toJson(data)))
.build();
RequestResponse<String> rawResponse = this.runRequest(request);
return new RequestResponse<>(rawResponse.status, new Gson().fromJson(rawResponse.data, clazz));
return this.execute(request, 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()
.build();
RequestResponse<String> rawResponse = this.runRequest(request);
return new RequestResponse<>(rawResponse.status, new Gson().fromJson(rawResponse.data, clazz));
return this.execute(request, clazz);
}
private URI getUri(String command) {
private URI getUri(String command, Consumer<URIBuilder> parameters) {
try {
URIBuilder builder = new URIBuilder(this.basePath + "/" + command);
this.baseUriBuilder.accept(builder);
parameters.accept(builder);
return builder.build();
} catch (URISyntaxException e) {
throw new RuntimeException(e);
@ -55,16 +65,22 @@ public class HttpRepository extends Repository {
private HttpRequest.Builder getRequestBuilder(URI endpoint) {
return HttpRequest.newBuilder()
.uri(endpoint)
.header("User-Agent", Main.instance().getServer().getBukkitVersion())
.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()) {
HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return new RequestResponse<>(httpResponse.statusCode(), httpResponse.body());
} catch(IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,11 +1,15 @@
package eu.mhsl.craftattack.spawn.api.client;
import com.google.gson.Gson;
import java.net.URI;
public class Repository {
protected URI basePath;
protected Gson gson;
public Repository(URI 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;
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;
public class ReportRepository extends HttpRepository {
public ReportRepository() throws URISyntaxException {
super(new URI("asdasdas"));
public ReportRepository() {
super(ApiUtil.getBaseUri());
}
public record SendReportResponse(UUID user) {}

View File

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

View File

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

View File

@ -1,82 +1,23 @@
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.util.text.DisconnectInfo;
import org.apache.http.client.utils.URIBuilder;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Objects;
public class ApiUtil {
private static URI whitelistEndpoint;
private static URI reportEndpoint;
private static String baseUrl;
private static String apiSecret;
public final static String basePath = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api"))
.getString("baseurl");
public static String getApiSecret() {
if(apiSecret == null) {
apiSecret = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api")).getString("secret");
}
return apiSecret;
}
public final static String apiSecret = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api"))
.getString("secret");
public static String getBaseUrl() {
if(baseUrl == null) {
baseUrl = Objects.requireNonNull(Configuration.cfg.getConfigurationSection("api")).getString("baseurl");
}
return baseUrl;
}
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) {
public static URI getBaseUri() {
Objects.requireNonNull(basePath);
try {
return new URI(basePath);
} catch(URISyntaxException e) {
throw new RuntimeException(e);
}
}