diff --git a/Assembly/dependency-reduced-pom.xml b/Assembly/dependency-reduced-pom.xml
index 9df70cc..2e4a037 100644
--- a/Assembly/dependency-reduced-pom.xml
+++ b/Assembly/dependency-reduced-pom.xml
@@ -18,31 +18,6 @@
shade
-
- false
-
-
- org.yaml.snakeyaml
- dev.brighten.antivpn.utils.shaded.org.yaml.snakeyaml
-
-
- com.mongodb
- dev.brighten.antivpn.utils.shaded.com.mongodb
-
-
- org.bson
- dev.brighten.antivpn.utils.shaded.org.bson
-
-
- com.mysql
- dev.brighten.antivpn.utils.shaded.com.mysql
-
-
- com.moandjiezana
- dev.brighten.antivpn.utils.shaded.com.moandjiezana
-
-
-
diff --git a/Assembly/pom.xml b/Assembly/pom.xml
index b0d98ee..6d7684b 100644
--- a/Assembly/pom.xml
+++ b/Assembly/pom.xml
@@ -28,31 +28,6 @@
shade
-
- false
-
-
- org.yaml.snakeyaml
- dev.brighten.antivpn.utils.shaded.org.yaml.snakeyaml
-
-
- com.mongodb
- dev.brighten.antivpn.utils.shaded.com.mongodb
-
-
- org.bson
- dev.brighten.antivpn.utils.shaded.org.bson
-
-
- com.mysql
- dev.brighten.antivpn.utils.shaded.com.mysql
-
-
- com.moandjiezana
- dev.brighten.antivpn.utils.shaded.com.moandjiezana
-
-
-
diff --git a/Bukkit/dependency-reduced-pom.xml b/Bukkit/dependency-reduced-pom.xml
index 691d87f..469a270 100644
--- a/Bukkit/dependency-reduced-pom.xml
+++ b/Bukkit/dependency-reduced-pom.xml
@@ -58,28 +58,6 @@
Common1.8.2provided
-
-
- toml4j
- com.moandjiezana.toml
-
-
- mysql-connector-java
- mysql
-
-
- h2
- com.h2database
-
-
- snakeyaml
- org.yaml
-
-
- mongo-java-driver
- org.mongodb
-
- cc.funkemunky.utils
diff --git a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java b/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java
index 8a5c550..9af38c2 100644
--- a/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java
+++ b/Bukkit/src/main/java/dev/brighten/antivpn/bukkit/BukkitPlugin.java
@@ -3,7 +3,6 @@ package dev.brighten.antivpn.bukkit;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.bukkit.command.BukkitCommand;
import dev.brighten.antivpn.command.Command;
-import dev.brighten.antivpn.utils.ConfigDefault;
import org.bstats.bukkit.Metrics;
import org.bstats.charts.SingleLineChart;
import org.bukkit.Bukkit;
diff --git a/Bungee/dependency-reduced-pom.xml b/Bungee/dependency-reduced-pom.xml
index 3da508d..d0084f0 100644
--- a/Bungee/dependency-reduced-pom.xml
+++ b/Bungee/dependency-reduced-pom.xml
@@ -52,28 +52,6 @@
Common1.8.2provided
-
-
- toml4j
- com.moandjiezana.toml
-
-
- mysql-connector-java
- mysql
-
-
- h2
- com.h2database
-
-
- snakeyaml
- org.yaml
-
-
- mongo-java-driver
- org.mongodb
-
- org.github.bungee
diff --git a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java
index 160aa20..bb54d83 100644
--- a/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java
+++ b/Bungee/src/main/java/dev/brighten/antivpn/bungee/BungeePlugin.java
@@ -3,8 +3,6 @@ package dev.brighten.antivpn.bungee;
import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.bungee.command.BungeeCommand;
import dev.brighten.antivpn.command.Command;
-import dev.brighten.antivpn.command.impl.AntiVPNCommand;
-import dev.brighten.antivpn.utils.ConfigDefault;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.plugin.Plugin;
import org.bstats.bungeecord.Metrics;
diff --git a/Common/pom.xml b/Common/pom.xml
index fb51510..9548534 100644
--- a/Common/pom.xml
+++ b/Common/pom.xml
@@ -45,36 +45,30 @@
-
- com.moandjiezana.toml
- toml4j
- 0.7.2
- compile
- mysqlmysql-connector-java
- 8.0.28
+ 8.0.30jar
- compile
+ providedcom.h2databaseh2
- 2.1.210
- compile
+ 2.1.214
+ providedorg.yamlsnakeyaml1.30
- compile
+ providedorg.mongodbmongo-java-driver
- 3.12.10
- compile
+ 3.12.11
+ provided
diff --git a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java b/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java
index 4fca9aa..179eb07 100644
--- a/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java
+++ b/Common/src/main/java/dev/brighten/antivpn/AntiVPN.java
@@ -9,6 +9,8 @@ import dev.brighten.antivpn.database.VPNDatabase;
import dev.brighten.antivpn.database.local.H2VPN;
import dev.brighten.antivpn.database.mongo.MongoVPN;
import dev.brighten.antivpn.database.sql.MySqlVPN;
+import dev.brighten.antivpn.depends.LibraryLoader;
+import dev.brighten.antivpn.depends.MavenLibrary;
import dev.brighten.antivpn.message.MessageHandler;
import dev.brighten.antivpn.utils.ConfigDefault;
import dev.brighten.antivpn.utils.MiscUtils;
@@ -29,6 +31,10 @@ import java.util.List;
@Getter
@Setter(AccessLevel.PRIVATE)
+@MavenLibrary(groupId = "com.h2database", artifactId ="h2", version = "2.1.214")
+@MavenLibrary(groupId = "org.yaml", artifactId = "snakeyaml", version = "1.30")
+@MavenLibrary(groupId = "org.mongodb", artifactId = "mongo-java-driver", version = "3.12.11")
+@MavenLibrary(groupId = "mysql", artifactId = "mysql-connector-java", version = "8.0.30")
public class AntiVPN {
private static AntiVPN INSTANCE;
@@ -50,6 +56,9 @@ public class AntiVPN {
INSTANCE.pluginFolder = pluginFolder;
INSTANCE.executor = executor;
INSTANCE.playerExecutor = playerExecutor;
+
+ LibraryLoader.loadAll(INSTANCE);
+
try {
File configFile = new File(pluginFolder, "config.yml");
if(!configFile.exists()){
@@ -142,6 +151,40 @@ public class AntiVPN {
if(database != null) database.shutdown();
}
+ public void reloadDatabase() {
+ database.shutdown();
+
+ switch(AntiVPN.getInstance().getVpnConfig().getDatabaseType().toLowerCase()) {
+ case "h2":
+ case "local":
+ case "flatfile": {
+ AntiVPN.getInstance().getExecutor().log("Using databaseType H2...");
+ INSTANCE.database = new H2VPN();
+ INSTANCE.database.init();
+ break;
+ }
+ case "mysql":
+ case "sql":{
+ AntiVPN.getInstance().getExecutor().log("Using databaseType MySQL...");
+ INSTANCE.database = new MySqlVPN();
+ INSTANCE.database.init();
+ break;
+ }
+ case "mongo":
+ case "mongodb":
+ case "mongod": {
+ INSTANCE.database = new MongoVPN();
+ INSTANCE.database.init();
+ break;
+ }
+ default: {
+ AntiVPN.getInstance().getExecutor().log("Could not find database type \"" + INSTANCE.vpnConfig.getDatabaseType() + "\". " +
+ "Options: [MySQL]");
+ break;
+ }
+ }
+ }
+
public static AntiVPN getInstance() {
assert INSTANCE != null: "AntiVPN has not been initialized!";
diff --git a/Common/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java b/Common/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java
index ab5a463..dd007b4 100644
--- a/Common/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java
+++ b/Common/src/main/java/dev/brighten/antivpn/command/impl/ReloadCommand.java
@@ -4,6 +4,9 @@ import dev.brighten.antivpn.AntiVPN;
import dev.brighten.antivpn.api.VPNExecutor;
import dev.brighten.antivpn.command.Command;
import dev.brighten.antivpn.command.CommandExecutor;
+import dev.brighten.antivpn.database.local.H2VPN;
+import dev.brighten.antivpn.database.mongo.MongoVPN;
+import dev.brighten.antivpn.database.sql.MySqlVPN;
import dev.brighten.antivpn.message.VpnString;
import java.util.Collections;
@@ -58,6 +61,8 @@ public class ReloadCommand extends Command {
// Clearing the local response cache
VPNExecutor.responseCache.clear();
+ AntiVPN.getInstance().reloadDatabase();
+
return AntiVPN.getInstance().getMessageHandler().getString("command-reload-complete").getMessage();
}
diff --git a/Common/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java b/Common/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java
index 54b3058..94466a0 100644
--- a/Common/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java
+++ b/Common/src/main/java/dev/brighten/antivpn/database/local/H2VPN.java
@@ -258,11 +258,11 @@ public class H2VPN implements VPNDatabase {
AntiVPN.getInstance().getExecutor().log("Creating indexes...");
try {
- Query.prepare("create index `uuid_1` if not exists on `whitelisted` (`uuid`)").execute();
- Query.prepare("create index `ip_1` if not exists on `responses` (`ip`)").execute();
- Query.prepare("create index `proxy_1` if not exists on `responses` (`proxy`)").execute();
- Query.prepare("create index `inserted_1` if not exists on `responses` (`inserted`)").execute();
- Query.prepare("create index `ip_1` if not exists on `whitelisted-ips` (`ip`)").execute();
+ Query.prepare("create index if not exists `uuid_1` on `whitelisted` (`uuid`)").execute();
+ Query.prepare("create index if not exists `ip_1` on `responses` (`ip`)").execute();
+ Query.prepare("create index if not exists `proxy_1` on `responses` (`proxy`)").execute();
+ Query.prepare("create index if not exists `inserted_1` on `responses` (`inserted`)").execute();
+ Query.prepare("create index if not exists `ip_1` on `whitelisted-ips` (`ip`)").execute();
} catch (Exception e) {
System.err.println("MySQL Excepton created" + e.getMessage());
}
diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java b/Common/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java
new file mode 100644
index 0000000..23c92e4
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/depends/LibraryLoader.java
@@ -0,0 +1,200 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.antivpn.depends;
+
+import dev.brighten.antivpn.AntiVPN;
+import dev.brighten.antivpn.utils.NonnullByDefault;
+import dev.brighten.antivpn.utils.Supplier;
+import dev.brighten.antivpn.utils.Suppliers;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.Objects;
+
+/**
+ * Resolves {@link MavenLibrary} annotations for a class, and loads the dependency
+ * into the classloader.
+ */
+@NonnullByDefault
+public final class LibraryLoader {
+
+ @SuppressWarnings("Guava")
+ private static final Supplier URL_INJECTOR = Suppliers.memoize(() -> URLClassLoaderAccess.create((URLClassLoader) AntiVPN.getInstance().getClass().getClassLoader()));
+
+ /**
+ * Resolves all {@link MavenLibrary} annotations on the given object.
+ *
+ * @param object the object to load libraries for.
+ */
+ public static void loadAll(Object object) {
+ loadAll(object.getClass());
+ }
+
+ /**
+ * Resolves all {@link MavenLibrary} annotations on the given class.
+ *
+ * @param clazz the class to load libraries for.
+ */
+ public static void loadAll(Class> clazz) {
+ MavenLibrary[] libs = clazz.getDeclaredAnnotationsByType(MavenLibrary.class);
+ if (libs == null) {
+ return;
+ }
+
+ for (MavenLibrary lib : libs) {
+ load(lib.groupId(), lib.artifactId(), lib.version(), lib.repo().url());
+ }
+ }
+
+ public static void load(String groupId, String artifactId, String version) {
+ load(groupId, artifactId, version, "https://repo1.maven.org/maven2");
+ }
+
+ public static void load(String groupId, String artifactId, String version, String repoUrl) {
+ load(new Dependency(groupId, artifactId, version, repoUrl));
+ }
+
+ public static void load(Dependency d) {
+ AntiVPN.getInstance().getExecutor().log(String.format("Loading dependency %s:%s:%s from %s", d.getGroupId(), d.getArtifactId(), d.getVersion(), d.getRepoUrl()));
+ String name = d.getArtifactId() + "-" + d.getVersion();
+
+ File saveLocation = new File(getLibFolder(), name + ".jar");
+ if (!saveLocation.exists()) {
+
+ try {
+ AntiVPN.getInstance().getExecutor().log("Dependency '" + name + "' is not already in the libraries folder. Attempting to download...");
+ URL url = d.getUrl();
+
+ try (InputStream is = url.openStream()) {
+ Files.copy(is, saveLocation.toPath());
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ AntiVPN.getInstance().getExecutor().log("Dependency '" + name + "' successfully downloaded.");
+ }
+
+ if (!saveLocation.exists()) {
+ throw new RuntimeException("Unable to download dependency: " + d.toString());
+ }
+
+ try {
+ URL_INJECTOR.get().addURL(saveLocation.toURI().toURL());
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to load dependency: " + saveLocation.toString(), e);
+ }
+
+ AntiVPN.getInstance().getExecutor().log("Loaded dependency '" + name + "' successfully.");
+ }
+
+ private static File getLibFolder() {
+ File pluginDataFolder = AntiVPN.getInstance().getPluginFolder();
+ File libs = new File(pluginDataFolder, "libraries");
+ libs.mkdirs();
+ return libs;
+ }
+
+ @NonnullByDefault
+ public static final class Dependency {
+ private final String groupId;
+ private final String artifactId;
+ private final String version;
+ private final String repoUrl;
+
+ public Dependency(String groupId, String artifactId, String version, String repoUrl) {
+ this.groupId = Objects.requireNonNull(groupId, "groupId");
+ this.artifactId = Objects.requireNonNull(artifactId, "artifactId");
+ this.version = Objects.requireNonNull(version, "version");
+ this.repoUrl = Objects.requireNonNull(repoUrl, "repoUrl");
+ }
+
+ public String getGroupId() {
+ return this.groupId;
+ }
+
+ public String getArtifactId() {
+ return this.artifactId;
+ }
+
+ public String getVersion() {
+ return this.version;
+ }
+
+ public String getRepoUrl() {
+ return this.repoUrl;
+ }
+
+ public URL getUrl() throws MalformedURLException {
+ String repo = this.repoUrl;
+ if (!repo.endsWith("/")) {
+ repo += "/";
+ }
+ repo += "%s/%s/%s/%s-%s.jar";
+
+ String url = String.format(repo, this.groupId.replace(".", "/"), this.artifactId, this.version, this.artifactId, this.version);
+ return new URL(url);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof Dependency)) return false;
+ final Dependency other = (Dependency) o;
+ return this.getGroupId().equals(other.getGroupId()) &&
+ this.getArtifactId().equals(other.getArtifactId()) &&
+ this.getVersion().equals(other.getVersion()) &&
+ this.getRepoUrl().equals(other.getRepoUrl());
+ }
+
+ @Override
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.getGroupId().hashCode();
+ result = result * PRIME + this.getArtifactId().hashCode();
+ result = result * PRIME + this.getVersion().hashCode();
+ result = result * PRIME + this.getRepoUrl().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "LibraryLoader.Dependency(" +
+ "groupId=" + this.getGroupId() + ", " +
+ "artifactId=" + this.getArtifactId() + ", " +
+ "version=" + this.getVersion() + ", " +
+ "repoUrl=" + this.getRepoUrl() + ")";
+ }
+ }
+
+
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java b/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java
new file mode 100644
index 0000000..189f737
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibraries.java
@@ -0,0 +1,40 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.antivpn.depends;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation to indicate the required libraries for a class.
+ */
+@Documented
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MavenLibraries {
+
+ MavenLibrary[] value() default {};
+
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java b/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java
new file mode 100644
index 0000000..4dad047
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/depends/MavenLibrary.java
@@ -0,0 +1,67 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.antivpn.depends;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation to indicate a required library for a class.
+ */
+@Documented
+@Repeatable(MavenLibraries.class)
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MavenLibrary {
+
+ /**
+ * The group id of the library
+ *
+ * @return the group id of the library
+ */
+ String groupId();
+
+ /**
+ * The artifact id of the library
+ *
+ * @return the artifact id of the library
+ */
+ String artifactId();
+
+ /**
+ * The version of the library
+ *
+ * @return the version of the library
+ */
+ String version();
+
+ /**
+ * The repo where the library can be obtained from
+ *
+ * @return the repo where the library can be obtained from
+ */
+ Repository repo() default @Repository(url = "https://repo1.maven.org/maven2");
+
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/Repository.java b/Common/src/main/java/dev/brighten/antivpn/depends/Repository.java
new file mode 100644
index 0000000..4381225
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/depends/Repository.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.antivpn.depends;
+
+import java.lang.annotation.*;
+
+/**
+ * Represents a maven repository.
+ */
+@Documented
+@Target(ElementType.LOCAL_VARIABLE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Repository {
+
+ /**
+ * Gets the base url of the repository.
+ *
+ * @return the base url of the repository
+ */
+ String url();
+
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java b/Common/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java
new file mode 100644
index 0000000..54c1100
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/depends/URLClassLoaderAccess.java
@@ -0,0 +1,175 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.antivpn.depends;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collection;
+
+/**
+ * Provides access to {@link URLClassLoader}#addURL.
+ */
+public abstract class URLClassLoaderAccess {
+
+ /**
+ * Creates a {@link URLClassLoaderAccess} for the given class loader.
+ *
+ * @param classLoader the class loader
+ * @return the access object
+ */
+ static URLClassLoaderAccess create(URLClassLoader classLoader) {
+ if (Reflection.isSupported()) {
+ return new Reflection(classLoader);
+ } else if (Unsafe.isSupported()) {
+ return new Unsafe(classLoader);
+ } else {
+ return Noop.INSTANCE;
+ }
+ }
+
+ private final URLClassLoader classLoader;
+
+ protected URLClassLoaderAccess(URLClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+
+ /**
+ * Adds the given URL to the class loader.
+ *
+ * @param url the URL to add
+ */
+ public abstract void addURL(URL url);
+
+ /**
+ * Accesses using reflection, not supported on Java 9+.
+ */
+ private static class Reflection extends URLClassLoaderAccess {
+ private static final Method ADD_URL_METHOD;
+
+ static {
+ Method addUrlMethod;
+ try {
+ addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+ addUrlMethod.setAccessible(true);
+ } catch (Exception e) {
+ addUrlMethod = null;
+ }
+ ADD_URL_METHOD = addUrlMethod;
+ }
+
+ private static boolean isSupported() {
+ return ADD_URL_METHOD != null;
+ }
+
+ Reflection(URLClassLoader classLoader) {
+ super(classLoader);
+ }
+
+ @Override
+ public void addURL(URL url) {
+ try {
+ ADD_URL_METHOD.invoke(super.classLoader, url);
+ } catch (ReflectiveOperationException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Accesses using sun.misc.Unsafe, supported on Java 9+.
+ *
+ * @author Vaishnav Anil (https://github.com/slimjar/slimjar)
+ */
+ private static class Unsafe extends URLClassLoaderAccess {
+ private static final sun.misc.Unsafe UNSAFE;
+
+ static {
+ sun.misc.Unsafe unsafe;
+ try {
+ Field unsafeField = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ unsafe = (sun.misc.Unsafe) unsafeField.get(null);
+ } catch (Throwable t) {
+ unsafe = null;
+ }
+ UNSAFE = unsafe;
+ }
+
+ private static boolean isSupported() {
+ return UNSAFE != null;
+ }
+
+ private final Collection unopenedURLs;
+ private final Collection pathURLs;
+
+ @SuppressWarnings("unchecked")
+ Unsafe(URLClassLoader classLoader) {
+ super(classLoader);
+
+ Collection unopenedURLs;
+ Collection pathURLs;
+ try {
+ Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp");
+ unopenedURLs = (Collection) fetchField(ucp.getClass(), ucp, "unopenedUrls");
+ pathURLs = (Collection) fetchField(ucp.getClass(), ucp, "path");
+ } catch (Throwable e) {
+ unopenedURLs = null;
+ pathURLs = null;
+ }
+ this.unopenedURLs = unopenedURLs;
+ this.pathURLs = pathURLs;
+ }
+
+ private static Object fetchField(final Class> clazz, final Object object, final String name) throws NoSuchFieldException {
+ Field field = clazz.getDeclaredField(name);
+ long offset = UNSAFE.objectFieldOffset(field);
+ return UNSAFE.getObject(object, offset);
+ }
+
+ @Override
+ public void addURL(URL url) {
+ this.unopenedURLs.add(url);
+ this.pathURLs.add(url);
+ }
+ }
+
+ private static class Noop extends URLClassLoaderAccess {
+ private static final Noop INSTANCE = new Noop();
+
+ private Noop() {
+ super(null);
+ }
+
+ @Override
+ public void addURL(URL url) {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java b/Common/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java
new file mode 100644
index 0000000..484f35e
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/ExtraObjectsMethodsForWeb.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package dev.brighten.antivpn.utils;
+
+/**
+ * Holder for extra methods of {@code Objects} only in web. Intended to be empty for regular
+ * version.
+ */
+abstract class ExtraObjectsMethodsForWeb {}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java b/Common/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java
new file mode 100644
index 0000000..48a1f73
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/NonnullByDefault.java
@@ -0,0 +1,36 @@
+/*
+ * This file is part of helper, licensed under the MIT License.
+ *
+ * Copyright (c) lucko (Luck)
+ * Copyright (c) contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package dev.brighten.antivpn.utils;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NonnullByDefault {
+
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java b/Common/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java
new file mode 100644
index 0000000..e9a33c8
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/NullnessCasts.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package dev.brighten.antivpn.utils;
+
+/** A utility method to perform unchecked casts to suppress errors produced by nullness analyses. */
+final class NullnessCasts {
+ /**
+ * Accepts a {@code @Nullable T} and returns a plain {@code T}, without performing any check that
+ * that conversion is safe.
+ *
+ *
This method is intended to help with usages of type parameters that have {
+ * ParametricNullness parametric nullness}. If a type parameter instead ranges over only non-null
+ * types (or if the type is a non-variable type, like {@code String}), then code should almost
+ * never use this method, preferring instead to call {@code requireNonNull} so as to benefit from
+ * its runtime check.
+ *
+ *
An example use case for this method is in implementing an {@code Iterator} whose {@code
+ * next} field is lazily initialized. The type of that field would be {@code @Nullable T}, and the
+ * code would be responsible for populating a "real" {@code T} (which might still be the value
+ * {@code null}!) before returning it to callers. Depending on how the code is structured, a
+ * nullness analysis might not understand that the field has been populated. To avoid that problem
+ * without having to add {@code @SuppressWarnings}, the code can call this method.
+ *
+ *
Why not just add {@code SuppressWarnings}? The problem is that this method is
+ * typically useful for {@code return} statements. That leaves the code with two options: Either
+ * add the suppression to the whole method (which turns off checking for a large section of code),
+ * or extract a variable, and put the suppression on that. However, a local variable typically
+ * doesn't work: Because nullness analyses typically infer the nullness of local variables,
+ * there's no way to assign a {@code @Nullable T} to a field {@code T foo;} and instruct the
+ * analysis that that means "plain {@code T}" rather than the inferred type {@code @Nullable T}.
+ * (Even if supported added {@code @NonNull}, that would not help, since the problem case
+ * addressed by this method is the case in which {@code T} has parametric nullness -- and thus its
+ * value may be legitimately {@code null}.)
+ */
+ @SuppressWarnings("nullness")
+ static T uncheckedCastNullableTToT(T t) {
+ return t;
+ }
+
+ private NullnessCasts() {}
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Objects.java b/Common/src/main/java/dev/brighten/antivpn/utils/Objects.java
new file mode 100644
index 0000000..3246091
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/Objects.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package dev.brighten.antivpn.utils;
+
+import com.mongodb.lang.Nullable;
+
+import java.util.Arrays;
+
+/**
+ * Helper functions that can operate on any {@code Object}.
+ *
+ *
See the Guava User Guide on writing {@code Object}
+ * methods with {@code Objects}.
+ *
+ * @author Laurence Gonsalves
+ * @since 2.0
+ */
+public final class Objects extends ExtraObjectsMethodsForWeb {
+ private Objects() {}
+
+ /**
+ * Determines whether two possibly-null objects are equal. Returns:
+ *
+ *
+ *
{@code true} if {@code a} and {@code b} are both null.
+ *
{@code true} if {@code a} and {@code b} are both non-null and they are equal according to
+ * {@link Object#equals(Object)}.
+ *
{@code false} in all other situations.
+ *
+ *
+ *
This assumes that any non-null objects passed to this function conform to the {@code
+ * equals()} contract.
+ *
+ *
Note for Java 7 and later: This method should be treated as deprecated; use {@link
+ * java.util.Objects#equals} instead.
+ */
+ public static boolean equal(Object a, Object b) {
+ return a == b || (a != null && a.equals(b));
+ }
+
+ /**
+ * Generates a hash code for multiple values. The hash code is generated by calling {@link
+ * Arrays#hashCode(Object[])}. Note that array arguments to this method, with the exception of a
+ * single Object array, do not get any special handling; their hash codes are based on identity
+ * and not contents.
+ *
+ *
This is useful for implementing {@link Object#hashCode()}. For example, in an object that
+ * has three properties, {@code x}, {@code y}, and {@code z}, one could write:
+ *
+ *
{@code
+ * public int hashCode() {
+ * return Objects.hashCode(getX(), getY(), getZ());
+ * }
+ * }
+ *
+ *
Warning: When a single object is supplied, the returned hash code does not equal the
+ * hash code of that object.
+ *
+ *
Note for Java 7 and later: This method should be treated as deprecated; use {@link
+ * java.util.Objects#hash} instead.
+ */
+ public static int hashCode(@Nullable Object... objects) {
+ return Arrays.hashCode(objects);
+ }
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Preconditions.java b/Common/src/main/java/dev/brighten/antivpn/utils/Preconditions.java
new file mode 100644
index 0000000..175cab0
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/Preconditions.java
@@ -0,0 +1,602 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package dev.brighten.antivpn.utils;
+
+public final class Preconditions {
+ private Preconditions() {
+ }
+
+ public static void checkArgument(boolean expression) {
+ if (!expression) {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public static void checkArgument(boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new IllegalArgumentException(String.valueOf(errorMessage));
+ }
+ }
+
+ public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, char p1) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, int p1) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, long p1) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, char p1, char p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, char p1, int p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, char p1, long p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, char p1, Object p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, int p1, char p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, int p1, int p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, int p1, long p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, int p1, Object p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, long p1, char p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, long p1, int p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, long p1, long p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, long p1, Object p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, char p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, int p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, long p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, Object p2) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2, p3));
+ }
+ }
+
+ public static void checkArgument(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3, Object p4) {
+ if (!b) {
+ throw new IllegalArgumentException(format(errorMessageTemplate, p1, p2, p3, p4));
+ }
+ }
+
+ public static void checkState(boolean expression) {
+ if (!expression) {
+ throw new IllegalStateException();
+ }
+ }
+
+ public static void checkState(boolean expression, Object errorMessage) {
+ if (!expression) {
+ throw new IllegalStateException(String.valueOf(errorMessage));
+ }
+ }
+
+ public static void checkState(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
+ if (!expression) {
+ throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, char p1) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, int p1) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, long p1) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, char p1, char p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, char p1, int p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, char p1, long p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, char p1, Object p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, int p1, char p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, int p1, int p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, int p1, long p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, int p1, Object p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, long p1, char p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, long p1, int p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, long p1, long p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, long p1, Object p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1, char p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1, int p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1, long p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1, Object p2) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2, p3));
+ }
+ }
+
+ public static void checkState(boolean b, String errorMessageTemplate, Object p1, Object p2, Object p3, Object p4) {
+ if (!b) {
+ throw new IllegalStateException(format(errorMessageTemplate, p1, p2, p3, p4));
+ }
+ }
+
+ public static T checkNotNull(T reference) {
+ if (reference == null) {
+ throw new NullPointerException();
+ } else {
+ return reference;
+ }
+ }
+
+ public static T checkNotNull(T reference, Object errorMessage) {
+ if (reference == null) {
+ throw new NullPointerException(String.valueOf(errorMessage));
+ } else {
+ return reference;
+ }
+ }
+
+ public static T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs) {
+ if (reference == null) {
+ throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
+ } else {
+ return reference;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, char p1) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, int p1) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, long p1) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, char p1, char p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, char p1, int p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, char p1, long p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, char p1, Object p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, int p1, char p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, int p1, int p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, int p1, long p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, int p1, Object p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, long p1, char p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, long p1, int p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, long p1, long p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, long p1, Object p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1, char p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1, int p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1, long p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1, Object p2) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1, Object p2, Object p3) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2, p3));
+ } else {
+ return obj;
+ }
+ }
+
+ public static T checkNotNull(T obj, String errorMessageTemplate, Object p1, Object p2, Object p3, Object p4) {
+ if (obj == null) {
+ throw new NullPointerException(format(errorMessageTemplate, p1, p2, p3, p4));
+ } else {
+ return obj;
+ }
+ }
+
+ public static int checkElementIndex(int index, int size) {
+ return checkElementIndex(index, size, "index");
+ }
+
+ public static int checkElementIndex(int index, int size, String desc) {
+ if (index >= 0 && index < size) {
+ return index;
+ } else {
+ throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
+ }
+ }
+
+ private static String badElementIndex(int index, int size, String desc) {
+ if (index < 0) {
+ return format("%s (%s) must not be negative", desc, index);
+ } else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ } else {
+ return format("%s (%s) must be less than size (%s)", desc, index, size);
+ }
+ }
+
+ public static int checkPositionIndex(int index, int size) {
+ return checkPositionIndex(index, size, "index");
+ }
+
+ public static int checkPositionIndex(int index, int size, String desc) {
+ if (index >= 0 && index <= size) {
+ return index;
+ } else {
+ throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
+ }
+ }
+
+ private static String badPositionIndex(int index, int size, String desc) {
+ if (index < 0) {
+ return format("%s (%s) must not be negative", desc, index);
+ } else if (size < 0) {
+ throw new IllegalArgumentException("negative size: " + size);
+ } else {
+ return format("%s (%s) must not be greater than size (%s)", desc, index, size);
+ }
+ }
+
+ public static void checkPositionIndexes(int start, int end, int size) {
+ if (start < 0 || end < start || end > size) {
+ throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
+ }
+ }
+
+ private static String badPositionIndexes(int start, int end, int size) {
+ if (start >= 0 && start <= size) {
+ return end >= 0 && end <= size ? format("end index (%s) must not be less than start index (%s)", end, start) : badPositionIndex(end, size, "end index");
+ } else {
+ return badPositionIndex(start, size, "start index");
+ }
+ }
+
+ static String format(String template, Object... args) {
+ template = String.valueOf(template);
+ StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
+ int templateStart = 0;
+
+ int i;
+ int placeholderStart;
+ for(i = 0; i < args.length; templateStart = placeholderStart + 2) {
+ placeholderStart = template.indexOf("%s", templateStart);
+ if (placeholderStart == -1) {
+ break;
+ }
+
+ builder.append(template, templateStart, placeholderStart);
+ builder.append(args[i++]);
+ }
+
+ builder.append(template, templateStart, template.length());
+ if (i < args.length) {
+ builder.append(" [");
+ builder.append(args[i++]);
+
+ while(i < args.length) {
+ builder.append(", ");
+ builder.append(args[i++]);
+ }
+
+ builder.append(']');
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Supplier.java b/Common/src/main/java/dev/brighten/antivpn/utils/Supplier.java
new file mode 100644
index 0000000..c1f7365
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/Supplier.java
@@ -0,0 +1,11 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package dev.brighten.antivpn.utils;
+
+@FunctionalInterface
+public interface Supplier extends java.util.function.Supplier {
+ T get();
+}
diff --git a/Common/src/main/java/dev/brighten/antivpn/utils/Suppliers.java b/Common/src/main/java/dev/brighten/antivpn/utils/Suppliers.java
new file mode 100644
index 0000000..85d3a0b
--- /dev/null
+++ b/Common/src/main/java/dev/brighten/antivpn/utils/Suppliers.java
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package dev.brighten.antivpn.utils;
+
+import static java.util.Objects.requireNonNull;
+
+import java.io.Serializable;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import static dev.brighten.antivpn.utils.Preconditions.checkArgument;
+import static dev.brighten.antivpn.utils.Preconditions.checkNotNull;
+import static dev.brighten.antivpn.utils.NullnessCasts.uncheckedCastNullableTToT;
+import static java.util.Objects.requireNonNull;
+
+import jdk.tools.jlink.internal.Platform;
+
+/**
+ * Useful suppliers.
+ *
+ *
All methods return serializable suppliers as long as they're given serializable parameters.
+ *
+ * @author Laurence Gonsalves
+ * @author Harry Heymann
+ * @since 2.0
+ */
+public final class Suppliers {
+ private Suppliers() {}
+
+ /**
+ * Returns a new supplier which is the composition of the provided function and supplier. In other
+ * words, the new supplier's value will be computed by retrieving the value from {@code supplier},
+ * and then applying {@code function} to that value. Note that the resulting supplier will not
+ * call {@code supplier} or invoke {@code function} until it is called.
+ */
+ public static Supplier compose(
+ Function super F, T> function, Supplier supplier) {
+ return new SupplierComposition<>(function, supplier);
+ }
+
+ private static class SupplierComposition
+ implements Supplier, Serializable {
+ final Function super F, T> function;
+ final Supplier supplier;
+
+ SupplierComposition(Function super F, T> function, Supplier supplier) {
+ this.function = checkNotNull(function);
+ this.supplier = checkNotNull(supplier);
+ }
+
+ @Override
+ public T get() {
+ return function.apply(supplier.get());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof SupplierComposition) {
+ SupplierComposition, ?> that = (SupplierComposition, ?>) obj;
+ return function.equals(that.function) && supplier.equals(that.supplier);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(function, supplier);
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.compose(" + function + ", " + supplier + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a supplier which caches the instance retrieved during the first call to {@code get()}
+ * and returns that value on subsequent calls to {@code get()}. See: memoization
+ *
+ *
The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at
+ * most once unless the underlying {@code get()} throws an exception. The supplier's serialized
+ * form does not contain the cached value, which will be recalculated when {@code get()} is called
+ * on the reserialized instance.
+ *
+ *
When the underlying delegate throws an exception then this memoizing supplier will keep
+ * delegating calls until it returns valid data.
+ *
+ *
If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
+ * returned directly.
+ */
+ public static Supplier memoize(Supplier delegate) {
+ if (delegate instanceof NonSerializableMemoizingSupplier
+ || delegate instanceof MemoizingSupplier) {
+ return delegate;
+ }
+ return delegate instanceof Serializable
+ ? new MemoizingSupplier(delegate)
+ : new NonSerializableMemoizingSupplier(delegate);
+ }
+
+ static class MemoizingSupplier implements Supplier, Serializable {
+ final Supplier delegate;
+ transient volatile boolean initialized;
+ // "value" does not need to be volatile; visibility piggy-backs
+ // on volatile read of "initialized".
+ transient T value;
+
+ MemoizingSupplier(Supplier delegate) {
+ this.delegate = checkNotNull(delegate);
+ }
+
+ @Override
+ public T get() {
+ // A 2-field variant of Double Checked Locking.
+ if (!initialized) {
+ synchronized (this) {
+ if (!initialized) {
+ T t = delegate.get();
+ value = t;
+ initialized = true;
+ return t;
+ }
+ }
+ }
+ // This is safe because we checked `initialized.`
+ return uncheckedCastNullableTToT(value);
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.memoize("
+ + (initialized ? "" : delegate)
+ + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ static class NonSerializableMemoizingSupplier implements Supplier {
+ volatile Supplier delegate;
+ volatile boolean initialized;
+ // "value" does not need to be volatile; visibility piggy-backs
+ // on volatile read of "initialized".
+ T value;
+
+ NonSerializableMemoizingSupplier(Supplier delegate) {
+ this.delegate = checkNotNull(delegate);
+ }
+
+ @Override
+ public T get() {
+ // A 2-field variant of Double Checked Locking.
+ if (!initialized) {
+ synchronized (this) {
+ if (!initialized) {
+ /*
+ * requireNonNull is safe because we read and write `delegate` under synchronization.
+ *
+ * TODO(cpovirk): To avoid having to check for null, replace `delegate` with a singleton
+ * `Supplier` that always throws an exception.
+ */
+ T t = requireNonNull(delegate).get();
+ value = t;
+ initialized = true;
+ // Release the delegate to GC.
+ delegate = null;
+ return t;
+ }
+ }
+ }
+ // This is safe because we checked `initialized.`
+ return uncheckedCastNullableTToT(value);
+ }
+
+ @Override
+ public String toString() {
+ Supplier delegate = this.delegate;
+ return "Suppliers.memoize("
+ + (delegate == null ? "" : delegate)
+ + ")";
+ }
+ }
+
+ /**
+ * Returns a supplier that caches the instance supplied by the delegate and removes the cached
+ * value after the specified time has passed. Subsequent calls to {@code get()} return the cached
+ * value if the expiration time has not passed. After the expiration time, a new value is
+ * retrieved, cached, and returned. See: memoization
+ *
+ *
The returned supplier is thread-safe. The supplier's serialized form does not contain the
+ * cached value, which will be recalculated when {@code get()} is called on the reserialized
+ * instance. The actual memoization does not happen when the underlying delegate throws an
+ * exception.
+ *
+ *
When the underlying delegate throws an exception then this memoizing supplier will keep
+ * delegating calls until it returns valid data.
+ *
+ * @param duration the length of time after a value is created that it should stop being returned
+ * by subsequent {@code get()} calls
+ * @param unit the unit that {@code duration} is expressed in
+ * @throws IllegalArgumentException if {@code duration} is not positive
+ * @since 2.0
+ */
+ @SuppressWarnings("GoodTime") // should accept a java.time.Duration
+ public static Supplier memoizeWithExpiration(
+ Supplier delegate, long duration, TimeUnit unit) {
+ return new ExpiringMemoizingSupplier<>(delegate, duration, unit);
+ }
+
+ @SuppressWarnings("GoodTime") // lots of violations
+ static class ExpiringMemoizingSupplier
+ implements Supplier, Serializable {
+ final Supplier delegate;
+ final long durationNanos;
+ transient volatile T value;
+ // The special value 0 means "not yet initialized".
+ transient volatile long expirationNanos;
+
+ ExpiringMemoizingSupplier(Supplier delegate, long duration, TimeUnit unit) {
+ this.delegate = checkNotNull(delegate);
+ this.durationNanos = unit.toNanos(duration);
+ checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit);
+ }
+
+ @Override
+ public T get() {
+ // Another variant of Double Checked Locking.
+ //
+ // We use two volatile reads. We could reduce this to one by
+ // putting our fields into a holder class, but (at least on x86)
+ // the extra memory consumption and indirection are more
+ // expensive than the extra volatile reads.
+ long nanos = expirationNanos;
+ long now = System.nanoTime();
+ if (nanos == 0 || now - nanos >= 0) {
+ synchronized (this) {
+ if (nanos == expirationNanos) { // recheck for lost race
+ T t = delegate.get();
+ value = t;
+ nanos = now + durationNanos;
+ // In the very unlikely event that nanos is 0, set it to 1;
+ // no one will notice 1 ns of tardiness.
+ expirationNanos = (nanos == 0) ? 1 : nanos;
+ return t;
+ }
+ }
+ }
+ // This is safe because we checked `expirationNanos.`
+ return uncheckedCastNullableTToT(value);
+ }
+
+ @Override
+ public String toString() {
+ // This is a little strange if the unit the user provided was not NANOS,
+ // but we don't want to store the unit just for toString
+ return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /** Returns a supplier that always supplies {@code instance}. */
+ public static Supplier ofInstance(
+ T instance) {
+ return new SupplierOfInstance<>(instance);
+ }
+
+ private static class SupplierOfInstance
+ implements Supplier, Serializable {
+ final T instance;
+
+ SupplierOfInstance(T instance) {
+ this.instance = instance;
+ }
+
+ @Override
+ public T get() {
+ return instance;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof SupplierOfInstance) {
+ SupplierOfInstance> that = (SupplierOfInstance>) obj;
+ return Objects.equal(instance, that.instance);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(instance);
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.ofInstance(" + instance + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling
+ * it, making it thread-safe.
+ */
+ public static Supplier synchronizedSupplier(
+ Supplier delegate) {
+ return new ThreadSafeSupplier<>(delegate);
+ }
+
+ private static class ThreadSafeSupplier
+ implements Supplier, Serializable {
+ final Supplier delegate;
+
+ ThreadSafeSupplier(Supplier delegate) {
+ this.delegate = checkNotNull(delegate);
+ }
+
+ @Override
+ public T get() {
+ synchronized (delegate) {
+ return delegate.get();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.synchronizedSupplier(" + delegate + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a function that accepts a supplier and returns the result of invoking {@link
+ * Supplier#get} on that supplier.
+ *
+ *