[FEATURE] Аннотация LauncherInject и возможность её использования.

Для использования нужен BuildTask по примеру Patcher`а, но с конверсией в классноду и обратно. Чтение класса должно быть с EXPAND_FRAMES, а запись с 0 (без COMPUTE_FRAMES).
This commit is contained in:
Zaxar163 2020-01-14 18:01:59 +01:00
parent 64d57faa48
commit ea6e131b60
No known key found for this signature in database
GPG key ID: 1FE4F2E1F053831B
2 changed files with 64 additions and 0 deletions

View file

@ -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());
});
}
}

View file

@ -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
}