From 5457b6028b9aa0165cc350a8dddcea485d200666 Mon Sep 17 00:00:00 2001 From: Geolykt Date: Sun, 23 Oct 2022 12:14:47 +0200 Subject: [PATCH] Don't include mock FF internals in the runtime classpath. This fixes issues with QF over at sl-starplane --- .../java/CompilationFailedException.java | 10 +++ build.bash | 2 +- buildscript/src/main/java/Buildscript.java | 62 ++++++++++++++++++- .../io/github/coolcrabs/fernutil/TJump.java | 31 ++++++++-- .../java/decompiler/main/Fernflower.java | 22 ------- offline-build.bash | 2 +- 6 files changed, 98 insertions(+), 31 deletions(-) delete mode 100644 fernutil/src/main/java/org/jetbrains/java/decompiler/main/Fernflower.java diff --git a/brachyura/src/main/java/io/github/coolcrabs/brachyura/compiler/java/CompilationFailedException.java b/brachyura/src/main/java/io/github/coolcrabs/brachyura/compiler/java/CompilationFailedException.java index 25471a7b..dbe00a15 100644 --- a/brachyura/src/main/java/io/github/coolcrabs/brachyura/compiler/java/CompilationFailedException.java +++ b/brachyura/src/main/java/io/github/coolcrabs/brachyura/compiler/java/CompilationFailedException.java @@ -1,6 +1,16 @@ package io.github.coolcrabs.brachyura.compiler.java; +import org.jetbrains.annotations.NotNull; + public class CompilationFailedException extends RuntimeException { private static final long serialVersionUID = 7555474203258502895L; // Slbrachyura: Add serialVersionUID + + public CompilationFailedException() { + // Default-constructor + } + + public CompilationFailedException(@NotNull Throwable t) { + super(t); + } } diff --git a/build.bash b/build.bash index 457d77cb..2544b2c5 100755 --- a/build.bash +++ b/build.bash @@ -1,3 +1,3 @@ #!/bin/bash javac Buildscript.java -java Buildscript build +java Buildscript publish diff --git a/buildscript/src/main/java/Buildscript.java b/buildscript/src/main/java/Buildscript.java index 999a326d..6ec3612c 100644 --- a/buildscript/src/main/java/Buildscript.java +++ b/buildscript/src/main/java/Buildscript.java @@ -1,16 +1,25 @@ import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.IOException; +import java.io.OutputStream; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.net.URL; import java.net.URLClassLoader; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileVisitOption; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; import javax.tools.StandardLocation; @@ -18,6 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.tinylog.Logger; +import io.github.coolcrabs.brachyura.compiler.java.CompilationFailedException; import io.github.coolcrabs.brachyura.compiler.java.JavaCompilation; import io.github.coolcrabs.brachyura.compiler.java.JavaCompilationOptions; import io.github.coolcrabs.brachyura.compiler.java.JavaCompilationResult; @@ -42,7 +52,8 @@ public class Buildscript extends BaseJavaProject { static final String GROUP = "de.geolykt.starloader.brachyura"; - private static final String BRACHY_VERSION = "0.94.4"; + private static final String BRACHY_VERSION = "0.94.5"; + private static final String FERNUTIL_VERSION = "0.2.1"; @NotNull private final JavaCompilationOptions compileOptions = new JavaCompilationOptions(); @@ -179,8 +190,21 @@ public String getJarBaseName() { } public final Lazy built = new Lazy<>(this::build); + protected BJarResult build() { Path buildLibsDir = PathUtil.resolveAndCreateDir(PathUtil.resolveAndCreateDir(getModuleRoot(), "build"), "libs"); + // Slbrachyura start: Purge old jars before building jars + try { + List jars = Files.walk(buildLibsDir, 1) + .filter(p -> p.getFileName().toString().endsWith(".jar")) + .collect(Collectors.toList()); + for (Path jar : jars) { + Files.delete(jar); + } + } catch (IOException e) { + e.printStackTrace(); + } + // Slbrachyura end Path testSrc = getModuleRoot().resolve("src").resolve("test").resolve("java"); Path outjar = buildLibsDir.resolve(getJarBaseName() + ".jar"); Path outjarsources = buildLibsDir.resolve(getJarBaseName() + "-sources.jar"); @@ -318,7 +342,7 @@ public boolean hasTests() { @Override @NotNull MavenId getId() { - return new MavenId(GROUP, "fernutil", "0.2"); + return new MavenId(GROUP, "fernutil", FERNUTIL_VERSION); } @Override @@ -333,6 +357,40 @@ protected List createDependencies() { } return deps; } + + // Slbrachyura start: Don't include mock FF internals in the runtime classpath. + @Override + protected BJarResult build() { + BJarResult result = super.build(); + Path jarPath = result.main.jar; + if (Files.exists(jarPath)) { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + byte[] bytebuffer = new byte[4096]; + try (ZipInputStream zipIn = new ZipInputStream(Files.newInputStream(jarPath), StandardCharsets.UTF_8); + ZipOutputStream zipOut = new ZipOutputStream(bytes, StandardCharsets.UTF_8)) { + for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn.getNextEntry()) { + if (entry.getName().startsWith("org/jetbrains/java/decompiler/") || entry.getName().startsWith("/org/jetbrains/java/decompiler/")) { + continue; + } + zipOut.putNextEntry(entry); + for (int read = zipIn.read(bytebuffer); read != -1; read = zipIn.read(bytebuffer)) { + zipOut.write(bytebuffer, 0, read); + } + } + } catch (IOException e) { + throw new CompilationFailedException(e); + } + try (OutputStream out = Files.newOutputStream(jarPath, StandardOpenOption.TRUNCATE_EXISTING)) { + bytes.writeTo(out); + } catch (IOException e) { + throw new CompilationFailedException(e); + } + } else { + throw new IllegalStateException("Build failure? Built jar doesn't exist for some reason."); + } + return result; + } + // Slbrachyura end }; public final Lazy> asm = new Lazy<>(this::createAsm); diff --git a/fernutil/src/main/java/io/github/coolcrabs/fernutil/TJump.java b/fernutil/src/main/java/io/github/coolcrabs/fernutil/TJump.java index b38124a4..7b0253d4 100644 --- a/fernutil/src/main/java/io/github/coolcrabs/fernutil/TJump.java +++ b/fernutil/src/main/java/io/github/coolcrabs/fernutil/TJump.java @@ -1,13 +1,16 @@ package io.github.coolcrabs.fernutil; +import java.io.File; import java.io.IOException; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.function.Consumer; -import org.jetbrains.java.decompiler.main.Fernflower; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import io.github.coolcrabs.fernutil.FernUtil.JavadocProvider; @@ -43,13 +46,31 @@ public static void decompile(Path inJar, Path outSources, List cp, Consume options.put(IFernflowerPreferences.NEW_LINE_SEPARATOR, "\n"); // Threads configured by default in all ff forks if (fabric) options.put(IFabricJavadocProvider.PROPERTY_NAME, new TJavadocProviderFabric(provider)); - Fernflower ff = new Fernflower(bytecodeProvider, resultSaver, options, new TFFLogger()); - ff.addSource(inJar.toFile()); + Class ffClass = Class.forName("org.jetbrains.java.decompiler.main.Fernflower", true, PackageHack.class.getClassLoader()); + MethodType ffCtorType = MethodType.fromMethodDescriptorString("(Lorg/jetbrains/java/decompiler/main/extern/IBytecodeProvider;Lorg/jetbrains/java/decompiler/main/extern/IResultSaver;Ljava/util/Map;Lorg/jetbrains/java/decompiler/main/extern/IFernflowerLogger;)V", ffClass.getClassLoader()); + MethodHandle ffCtorHandle = MethodHandles.publicLookup().findConstructor(ffClass, ffCtorType); + Object ff = ffCtorHandle.invoke(bytecodeProvider, resultSaver, options, new TFFLogger()); + MethodHandles.publicLookup().bind(ff, "addSource", MethodType.methodType(Void.class, File.class)).invoke(inJar.toFile()); + MethodHandle addLibHandle = MethodHandles.publicLookup().bind(ff, "addLibrary", MethodType.methodType(Void.class, File.class)); for (Path p : cp) { - ff.addLibrary(p.toFile()); + addLibHandle.invoke(p.toFile()); + } + MethodHandles.publicLookup().bind(ff, "decompileContext", MethodType.methodType(Void.class)).invoke(); + } catch (Throwable t) { + if (t instanceof Exception) { + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + throw new IllegalStateException(t); + } else { + sneak(t); } - ff.decompileContext(); } } + + @SuppressWarnings("unchecked") + private static void sneak(Throwable t) throws T { + throw (T) t; + } } } diff --git a/fernutil/src/main/java/org/jetbrains/java/decompiler/main/Fernflower.java b/fernutil/src/main/java/org/jetbrains/java/decompiler/main/Fernflower.java deleted file mode 100644 index 278745fe..00000000 --- a/fernutil/src/main/java/org/jetbrains/java/decompiler/main/Fernflower.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.jetbrains.java.decompiler.main; - -import java.io.File; -import java.util.Map; - -import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; -import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; -import org.jetbrains.java.decompiler.main.extern.IResultSaver; - -public class Fernflower { - public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map customProperties, IFernflowerLogger logger) { - } - - public void addSource(File source) { - } - - public void addLibrary(File library) { - } - - public void decompileContext() { - } -} diff --git a/offline-build.bash b/offline-build.bash index 71993681..aa327d2c 100755 --- a/offline-build.bash +++ b/offline-build.bash @@ -1,3 +1,3 @@ #!/bin/bash javac Buildscript.java -java -Dskiptests=true Buildscript build +java -Dskiptests=true Buildscript publish