From ea6e131b60113841f3fa69696a974d0e63661b96 Mon Sep 17 00:00:00 2001
From: Zaxar163 <zahar.vcherachny@yandex.ru>
Date: Tue, 14 Jan 2020 18:01:59 +0100
Subject: [PATCH] =?UTF-8?q?[FEATURE]=20=D0=90=D0=BD=D0=BD=D0=BE=D1=82?=
 =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20LauncherInject=20=D0=B8=20=D0=B2?=
 =?UTF-8?q?=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C=20?=
 =?UTF-8?q?=D0=B5=D1=91=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE?=
 =?UTF-8?q?=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F.=20=D0=94=D0=BB=D1=8F=20=D0=B8?=
 =?UTF-8?q?=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD?=
 =?UTF-8?q?=D0=B8=D1=8F=20=D0=BD=D1=83=D0=B6=D0=B5=D0=BD=20BuildTask=20?=
 =?UTF-8?q?=D0=BF=D0=BE=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D1=83=20Pat?=
 =?UTF-8?q?cher`=D0=B0,=20=D0=BD=D0=BE=20=D1=81=20=D0=BA=D0=BE=D0=BD=D0=B2?=
 =?UTF-8?q?=D0=B5=D1=80=D1=81=D0=B8=D0=B5=D0=B9=20=D0=B2=20=D0=BA=D0=BB?=
 =?UTF-8?q?=D0=B0=D1=81=D1=81=D0=BD=D0=BE=D0=B4=D1=83=20=D0=B8=20=D0=BE?=
 =?UTF-8?q?=D0=B1=D1=80=D0=B0=D1=82=D0=BD=D0=BE.=20=D0=A7=D1=82=D0=B5?=
 =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D0=B0=20?=
 =?UTF-8?q?=D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D0=BE=20=D0=B1=D1=8B=D1=82=D1=8C?=
 =?UTF-8?q?=20=D1=81=20EXPAND=5FFRAMES,=20=D0=B0=20=D0=B7=D0=B0=D0=BF?=
 =?UTF-8?q?=D0=B8=D1=81=D1=8C=20=D1=81=200=20(=D0=B1=D0=B5=D0=B7=20COMPUTE?=
 =?UTF-8?q?=5FFRAMES).?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../launchserver/asm/InjectClassAcceptor.java | 51 +++++++++++++++++++
 .../pro/gravit/launcher/LauncherInject.java   | 13 +++++
 2 files changed, 64 insertions(+)
 create mode 100644 LaunchServer/src/main/java/pro/gravit/launchserver/asm/InjectClassAcceptor.java
 create mode 100644 LauncherCore/src/main/java/pro/gravit/launcher/LauncherInject.java

diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/asm/InjectClassAcceptor.java b/LaunchServer/src/main/java/pro/gravit/launchserver/asm/InjectClassAcceptor.java
new file mode 100644
index 00000000..f8246e95
--- /dev/null
+++ b/LaunchServer/src/main/java/pro/gravit/launchserver/asm/InjectClassAcceptor.java
@@ -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());
+				});
+	}
+}
diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/LauncherInject.java b/LauncherCore/src/main/java/pro/gravit/launcher/LauncherInject.java
new file mode 100644
index 00000000..b11647c1
--- /dev/null
+++ b/LauncherCore/src/main/java/pro/gravit/launcher/LauncherInject.java
@@ -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
+}