mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-22 16:41:46 +03:00
[FEATURE] Аннотация LauncherInject и возможность её использования.
Для использования нужен BuildTask по примеру Patcher`а, но с конверсией в классноду и обратно. Чтение класса должно быть с EXPAND_FRAMES, а запись с 0 (без COMPUTE_FRAMES).
This commit is contained in:
parent
64d57faa48
commit
ea6e131b60
2 changed files with 64 additions and 0 deletions
|
@ -0,0 +1,51 @@
|
|||
package pro.gravit.launchserver.asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.objectweb.asm.AnnotationVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.AnnotationNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
||||
import pro.gravit.launcher.LauncherInject;
|
||||
|
||||
public class InjectClassAcceptor {
|
||||
public static final Class<?>[] primitives = new Class<?>[] { java.lang.Boolean.class, java.lang.Character.class,
|
||||
java.lang.Byte.class, java.lang.Short.class, java.lang.Integer.class, java.lang.Long.class,
|
||||
java.lang.Float.class, java.lang.Double.class, java.lang.String.class };
|
||||
|
||||
public static final List<Class<?>> zPrimitivesList = Arrays.asList(primitives);
|
||||
public static final String INJ_DESC = Type.getDescriptor(LauncherInject.class);
|
||||
|
||||
public static void visit(ClassNode cn, Map<String, Object> object) {
|
||||
if (!object.values().stream().allMatch(zPrimitivesList::contains))
|
||||
throw new IllegalArgumentException("Only primitives in values...");
|
||||
cn.fields.stream().filter(e -> e.invisibleAnnotations != null)
|
||||
.filter(e -> e.invisibleAnnotations.stream().anyMatch(f -> f.desc.equals(INJ_DESC))).forEach(e -> {
|
||||
// Notice that fields that will be used with this algo should not have default
|
||||
// value by = ...;
|
||||
AnnotationNode n = e.invisibleAnnotations.stream().filter(f -> INJ_DESC.equals(f.desc)).findFirst()
|
||||
.get();
|
||||
AtomicReference<String> valueName = new AtomicReference<>(null);
|
||||
n.accept(new AnnotationVisitor(Opcodes.ASM7) {
|
||||
@Override
|
||||
public void visit(final String name, final Object value) {
|
||||
if ("value".equals(name)) {
|
||||
if (value.getClass() != String.class)
|
||||
throw new IllegalArgumentException(
|
||||
"Invalid Annotation with value class " + e.getClass().getName());
|
||||
valueName.set(value.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
if (valueName.get() == null)
|
||||
throw new IllegalArgumentException("Annotation should always contains 'value' key");
|
||||
if (object.containsKey(valueName.get()))
|
||||
e.value = object.get(valueName.get());
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package pro.gravit.launcher;
|
||||
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.RetentionPolicy.CLASS;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(CLASS)
|
||||
@Target(FIELD)
|
||||
public @interface LauncherInject {
|
||||
public String value(); // target of inject
|
||||
}
|
Loading…
Reference in a new issue