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 @@ Common 1.8.2 provided - - - 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 @@ Common 1.8.2 provided - - - 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 - mysql mysql-connector-java - 8.0.28 + 8.0.30 jar - compile + provided com.h2database h2 - 2.1.210 - compile + 2.1.214 + provided org.yaml snakeyaml 1.30 - compile + provided org.mongodb mongo-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 function, Supplier supplier) { + return new SupplierComposition<>(function, supplier); + } + + private static class SupplierComposition + implements Supplier, Serializable { + final Function function; + final Supplier supplier; + + SupplierComposition(Function 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. + * + *

Java 8 users: use the method reference {@code Supplier::get} instead. + * + * @since 8.0 + */ + public static Function, T> supplierFunction() { + @SuppressWarnings("unchecked") // implementation is "fully variant" + SupplierFunction sf = (SupplierFunction) SupplierFunctionImpl.INSTANCE; + return sf; + } + + private interface SupplierFunction extends Function, T> {} + + private enum SupplierFunctionImpl implements SupplierFunction { + INSTANCE; + + // Note: This makes T a "pass-through type" + @Override + public Object apply(Supplier input) { + return input.get(); + } + + @Override + public String toString() { + return "Suppliers.supplierFunction()"; + } + } +} diff --git a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java index dd2b89e..afecfa9 100644 --- a/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java +++ b/Velocity/src/main/java/dev/brighten/antivpn/velocity/VelocityPlugin.java @@ -8,7 +8,6 @@ import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.ProxyServer; import dev.brighten.antivpn.AntiVPN; import dev.brighten.antivpn.command.Command; -import dev.brighten.antivpn.utils.ConfigDefault; import dev.brighten.antivpn.velocity.command.VelocityCommand; import lombok.Getter; import org.bstats.velocity.Metrics;