package de.geolykt.starloader.launcher; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Map; import java.util.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; import org.slf4j.LoggerFactory; import org.stianloader.micromixin.transform.api.BytecodeProvider; import org.stianloader.micromixin.transform.api.CodeSourceURIProvider; import org.stianloader.micromixin.transform.api.supertypes.ASMClassWrapperProvider; import net.minestom.server.extras.selfmodification.HierarchyClassLoader; import net.minestom.server.extras.selfmodification.MinestomRootClassLoader; import de.geolykt.starloader.util.JavaInterop; final class MixinBytecodeProvider extends ASMClassWrapperProvider implements BytecodeProvider, CodeSourceURIProvider { @NotNull private final Map smapURIAliases; public MixinBytecodeProvider(@NotNull Map smapURIAliases) { this.smapURIAliases = smapURIAliases; } @Override @NotNull public ClassNode getClassNode(HierarchyClassLoader modularityAttachment, @NotNull String name) throws ClassNotFoundException { ClassNode node = new ClassNode(); ClassReader cr; try { String path = name.replace('.', '/') + ".class"; InputStream input = modularityAttachment.getResourceAsStreamWithChildren(path); if (input == null) { throw new ClassNotFoundException("Classloader " + JavaInterop.getClassloaderName(modularityAttachment) + " does not provide " + path); } cr = new ClassReader(input); } catch (IOException e) { throw new ClassNotFoundException("Unable to provide classnode", e); } cr.accept(node, 0); return node; } @Override @Nullable public ClassNode getNode(@NotNull String name) { try { return this.getClassNode(MinestomRootClassLoader.getInstance(), name); } catch (ClassNotFoundException cnfe) { LoggerFactory.getLogger(MixinBytecodeProvider.class).trace("Cannot resolve node", cnfe); return null; } } @Override @Nullable public URI findURI(@Nullable HierarchyClassLoader modularityAttachment, @NotNull String internalClassName) { URL url = Objects.requireNonNull(modularityAttachment).getResourceAsURLWithChildren(internalClassName.replace('.', '/') + ".class"); URI uri = Utils.toCodeSourceURI(url, internalClassName); if (uri != null) { try { String uriString = uri.toString(); uriString = this.smapURIAliases.getOrDefault(uriString, uriString); return new URI(Objects.requireNonNull(uriString)); } catch (URISyntaxException e) { LoggerFactory.getLogger(MixinBytecodeProvider.class).warn("Cannot convert url to URI: {}", url, e); return null; } } else { return null; } } }