com.cryptomorin.xseries.reflection.AggregateReflectiveHandle Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of XSeries Show documentation
Show all versions of XSeries Show documentation
A set of utilities for Minecraft plugins
package com.cryptomorin.xseries.reflection;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
/**
* Most reflection APIs already provide a name-based fallback system that can be used (like {@link com.cryptomorin.xseries.reflection.jvm.classes.DynamicClassHandle#named(String...)})
* but sometimes the signature of certain JVM declarations just change entirely, that's where this class could be useful.
*
* It simply tries the {@link #reflect()} method of each handle until one of them returns without throwing an exception (order matters).
*
Usage
* {@code
* MethodMemberHandle profileByName = XReflection.of(GameProfileCache.class).method().named("getProfile", "a");
* MethodHandle getProfileByName = XReflection.anyOf(
* () -> profileByName.signature("public GameProfile get(String username);"),
* () -> profileByName.signature("public Optional get(String username);")
* ).reflect();
* }
* @param the JVM type of {@link H}
* @param the types of handles that are going to be checked.
* @see ReflectiveHandle
*/
public class AggregateReflectiveHandle> implements ReflectiveHandle {
private final List> handles;
private Consumer handleModifier;
protected AggregateReflectiveHandle(Collection> handles) {
this.handles = new ArrayList<>(handles.size());
this.handles.addAll(handles);
}
/**
* @see #or(Callable)
*/
public AggregateReflectiveHandle or(@Nonnull H handle) {
return or(() -> handle);
}
/**
* @see #or(ReflectiveHandle)
*/
public AggregateReflectiveHandle or(@Nonnull Callable handle) {
this.handles.add(handle);
return this;
}
/**
* Action performed on all the handles before being checked.
*/
public AggregateReflectiveHandle modify(@Nullable Consumer handleModifier) {
this.handleModifier = handleModifier;
return this;
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public AggregateReflectiveHandle clone() {
AggregateReflectiveHandle handle = new AggregateReflectiveHandle<>(new ArrayList<>(handles));
handle.handleModifier = this.handleModifier;
return handle;
}
@Override
public T reflect() throws ReflectiveOperationException {
ClassNotFoundException errors = null;
for (Callable handle : handles) {
H handled;
try {
handled = handle.call();
} catch (Throwable ex) {
if (errors == null)
errors = new ClassNotFoundException("None of the aggregate handles were successful");
errors.addSuppressed(ex);
continue;
}
if (handleModifier != null) handleModifier.accept(handled);
try {
return handled.reflect();
} catch (Throwable ex) {
if (errors == null)
errors = new ClassNotFoundException("None of the aggregate handles were successful");
errors.addSuppressed(ex);
}
}
throw XReflection.relativizeSuppressedExceptions(errors);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy