diff --git a/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/DowngradeFlags.kt b/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/DowngradeFlags.kt index fd7cdbe..c5323db 100644 --- a/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/DowngradeFlags.kt +++ b/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/DowngradeFlags.kt @@ -106,4 +106,12 @@ interface DowngradeFlags: TransformParameters { @get:Optional val multiReleaseVersions: SetProperty + /** + * sets if should downgrade classess from the multi-release folder, instead of selecting the normal one + * @since 1.2.1 + */ + @get:Input + @get:Optional + val downgradeFromMultiReleases: Property + } diff --git a/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/toFlags.kt b/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/toFlags.kt index 1607740..fd44730 100644 --- a/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/toFlags.kt +++ b/gradle-plugin/src/main/kotlin/xyz/wagyourtail/jvmdg/gradle/flags/toFlags.kt @@ -18,6 +18,7 @@ fun DowngradeFlags.toFlags(): Flags { flags.debugDumpClasses = debugDumpClasses.getOrElse(false) flags.multiReleaseOriginal = multiReleaseOriginal.getOrElse(false) flags.multiReleaseVersions = multiReleaseVersions.getOrElse(emptySet()).map { it.toOpcode() }.toSet() + flags.downgradeFromMultiReleases = downgradeFromMultiReleases.getOrElse(false) if (this is ShadeFlags) { flags.shadeInlining = shadeInlining.get() } diff --git a/gradle.properties b/gradle.properties index cfc81a4..37c76d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,9 +2,9 @@ kotlin.code.style=official org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true -version=1.2.0 +version=1.2.1 -asm_version=9.7 +asm_version=9.7.1 mainVersion=7 testVersion=21 diff --git a/src/main/java/xyz/wagyourtail/jvmdg/classloader/DowngradingClassLoader.java b/src/main/java/xyz/wagyourtail/jvmdg/classloader/DowngradingClassLoader.java index 2f23ebd..7110a10 100644 --- a/src/main/java/xyz/wagyourtail/jvmdg/classloader/DowngradingClassLoader.java +++ b/src/main/java/xyz/wagyourtail/jvmdg/classloader/DowngradingClassLoader.java @@ -115,7 +115,11 @@ public byte[] apply(String s) { @Override protected int maxClassVersionSupported() { - return holder.maxVersion(); + if (!holder.flags.downgradeFromMultiReleases) { + return Utils.getCurrentClassVersion(); + } else { + return holder.maxVersion(); + } } @Override diff --git a/src/main/java/xyz/wagyourtail/jvmdg/cli/Flags.java b/src/main/java/xyz/wagyourtail/jvmdg/cli/Flags.java index 1acb8f3..613ac0c 100644 --- a/src/main/java/xyz/wagyourtail/jvmdg/cli/Flags.java +++ b/src/main/java/xyz/wagyourtail/jvmdg/cli/Flags.java @@ -106,6 +106,13 @@ public class Flags { */ public Set multiReleaseVersions = new HashSet<>(getMultiReleaseVersions()); + /** + * if should downgrade classes from the multi-release folder, instead of selecting the normal one + * + * @since 1.2.1 + */ + public boolean downgradeFromMultiReleases = false; + public Flags() { getIgnoreWarnings(); } @@ -124,6 +131,7 @@ public Flags copy() { flags.debugDumpClasses = debugDumpClasses; flags.multiReleaseOriginal = multiReleaseOriginal; flags.multiReleaseVersions = new HashSet<>(multiReleaseVersions); + flags.downgradeFromMultiReleases = downgradeFromMultiReleases; return flags; } diff --git a/src/main/java/xyz/wagyourtail/jvmdg/compile/PathDowngrader.java b/src/main/java/xyz/wagyourtail/jvmdg/compile/PathDowngrader.java index 4114e0c..e2ea267 100644 --- a/src/main/java/xyz/wagyourtail/jvmdg/compile/PathDowngrader.java +++ b/src/main/java/xyz/wagyourtail/jvmdg/compile/PathDowngrader.java @@ -66,6 +66,15 @@ protected int maxClassVersionSupported() { return downgrader.maxVersion(); } + @Override + protected List multiVersionPrefixes() { + if (downgrader.flags.downgradeFromMultiReleases) { + return super.multiVersionPrefixes(); + } else { + return Collections.singletonList(""); + } + } + }) { // zip input and output for (int i = 0; i < inputRoots.size(); i++) { @@ -76,6 +85,7 @@ protected int maxClassVersionSupported() { for (int j = downgrader.maxVersion(); j >= 52; j--) { multiReleasePaths.add("META-INF/versions/" + Utils.classVersionToMajorVersion(j)); } + final Set visitedClasses = new HashSet<>(); AsyncUtils.visitPathsAsync(in, new IOFunction() { @@ -92,27 +102,45 @@ public void accept(Path path) throws IOException { Path relativized = in.relativize(path); Path outFile = out.resolve(relativized.toString()); if (path.getFileName().toString().endsWith(".class")) { - if (!relativized.startsWith("META-INF/versions")) { - // prefer multi-release over normal + + if (relativized.startsWith("META-INF/versions")) { + if (downgrader.flags.downgradeFromMultiReleases) { + relativized = relativized.subpath(3, relativized.getNameCount()); + outFile = out.resolve(relativized); + } else { + return; + } + } + + // dont if already visited + if (visitedClasses.contains(outFile)) { + return; + } + + if (downgrader.flags.downgradeFromMultiReleases) { + // prefer highest multi-release for (String pth : multiReleasePaths) { if (Files.exists(in.resolve(pth).resolve(relativized))) { path = in.resolve(pth).resolve(relativized); break; } } + } - try { - String relativizedName = relativized.toString(); - if (relativized.getFileSystem().getSeparator().equals("\\")) { - relativizedName = relativizedName.replace('\\', '/'); - } - String internalName = relativizedName.substring(0, relativizedName.length() - 6); - byte[] bytes = Files.readAllBytes(path); - Map outputs = downgrader.downgrade(new AtomicReference<>(internalName), bytes, false, new Function() { - @Override - public byte[] apply(String s) { - try { - // multi-version + try { + String relativizedName = relativized.toString(); + if (relativized.getFileSystem().getSeparator().equals("\\")) { + relativizedName = relativizedName.replace('\\', '/'); + } + String internalName = relativizedName.substring(0, relativizedName.length() - 6); + byte[] bytes = Files.readAllBytes(path); + Map outputs = downgrader.downgrade(new AtomicReference<>(internalName), bytes, false, new Function() { + @Override + public byte[] apply(String s) { + try { + + // multi-version + if (downgrader.flags.downgradeFromMultiReleases) { for (String pth : multiReleasePaths) { for (Path in : inputRoots) { Path p = in.resolve(pth).resolve(s + ".class"); @@ -121,41 +149,41 @@ public byte[] apply(String s) { } } } + } - // main version - for (Path in : inputRoots) { - Path p = in.resolve(s + ".class"); - if (Files.exists(p)) { - return Files.readAllBytes(p); - } + // main version + for (Path in : inputRoots) { + Path p = in.resolve(s + ".class"); + if (Files.exists(p)) { + return Files.readAllBytes(p); } + } - URL url = extraClasspath.getResource(s + ".class"); - if (url == null) return null; - try (InputStream is = url.openStream()) { - return Utils.readAllBytes(is); - } - } catch (IOException e) { - throw new RuntimeException(e); + URL url = extraClasspath.getResource(s + ".class"); + if (url == null) return null; + try (InputStream is = url.openStream()) { + return Utils.readAllBytes(is); } + } catch (IOException e) { + throw new RuntimeException(e); } - }); - if (outputs == null) { - Files.copy(path, outFile, StandardCopyOption.REPLACE_EXISTING); - } else { - for (Map.Entry entry : outputs.entrySet()) { - String internal = entry.getKey(); - Path p = out.resolve(internal + ".class"); - Path parent = p.getParent(); - if (parent != null) { - Files.createDirectories(parent); - } - Files.write(p, entry.getValue(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); + } + }); + if (outputs == null) { + Files.copy(path, outFile, StandardCopyOption.REPLACE_EXISTING); + } else { + for (Map.Entry entry : outputs.entrySet()) { + String internal = entry.getKey(); + Path p = out.resolve(internal + ".class"); + Path parent = p.getParent(); + if (parent != null) { + Files.createDirectories(parent); } + Files.write(p, entry.getValue(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); } - } catch (IllegalClassFormatException e) { - throw new IOException("Failed to downgrade " + path, e); } + } catch (IllegalClassFormatException e) { + throw new IOException("Failed to downgrade " + path, e); } } else if (relativized.toString().equals("META-INF/MANIFEST.MF")) { // add version number to manifest