Shrunk jar file size, fixed errors, added database reload

- Fixed H2 database error on index creation when loading plugin by using dynamic library downloader/loader from Lucko's Helper.
- Shrunk jar file size extensively so it can be uploaded to Spigot directly.
- Updated h2database driver to 2.1.214 to patch vulnerability
- Updated mysql database driver to 8.0.30 to patch vulnerability
- Updated MongoDB java driver to 3.12.11.
This commit is contained in:
Dawson Hessler
2022-08-28 13:14:13 -04:00
parent 4c82755935
commit 9dc312186b
23 changed files with 1768 additions and 116 deletions
-25
View File
@@ -18,31 +18,6 @@
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.org.yaml.snakeyaml</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.com.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.org.bson</shadedPattern>
</relocation>
<relocation>
<pattern>com.mysql</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.com.mysql</shadedPattern>
</relocation>
<relocation>
<pattern>com.moandjiezana</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.com.moandjiezana</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
-25
View File
@@ -28,31 +28,6 @@
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>false</minimizeJar>
<relocations>
<relocation>
<pattern>org.yaml.snakeyaml</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.org.yaml.snakeyaml</shadedPattern>
</relocation>
<relocation>
<pattern>com.mongodb</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.com.mongodb</shadedPattern>
</relocation>
<relocation>
<pattern>org.bson</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.org.bson</shadedPattern>
</relocation>
<relocation>
<pattern>com.mysql</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.com.mysql</shadedPattern>
</relocation>
<relocation>
<pattern>com.moandjiezana</pattern>
<shadedPattern>dev.brighten.antivpn.utils.shaded.com.moandjiezana</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
-22
View File
@@ -58,28 +58,6 @@
<artifactId>Common</artifactId>
<version>1.8.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>toml4j</artifactId>
<groupId>com.moandjiezana.toml</groupId>
</exclusion>
<exclusion>
<artifactId>mysql-connector-java</artifactId>
<groupId>mysql</groupId>
</exclusion>
<exclusion>
<artifactId>h2</artifactId>
<groupId>com.h2database</groupId>
</exclusion>
<exclusion>
<artifactId>snakeyaml</artifactId>
<groupId>org.yaml</groupId>
</exclusion>
<exclusion>
<artifactId>mongo-java-driver</artifactId>
<groupId>org.mongodb</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cc.funkemunky.utils</groupId>
@@ -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;
-22
View File
@@ -52,28 +52,6 @@
<artifactId>Common</artifactId>
<version>1.8.2</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>toml4j</artifactId>
<groupId>com.moandjiezana.toml</groupId>
</exclusion>
<exclusion>
<artifactId>mysql-connector-java</artifactId>
<groupId>mysql</groupId>
</exclusion>
<exclusion>
<artifactId>h2</artifactId>
<groupId>com.h2database</groupId>
</exclusion>
<exclusion>
<artifactId>snakeyaml</artifactId>
<groupId>org.yaml</groupId>
</exclusion>
<exclusion>
<artifactId>mongo-java-driver</artifactId>
<groupId>org.mongodb</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.github.bungee</groupId>
@@ -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;
+7 -13
View File
@@ -45,36 +45,30 @@
</repositories>
<dependencies>
<dependency>
<groupId>com.moandjiezana.toml</groupId>
<artifactId>toml4j</artifactId>
<version>0.7.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<version>8.0.30</version>
<type>jar</type>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.210</version>
<scope>compile</scope>
<version>2.1.214</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.30</version>
<scope>compile</scope>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.10</version>
<scope>compile</scope>
<version>3.12.11</version>
<scope>provided</scope>
</dependency>
</dependencies>
@@ -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!";
@@ -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();
}
@@ -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());
}
@@ -0,0 +1,200 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* 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<URLClassLoaderAccess> 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() + ")";
}
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* 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 {};
}
@@ -0,0 +1,67 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* 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");
}
@@ -0,0 +1,45 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* 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();
}
@@ -0,0 +1,175 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* 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<URL> unopenedURLs;
private final Collection<URL> pathURLs;
@SuppressWarnings("unchecked")
Unsafe(URLClassLoader classLoader) {
super(classLoader);
Collection<URL> unopenedURLs;
Collection<URL> pathURLs;
try {
Object ucp = fetchField(URLClassLoader.class, classLoader, "ucp");
unopenedURLs = (Collection<URL>) fetchField(ucp.getClass(), ucp, "unopenedUrls");
pathURLs = (Collection<URL>) 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();
}
}
}
@@ -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 {}
@@ -0,0 +1,36 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* 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 {
}
@@ -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.
*
* <p>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.
*
* <p>An example use case for this method is in implementing an {@code Iterator<T>} 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.
*
* <p>Why <i>not</i> 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 extends Object> T uncheckedCastNullableTToT(T t) {
return t;
}
private NullnessCasts() {}
}
@@ -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}.
*
* <p>See the Guava User Guide on <a
* href="https://github.com/google/guava/wiki/CommonObjectUtilitiesExplained">writing {@code Object}
* methods with {@code Objects}</a>.
*
* @author Laurence Gonsalves
* @since 2.0
*/
public final class Objects extends ExtraObjectsMethodsForWeb {
private Objects() {}
/**
* Determines whether two possibly-null objects are equal. Returns:
*
* <ul>
* <li>{@code true} if {@code a} and {@code b} are both null.
* <li>{@code true} if {@code a} and {@code b} are both non-null and they are equal according to
* {@link Object#equals(Object)}.
* <li>{@code false} in all other situations.
* </ul>
*
* <p>This assumes that any non-null objects passed to this function conform to the {@code
* equals()} contract.
*
* <p><b>Note for Java 7 and later:</b> 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.
*
* <p>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:
*
* <pre>{@code
* public int hashCode() {
* return Objects.hashCode(getX(), getY(), getZ());
* }
* }</pre>
*
* <p><b>Warning:</b> When a single object is supplied, the returned hash code does not equal the
* hash code of that object.
*
* <p><b>Note for Java 7 and later:</b> 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);
}
}
@@ -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> T checkNotNull(T reference) {
if (reference == null) {
throw new NullPointerException();
} else {
return reference;
}
}
public static <T> T checkNotNull(T reference, Object errorMessage) {
if (reference == null) {
throw new NullPointerException(String.valueOf(errorMessage));
} else {
return reference;
}
}
public static <T> T checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs) {
if (reference == null) {
throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs));
} else {
return reference;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, char p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, int p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, long p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> T checkNotNull(T obj, String errorMessageTemplate, Object p1) {
if (obj == null) {
throw new NullPointerException(format(errorMessageTemplate, p1));
} else {
return obj;
}
}
public static <T> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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();
}
}
@@ -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<T> extends java.util.function.Supplier<T> {
T get();
}
@@ -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.
*
* <p>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 <F extends Object, T extends Object> Supplier<T> compose(
Function<? super F, T> function, Supplier<F> supplier) {
return new SupplierComposition<>(function, supplier);
}
private static class SupplierComposition<F extends Object, T extends Object>
implements Supplier<T>, Serializable {
final Function<? super F, T> function;
final Supplier<F> supplier;
SupplierComposition(Function<? super F, T> function, Supplier<F> 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: <a
* href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>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.
*
* <p>When the underlying delegate throws an exception then this memoizing supplier will keep
* delegating calls until it returns valid data.
*
* <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
* returned directly.
*/
public static <T extends Object> Supplier<T> memoize(Supplier<T> delegate) {
if (delegate instanceof NonSerializableMemoizingSupplier
|| delegate instanceof MemoizingSupplier) {
return delegate;
}
return delegate instanceof Serializable
? new MemoizingSupplier<T>(delegate)
: new NonSerializableMemoizingSupplier<T>(delegate);
}
static class MemoizingSupplier<T extends Object> implements Supplier<T>, Serializable {
final Supplier<T> 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<T> 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 ? "<supplier that returned " + value + ">" : delegate)
+ ")";
}
private static final long serialVersionUID = 0;
}
static class NonSerializableMemoizingSupplier<T extends Object> implements Supplier<T> {
volatile Supplier<T> delegate;
volatile boolean initialized;
// "value" does not need to be volatile; visibility piggy-backs
// on volatile read of "initialized".
T value;
NonSerializableMemoizingSupplier(Supplier<T> 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<T> delegate = this.delegate;
return "Suppliers.memoize("
+ (delegate == null ? "<supplier that returned " + value + ">" : 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: <a
* href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
*
* <p>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.
*
* <p>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 <T extends Object> Supplier<T> memoizeWithExpiration(
Supplier<T> delegate, long duration, TimeUnit unit) {
return new ExpiringMemoizingSupplier<>(delegate, duration, unit);
}
@SuppressWarnings("GoodTime") // lots of violations
static class ExpiringMemoizingSupplier<T extends Object>
implements Supplier<T>, Serializable {
final Supplier<T> delegate;
final long durationNanos;
transient volatile T value;
// The special value 0 means "not yet initialized".
transient volatile long expirationNanos;
ExpiringMemoizingSupplier(Supplier<T> 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 <T extends Object> Supplier<T> ofInstance(
T instance) {
return new SupplierOfInstance<>(instance);
}
private static class SupplierOfInstance<T extends Object>
implements Supplier<T>, 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 <T extends Object> Supplier<T> synchronizedSupplier(
Supplier<T> delegate) {
return new ThreadSafeSupplier<>(delegate);
}
private static class ThreadSafeSupplier<T extends Object>
implements Supplier<T>, Serializable {
final Supplier<T> delegate;
ThreadSafeSupplier(Supplier<T> 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.
*
* <p><b>Java 8 users:</b> use the method reference {@code Supplier::get} instead.
*
* @since 8.0
*/
public static <T extends Object> Function<Supplier<T>, T> supplierFunction() {
@SuppressWarnings("unchecked") // implementation is "fully variant"
SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
return sf;
}
private interface SupplierFunction<T extends Object> extends Function<Supplier<T>, T> {}
private enum SupplierFunctionImpl implements SupplierFunction<Object> {
INSTANCE;
// Note: This makes T a "pass-through type"
@Override
public Object apply(Supplier<Object> input) {
return input.get();
}
@Override
public String toString() {
return "Suppliers.supplierFunction()";
}
}
}
@@ -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;