Javadocs for prosperity, hopefully
This commit is contained in:
@@ -25,16 +25,35 @@ import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/**
|
||||
* Base class for plugin compatibility. Defines common functions for evaluating plugin compatibility conditions.
|
||||
* Any given instance of a subclass should always be a singleton. See {@link net.gensokyoreimagined.nitori.compatibility.PluginCompatibilityRegistry}
|
||||
*/
|
||||
public abstract class BasePluginCompatibility {
|
||||
|
||||
/**
|
||||
* List of plugin names required by this compatibility class. The names in this list are to be the same used in
|
||||
* the plugin.yml files in their respective plugins.
|
||||
*/
|
||||
private final String[] pluginNames;
|
||||
|
||||
/**
|
||||
* Whether the compatibility class has attempted to resolve the reflection references yet or not.
|
||||
*/
|
||||
private final AtomicBoolean reflectionResolutionAttempted = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* Define a new compatibility class.
|
||||
* @param pluginNames See {@link net.gensokyoreimagined.nitori.compatibility.BasePluginCompatibility#pluginNames}
|
||||
*/
|
||||
protected BasePluginCompatibility(String[] pluginNames) {
|
||||
this.pluginNames = pluginNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the class loaders for the plugins needed for this compatibility class.
|
||||
* @return The class loaders for the plugins needed for this compatibility class.
|
||||
*/
|
||||
@Nullable
|
||||
private Map<String, ClassLoader> collectPluginClassLoaders() {
|
||||
var pluginManager = Bukkit.getPluginManager();
|
||||
@@ -49,21 +68,48 @@ public abstract class BasePluginCompatibility {
|
||||
return pluginClassLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message for when checking a compatibility condition fails.
|
||||
* @param problemFormat The format String to be used for explaining the problem. Requires one `%s` for the class name.
|
||||
* @param e The exception thrown by the check failure.
|
||||
*/
|
||||
private void logCompatibilityCheckFailureMessage(@Nonnull String problemFormat, @Nonnull Exception e) {
|
||||
NitoriUtil.getPreferredLogger().error(NitoriUtil.makeLogMessage(problemFormat.formatted("`" + this.getClass().getName() + "`") + "! I'll assume the related plugin(s) will otherwise hang and always run on main. Please update my intel! Exception follows:\n" +
|
||||
e));
|
||||
}
|
||||
|
||||
/**
|
||||
* What to do when the plugin classes are not found.
|
||||
* @param e The exception thrown by the plugin classes not being found.
|
||||
*/
|
||||
private void onPluginClassesNotFound(ReflectiveOperationException e) {
|
||||
logCompatibilityCheckFailureMessage("FAILED TO LOCATE CLASSES FOR %s", e);
|
||||
}
|
||||
|
||||
/**
|
||||
* What to do when attempting to use the plugin reflection references fails.
|
||||
* @param e The exception thrown by an attempt to use a plugin reflection reference fails.
|
||||
*/
|
||||
private void onReferenceUseFailure(CompletionException e) {
|
||||
logCompatibilityCheckFailureMessage("FAILED TO USE REFLECTED REFERENCES FOR %s!", e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and caches plugin reflection references.
|
||||
* @param pluginClassLoaders The plugin class loaders used to resolve the reflection references.
|
||||
* @throws ReflectiveOperationException If something went wrong finding the resolutions for reflection references.
|
||||
*/
|
||||
protected abstract void collectReferences(@Nonnull Map<String, ClassLoader> pluginClassLoaders) throws ReflectiveOperationException;
|
||||
|
||||
/**
|
||||
* Fullfills a plugin compatibility boolean condition.
|
||||
* @param conditionCallback The function used to ultimately determine if the condition passes or fails.
|
||||
* The condition callback may throw an {@link IllegalStateException} if the reflection references have not yet been resolved.
|
||||
* @return If the necessary plugins aren't loaded, false.
|
||||
* Otherwise, if the reflection references failed to be resolved, or an unexpected exception is thrown by the condition callback, true.
|
||||
* Otherwise, the result of the condition callback.
|
||||
* @throws IllegalStateException If the reflection references weren't resolved before calling the condition callback.
|
||||
*/
|
||||
boolean completePluginCompatibilityCondition(BooleanSupplier conditionCallback) {
|
||||
synchronized (this) { // compatibility classes are singletons so syncing on itself is safe
|
||||
if (!this.reflectionResolutionAttempted.getAcquire()) {
|
||||
|
||||
@@ -14,9 +14,18 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
package net.gensokyoreimagined.nitori.compatibility;
|
||||
|
||||
/**
|
||||
* Stores and provides access to all plugin compatibility instances.
|
||||
*/
|
||||
public class PluginCompatibilityRegistry {
|
||||
|
||||
/**
|
||||
* Instance for Citizens compatibility.
|
||||
*/
|
||||
public static final PluginCompatibilityCitizens CITIZENS = new PluginCompatibilityCitizens();
|
||||
|
||||
/**
|
||||
* Instance for Train Carts compatibility.
|
||||
*/
|
||||
public static final PluginCompatibilityTrainCarts TRAIN_CARTS = new PluginCompatibilityTrainCarts();
|
||||
}
|
||||
|
||||
@@ -17,17 +17,40 @@ package net.gensokyoreimagined.nitori.compatibility.reflection;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A resolver for a reflection reference to be invoked at runtime when the resolution should be valid.
|
||||
* @param <T> The data type to be returned.
|
||||
*/
|
||||
public abstract class BaseReflectionReferenceResolver<T> {
|
||||
/**
|
||||
* The resolution of this reflection reference. Is null until resolved.
|
||||
*/
|
||||
@Nullable
|
||||
private T resolution;
|
||||
|
||||
/**
|
||||
* Resolves this reflection reference.
|
||||
* @param classLoader The class loader to use for resolving this reflection reference
|
||||
* @return The resolution of this reflection reference.
|
||||
* @throws ReflectiveOperationException If something went wrong finding the resolution for this reflection reference
|
||||
*/
|
||||
@Nonnull
|
||||
protected abstract T resolve(ClassLoader classLoader) throws ReflectiveOperationException;
|
||||
|
||||
/**
|
||||
* Accept a classloader and resolve this reflection reference.
|
||||
* @param classLoader The class loader to use for resolving this reflection reference
|
||||
* @throws ReflectiveOperationException If something went wrong finding the resolution for this reflection reference
|
||||
*/
|
||||
public void accept(ClassLoader classLoader) throws ReflectiveOperationException {
|
||||
this.resolution = resolve(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resolution of this reflection reference.
|
||||
* @return The resolution of this reflection reference.
|
||||
* @throws IllegalStateException If this reflection reference has not yet been resolved.
|
||||
*/
|
||||
@Nonnull
|
||||
public T getResolution() {
|
||||
if (this.resolution == null) {
|
||||
@@ -36,6 +59,13 @@ public abstract class BaseReflectionReferenceResolver<T> {
|
||||
return this.resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common function for resolving a class.
|
||||
* @param classLoader The class loader to use for finding the class.
|
||||
* @param classPath The path of the class.
|
||||
* @return The class
|
||||
* @throws ClassNotFoundException If the class could not be found with the given class loader
|
||||
*/
|
||||
@Nonnull
|
||||
protected static Class<?> resolveClass(ClassLoader classLoader, String classPath) throws ClassNotFoundException {
|
||||
return Class.forName(classPath, false, classLoader);
|
||||
|
||||
@@ -20,6 +20,10 @@ public class ClassReflectionReferenceResolver extends BaseReflectionReferenceRes
|
||||
|
||||
private final String classPath;
|
||||
|
||||
/**
|
||||
* Creates a new class resolver.
|
||||
* @param classPath The path of the class.
|
||||
*/
|
||||
public ClassReflectionReferenceResolver(String classPath) {
|
||||
this.classPath = classPath;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@ public class FieldReflectionReferenceResolver extends BaseReflectionReferenceRes
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
/**
|
||||
* Creates a new field resolver.
|
||||
* @param classPath The path of the class containing the field.
|
||||
* @param fieldName the name of the field.
|
||||
*/
|
||||
public FieldReflectionReferenceResolver(String classPath, String fieldName) {
|
||||
this.classPath = classPath;
|
||||
this.fieldName = fieldName;
|
||||
|
||||
@@ -26,6 +26,12 @@ public class MethodReflectionReferenceResolver extends BaseReflectionReferenceRe
|
||||
|
||||
private final Class<?>[] methodParameterClasses;
|
||||
|
||||
/**
|
||||
* Creates a new method resolver.
|
||||
* @param classPath The path of the class containing the method.
|
||||
* @param methodName The name of the method.
|
||||
* @param methodParameterClasses The classes of the parameter types of the method, per parameter, in order.
|
||||
*/
|
||||
public MethodReflectionReferenceResolver(String classPath, String methodName, Class<?>... methodParameterClasses) {
|
||||
this.classPath = classPath;
|
||||
this.methodName = methodName;
|
||||
|
||||
Reference in New Issue
Block a user