mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-31 20:59:54 +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