From 9e7ce6404502974285342b62c787bb16b80f3a02 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Thu, 4 Jul 2024 13:53:56 +0200 Subject: [PATCH 1/6] Remove package scanning in log4j2 configuration ModLauncher already includes the annotation processor that now writes the plugin metadata, making the deprecated packages attribute obsolete. This fixes warnings we get on startup: WARN StatusConsoleListener The use of package scanning to locate plugins is deprecated and will be removed in a future release --- src/main/resources/log4j2.xml | 2 +- src/test/resources/log4j2.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 78aa13c..78664cb 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -1,5 +1,5 @@ - + diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml index 2bd065a..a43313e 100644 --- a/src/test/resources/log4j2.xml +++ b/src/test/resources/log4j2.xml @@ -1,5 +1,5 @@ - + From 4ad37c278643efe21ae50cd1e31963ae5b7db4e9 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Mon, 1 Jul 2024 20:32:09 +0200 Subject: [PATCH 2/6] Make things in ML visible so that it can be used by FML in a library-like fashion. --- gradle/daemon-jvm.properties | 3 ++ .../cpw/mods/modlauncher/ArgumentHandler.java | 12 +---- .../cpw/mods/modlauncher/DiscoveryData.java | 19 +++++++ .../cpw/mods/modlauncher/Environment.java | 21 +++++--- .../mods/modlauncher/LaunchPluginHandler.java | 2 +- .../modlauncher/LaunchServiceHandler.java | 12 +++-- .../java/cpw/mods/modlauncher/Launcher.java | 50 +++++++++++-------- .../mods/modlauncher/ModuleLayerHandler.java | 4 +- .../cpw/mods/modlauncher/TransformStore.java | 30 +++++++++-- .../modlauncher/TransformTargetLabel.java | 2 +- .../TransformationServiceDecorator.java | 22 ++------ .../TransformationServicesHandler.java | 14 +++--- src/main/resources/META-INF/MANIFEST.MF | 26 ---------- .../cpw.mods.modlauncher.resourceroot | 0 .../test/TransformingClassLoaderTests.java | 12 +++-- 15 files changed, 123 insertions(+), 106 deletions(-) create mode 100644 gradle/daemon-jvm.properties create mode 100644 src/main/java/cpw/mods/modlauncher/DiscoveryData.java delete mode 100644 src/main/resources/META-INF/MANIFEST.MF create mode 100644 src/main/resources/cpw.mods.modlauncher.resourceroot diff --git a/gradle/daemon-jvm.properties b/gradle/daemon-jvm.properties new file mode 100644 index 0000000..ebc8101 --- /dev/null +++ b/gradle/daemon-jvm.properties @@ -0,0 +1,3 @@ + +#This file is generated by updateDaemonJvm +toolchainVersion=21 diff --git a/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java b/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java index 3b2d735..0363c26 100644 --- a/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java +++ b/src/main/java/cpw/mods/modlauncher/ArgumentHandler.java @@ -28,7 +28,7 @@ import java.util.function.*; public class ArgumentHandler { - private String[] args; + private final String[] args; private OptionSet optionSet; private OptionSpec profileOption; private OptionSpec gameDirOption; @@ -37,16 +37,8 @@ public class ArgumentHandler { private OptionSpec launchTarget; private OptionSpec uuidOption; - record DiscoveryData(Path gameDir, String launchTarget, String[] arguments) {} - - DiscoveryData setArgs(String[] args) { + public ArgumentHandler(String[] args) { this.args = args; - final OptionParser parser = new OptionParser(); - final var gameDir = parser.accepts("gameDir", "Alternative game directory").withRequiredArg().withValuesConvertedBy(new PathConverter(PathProperties.DIRECTORY_EXISTING)).defaultsTo(Path.of(".")); - final var launchTarget = parser.accepts("launchTarget", "LauncherService target to launch").withRequiredArg(); - parser.allowsUnrecognizedOptions(); - final OptionSet optionSet = parser.parse(args); - return new DiscoveryData(optionSet.valueOf(gameDir), optionSet.valueOf(launchTarget), args); } void processArguments(Environment env, Consumer parserConsumer, BiConsumer> resultConsumer) { diff --git a/src/main/java/cpw/mods/modlauncher/DiscoveryData.java b/src/main/java/cpw/mods/modlauncher/DiscoveryData.java new file mode 100644 index 0000000..2b70701 --- /dev/null +++ b/src/main/java/cpw/mods/modlauncher/DiscoveryData.java @@ -0,0 +1,19 @@ +package cpw.mods.modlauncher; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.util.PathConverter; +import joptsimple.util.PathProperties; + +import java.nio.file.Path; + +public record DiscoveryData(Path gameDir, String launchTarget, String[] arguments) { + public static DiscoveryData create(String[] programArgs) { + final OptionParser parser = new OptionParser(); + final var gameDir = parser.accepts("gameDir", "Alternative game directory").withRequiredArg().withValuesConvertedBy(new PathConverter(PathProperties.DIRECTORY_EXISTING)).defaultsTo(Path.of(".")); + final var launchTarget = parser.accepts("launchTarget", "LauncherService target to launch").withRequiredArg(); + parser.allowsUnrecognizedOptions(); + final OptionSet optionSet = parser.parse(programArgs); + return new DiscoveryData(optionSet.valueOf(gameDir), optionSet.valueOf(launchTarget), programArgs); + } +} diff --git a/src/main/java/cpw/mods/modlauncher/Environment.java b/src/main/java/cpw/mods/modlauncher/Environment.java index 1c09e34..b4310d1 100644 --- a/src/main/java/cpw/mods/modlauncher/Environment.java +++ b/src/main/java/cpw/mods/modlauncher/Environment.java @@ -28,12 +28,17 @@ * Environment implementation class */ public final class Environment implements IEnvironment { - private final TypesafeMap environment; - private final Launcher launcher; + private final TypesafeMap environment = new TypesafeMap(IEnvironment.class); + private final Function> launchPlugins; + private final Function> launchService; + private final IModuleLayerManager moduleLayerHandler; - Environment(Launcher launcher) { - environment = new TypesafeMap(IEnvironment.class); - this.launcher = launcher; + public Environment(Function> launchPlugins, + Function> launchService, + IModuleLayerManager moduleLayerHandler) { + this.launchPlugins = launchPlugins; + this.launchService = launchService; + this.moduleLayerHandler = moduleLayerHandler; } @Override @@ -43,17 +48,17 @@ public final Optional getProperty(TypesafeMap.Key key) { @Override public Optional findLaunchPlugin(final String name) { - return launcher.findLaunchPlugin(name); + return launchPlugins.apply(name); } @Override public Optional findLaunchHandler(final String name) { - return launcher.findLaunchHandler(name); + return launchService.apply(name); } @Override public Optional findModuleLayerManager() { - return launcher.findLayerManager(); + return Optional.of(this.moduleLayerHandler); } @Override diff --git a/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java b/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java index f395314..0f724c0 100644 --- a/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java +++ b/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java @@ -83,7 +83,7 @@ public EnumMap> computeLa return phaseObjectEnumMap; } - void offerScanResultsToPlugins(List scanResults) { + public void offerScanResultsToPlugins(List scanResults) { plugins.forEach((n,p)->p.addResources(scanResults)); } diff --git a/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java b/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java index 00c882e..47c63cc 100644 --- a/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java +++ b/src/main/java/cpw/mods/modlauncher/LaunchServiceHandler.java @@ -31,12 +31,16 @@ /** * Identifies the launch target and dispatches to it */ -class LaunchServiceHandler { +public class LaunchServiceHandler { private static final Logger LOGGER = LogManager.getLogger(); private final Map launchHandlerLookup; public LaunchServiceHandler(final ModuleLayerHandler layerHandler) { - this.launchHandlerLookup = ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(layerHandler.getLayer(IModuleLayerManager.Layer.BOOT).orElseThrow(), ILaunchHandlerService.class), sce -> LOGGER.fatal("Encountered serious error loading transformation service, expect problems", sce)) + this(ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(layerHandler.getLayer(IModuleLayerManager.Layer.BOOT).orElseThrow(), ILaunchHandlerService.class), sce -> LOGGER.fatal("Encountered serious error loading transformation service, expect problems", sce))); + } + + public LaunchServiceHandler(Stream launchHandlers) { + this.launchHandlerLookup = launchHandlers .collect(Collectors.toMap(ILaunchHandlerService::name, LaunchServiceHandlerDecorator::new)); LOGGER.debug(MODLAUNCHER,"Found launch services [{}]", () -> String.join(",",launchHandlerLookup.keySet())); } @@ -45,7 +49,7 @@ public Optional findLaunchHandler(final String name) { return Optional.ofNullable(launchHandlerLookup.getOrDefault(name, null)).map(LaunchServiceHandlerDecorator::service); } - private void launch(String target, String[] arguments, ModuleLayer gameLayer, TransformingClassLoader classLoader, final LaunchPluginHandler launchPluginHandler) { + public void launch(String target, String[] arguments, ModuleLayer gameLayer, TransformingClassLoader classLoader, final LaunchPluginHandler launchPluginHandler) { final LaunchServiceHandlerDecorator launchServiceHandlerDecorator = launchHandlerLookup.get(target); final NamedPath[] paths = launchServiceHandlerDecorator.service().getPaths(); launchPluginHandler.announceLaunch(classLoader, paths); @@ -71,7 +75,7 @@ public void launch(ArgumentHandler argumentHandler, ModuleLayer gameLayer, Trans launch(launchTarget, args, gameLayer, classLoader, launchPluginHandler); } - void validateLaunchTarget(final ArgumentHandler argumentHandler) { + public void validateLaunchTarget(final ArgumentHandler argumentHandler) { if (!launchHandlerLookup.containsKey(argumentHandler.getLaunchTarget())) { LOGGER.error(MODLAUNCHER, "Cannot find launch target {}, unable to launch", argumentHandler.getLaunchTarget()); diff --git a/src/main/java/cpw/mods/modlauncher/Launcher.java b/src/main/java/cpw/mods/modlauncher/Launcher.java index a247d65..4828957 100644 --- a/src/main/java/cpw/mods/modlauncher/Launcher.java +++ b/src/main/java/cpw/mods/modlauncher/Launcher.java @@ -21,7 +21,6 @@ import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.*; import org.apache.logging.log4j.LogManager; -import cpw.mods.modlauncher.serviceapi.ILaunchPluginService; import java.util.*; import java.util.stream.Collectors; @@ -38,26 +37,43 @@ public class Launcher { private final TransformationServicesHandler transformationServicesHandler; private final Environment environment; private final TransformStore transformStore; - private final ArgumentHandler argumentHandler; private final LaunchServiceHandler launchService; private final LaunchPluginHandler launchPlugins; private final ModuleLayerHandler moduleLayerHandler; private TransformingClassLoader classLoader; + private ArgumentHandler argumentHandler; - private Launcher() { - INSTANCE = this; + public Launcher() { LogManager.getLogger().info(MODLAUNCHER,"ModLauncher {} starting: java version {} by {}; OS {} arch {} version {}", ()->IEnvironment.class.getPackage().getImplementationVersion(), () -> System.getProperty("java.version"), ()->System.getProperty("java.vendor"), ()->System.getProperty("os.name"), ()->System.getProperty("os.arch"), ()->System.getProperty("os.version")); this.moduleLayerHandler = new ModuleLayerHandler(); this.launchService = new LaunchServiceHandler(this.moduleLayerHandler); this.blackboard = new TypesafeMap(); - this.environment = new Environment(this); - environment.computePropertyIfAbsent(IEnvironment.Keys.MLSPEC_VERSION.get(), s->IEnvironment.class.getPackage().getSpecificationVersion()); - environment.computePropertyIfAbsent(IEnvironment.Keys.MLIMPL_VERSION.get(), s->IEnvironment.class.getPackage().getImplementationVersion()); - environment.computePropertyIfAbsent(IEnvironment.Keys.MODLIST.get(), s->new ArrayList<>()); this.transformStore = new TransformStore(); this.transformationServicesHandler = new TransformationServicesHandler(this.transformStore, this.moduleLayerHandler); - this.argumentHandler = new ArgumentHandler(); this.launchPlugins = new LaunchPluginHandler(this.moduleLayerHandler); + this.environment = new Environment( + launchPlugins::get, + launchService::findLaunchHandler, + moduleLayerHandler + ); + environment.computePropertyIfAbsent(IEnvironment.Keys.MLSPEC_VERSION.get(), s->IEnvironment.class.getPackage().getSpecificationVersion()); + environment.computePropertyIfAbsent(IEnvironment.Keys.MLIMPL_VERSION.get(), s->IEnvironment.class.getPackage().getImplementationVersion()); + environment.computePropertyIfAbsent(IEnvironment.Keys.MODLIST.get(), s->new ArrayList<>()); + } + + public Launcher(TransformationServicesHandler transformationServicesHandler, + Environment environment, + TransformStore transformStore, + LaunchServiceHandler launchService, + LaunchPluginHandler launchPlugins, + ModuleLayerHandler moduleLayerHandler) { + this.blackboard = new TypesafeMap(); + this.transformationServicesHandler = transformationServicesHandler; + this.environment = environment; + this.transformStore = transformStore; + this.launchService = launchService; + this.launchPlugins = launchPlugins; + this.moduleLayerHandler = moduleLayerHandler; } public static void main(String... args) { @@ -71,7 +87,9 @@ public static void main(String... args) { } LogManager.getLogger().info(MODLAUNCHER,"ModLauncher running: args {}", () -> LaunchServiceHandler.hideAccessToken(args)); LogManager.getLogger().info(MODLAUNCHER, "JVM identified as {} {} {}", props.getProperty("java.vm.vendor"), props.getProperty("java.vm.name"), props.getProperty("java.vm.version")); - new Launcher().run(args); + var launcher = new Launcher(); + INSTANCE = launcher; + launcher.run(args); } public final TypesafeMap blackboard() { @@ -79,8 +97,8 @@ public final TypesafeMap blackboard() { } private void run(String... args) { - final ArgumentHandler.DiscoveryData discoveryData = this.argumentHandler.setArgs(args); - this.transformationServicesHandler.discoverServices(discoveryData); + this.argumentHandler = new ArgumentHandler(args); + this.transformationServicesHandler.discoverServices(DiscoveryData.create(args)); final var scanResults = this.transformationServicesHandler.initializeTransformationServices(this.argumentHandler, this.environment) .stream().collect(Collectors.groupingBy(ITransformationService.Resource::target)); scanResults.getOrDefault(IModuleLayerManager.Layer.PLUGIN, List.of()) @@ -107,14 +125,6 @@ public Environment environment() { return this.environment; } - Optional findLaunchPlugin(final String name) { - return launchPlugins.get(name); - } - - Optional findLaunchHandler(final String name) { - return launchService.findLaunchHandler(name); - } - public Optional findLayerManager() { return Optional.ofNullable(this.moduleLayerHandler); } diff --git a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java index 4bb7bfb..8e6bdd5 100644 --- a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java +++ b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java @@ -48,7 +48,7 @@ SecureJar build() { private final EnumMap> layers = new EnumMap<>(Layer.class); private final EnumMap completedLayers = new EnumMap<>(Layer.class); - ModuleLayerHandler() { + public ModuleLayerHandler() { ClassLoader classLoader = getClass().getClassLoader(); // Create a new ModuleClassLoader from the boot module layer if it doesn't exist already. // This allows us to launch without BootstrapLauncher. @@ -57,7 +57,7 @@ SecureJar build() { completedLayers.put(Layer.BOOT, new LayerInfo(getClass().getModule().getLayer(), cl)); } - void addToLayer(final Layer layer, final SecureJar jar) { + public void addToLayer(final Layer layer, final SecureJar jar) { if (completedLayers.containsKey(layer)) throw new IllegalStateException("Layer already populated"); layers.computeIfAbsent(layer, l->new ArrayList<>()).add(PathOrJar.from(jar)); } diff --git a/src/main/java/cpw/mods/modlauncher/TransformStore.java b/src/main/java/cpw/mods/modlauncher/TransformStore.java index fd52cb3..0608b2c 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformStore.java +++ b/src/main/java/cpw/mods/modlauncher/TransformStore.java @@ -24,6 +24,7 @@ import org.objectweb.asm.tree.*; import java.util.*; +import java.util.stream.Collectors; import static cpw.mods.modlauncher.LogMarkers.*; @@ -41,30 +42,49 @@ public TransformStore() { transformers.put(type, new TransformList<>(type.getNodeType())); } - List> getTransformersFor(String className, FieldNode field) { + public List> getTransformersFor(String className, FieldNode field) { TransformTargetLabel tl = new TransformTargetLabel(className, field.name); TransformList transformerlist = TargetType.FIELD.get(this.transformers); return transformerlist.getTransformersForLabel(tl); } - List> getTransformersFor(String className, MethodNode method) { + public List> getTransformersFor(String className, MethodNode method) { TransformTargetLabel tl = new TransformTargetLabel(className, method.name, method.desc); TransformList transformerlist = TargetType.METHOD.get(this.transformers); return transformerlist.getTransformersForLabel(tl); } - List> getTransformersFor(String className, TargetType classType) { + public List> getTransformersFor(String className, TargetType classType) { TransformTargetLabel tl = new TransformTargetLabel(className, classType); TransformList transformerlist = classType.get(this.transformers); return transformerlist.getTransformersForLabel(tl); } + public void addTransformer(ITransformer xform, ITransformationService owner) { + final TargetType targetType = xform.getTargetType(); + Objects.requireNonNull(targetType, "Transformer type must not be null"); + final Set> targets = xform.targets(); + if (!targets.isEmpty()) { + final Map, List> targetTypeListMap = targets.stream() + .map(TransformTargetLabel::new) + .collect(Collectors.groupingBy(TransformTargetLabel::getTargetType)); + if (targetTypeListMap.keySet().size() > 1 || !targetTypeListMap.containsKey(targetType)) { + LOGGER.error("Invalid target {} for transformer {}", targetType, xform); + throw new IllegalArgumentException("The transformer contains invalid targets"); + } + targetTypeListMap.values() + .stream() + .flatMap(Collection::stream) + .forEach(target -> addTransformer(target, xform, owner)); + } + } + @SuppressWarnings("unchecked") - void addTransformer(TransformTargetLabel targetLabel, ITransformer transformer, ITransformationService service) { + public void addTransformer(TransformTargetLabel targetLabel, ITransformer transformer, ITransformationService owner) { LOGGER.debug(MODLAUNCHER,"Adding transformer {} to {}", () -> transformer, () -> targetLabel); classNeedsTransforming.add(targetLabel.getClassName().getInternalName()); final TransformList transformList = (TransformList) this.transformers.get(targetLabel.getTargetType()); - transformList.addTransformer(targetLabel, new TransformerHolder<>(transformer, service)); + transformList.addTransformer(targetLabel, new TransformerHolder<>(transformer, owner)); } /** diff --git a/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java b/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java index df9ac70..109b16d 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java +++ b/src/main/java/cpw/mods/modlauncher/TransformTargetLabel.java @@ -74,7 +74,7 @@ public final Type getElementDescriptor() { return this.elementDescriptor; } - final TargetType getTargetType() { + public TargetType getTargetType() { return this.labelType; } diff --git a/src/main/java/cpw/mods/modlauncher/TransformationServiceDecorator.java b/src/main/java/cpw/mods/modlauncher/TransformationServiceDecorator.java index 404a51e..88f0f00 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformationServiceDecorator.java +++ b/src/main/java/cpw/mods/modlauncher/TransformationServiceDecorator.java @@ -24,7 +24,6 @@ import org.jetbrains.annotations.VisibleForTesting; import java.util.*; -import java.util.stream.*; import static cpw.mods.modlauncher.LogMarkers.*; @@ -67,24 +66,9 @@ public void gatherTransformers(TransformStore transformStore) { LOGGER.debug(MODLAUNCHER,"Initializing transformers for transformation service {}", this.service::name); final List> transformers = this.service.transformers(); Objects.requireNonNull(transformers, "The transformers list should not be null"); - transformers.forEach(xform -> { - final TargetType targetType = xform.getTargetType(); - Objects.requireNonNull(targetType, "Transformer type must not be null"); - final Set> targets = xform.targets(); - if (!targets.isEmpty()) { - final Map, List> targetTypeListMap = targets.stream() - .map(TransformTargetLabel::new) - .collect(Collectors.groupingBy(TransformTargetLabel::getTargetType)); - if (targetTypeListMap.keySet().size() > 1 || !targetTypeListMap.containsKey(targetType)) { - LOGGER.error(MODLAUNCHER,"Invalid target {} for transformer {}", targetType, xform); - throw new IllegalArgumentException("The transformer contains invalid targets"); - } - targetTypeListMap.values() - .stream() - .flatMap(Collection::stream) - .forEach(target -> transformStore.addTransformer(target, xform, service)); - } - }); + for (ITransformer xform : transformers) { + transformStore.addTransformer(xform, service); + } LOGGER.debug(MODLAUNCHER,"Initialized transformers for transformation service {}", this.service::name); } diff --git a/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java b/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java index 6b4209e..0379244 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java +++ b/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java @@ -31,18 +31,18 @@ import static cpw.mods.modlauncher.LogMarkers.*; -class TransformationServicesHandler { +public class TransformationServicesHandler { private static final Logger LOGGER = LogManager.getLogger(); private Map serviceLookup; private final TransformStore transformStore; private final ModuleLayerHandler layerHandler; - TransformationServicesHandler(TransformStore transformStore, ModuleLayerHandler layerHandler) { + public TransformationServicesHandler(TransformStore transformStore, ModuleLayerHandler layerHandler) { this.transformStore = transformStore; this.layerHandler = layerHandler; } - List initializeTransformationServices(ArgumentHandler argumentHandler, Environment environment) { + public List initializeTransformationServices(ArgumentHandler argumentHandler, Environment environment) { loadTransformationServices(environment); validateTransformationServices(); processArguments(argumentHandler, environment); @@ -50,7 +50,9 @@ List initializeTransformationServices(ArgumentH return runScanningTransformationServices(environment); } - TransformingClassLoader buildTransformingClassLoader(final LaunchPluginHandler pluginHandler, final Environment environment, final ModuleLayerHandler layerHandler) { + public TransformingClassLoader buildTransformingClassLoader(final LaunchPluginHandler pluginHandler, + final Environment environment, + final ModuleLayerHandler layerHandler) { final var layerInfo = layerHandler.buildLayer(IModuleLayerManager.Layer.GAME, (cf, parents)->new TransformingClassLoader(transformStore, pluginHandler, environment, cf, parents)); layerHandler.updateLayer(IModuleLayerManager.Layer.PLUGIN, li->li.cl().setFallbackClassLoader(layerInfo.cl())); return (TransformingClassLoader) layerInfo.cl(); @@ -74,7 +76,7 @@ private void offerArgumentResultsToServices(OptionSet optionSet, BiFunction service.argumentValues(resultHandler.apply(service.name(), optionSet))); } - void initialiseServiceTransformers() { + public void initialiseServiceTransformers() { LOGGER.debug(MODLAUNCHER,"Transformation services loading transformers"); serviceLookup.values().forEach(s -> s.gatherTransformers(transformStore)); @@ -110,7 +112,7 @@ private void loadTransformationServices(Environment environment) { serviceLookup.values().forEach(s -> s.onLoad(environment, serviceLookup.keySet())); } - void discoverServices(final ArgumentHandler.DiscoveryData discoveryData) { + public void discoverServices(final DiscoveryData discoveryData) { LOGGER.debug(MODLAUNCHER, "Discovering transformation services"); var bootLayer = layerHandler.getLayer(IModuleLayerManager.Layer.BOOT).orElseThrow(); var earlyDiscoveryServices = ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(bootLayer, ITransformerDiscoveryService.class), sce -> LOGGER.fatal(MODLAUNCHER, "Encountered serious error loading transformation discoverer, expect problems", sce)) diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF deleted file mode 100644 index 5a898d3..0000000 --- a/src/main/resources/META-INF/MANIFEST.MF +++ /dev/null @@ -1,26 +0,0 @@ -Manifest-Version: 1.0 - -Name: cpw/mods/modlauncher/api/ -Specification-Title: modlauncher -Specification-Vendor: forge -Specification-Version: 7.0 -Implementation-Title: modlauncher -Implementation-Version: 9.0.1+0+master.09c65e8 -Implementation-Vendor: forge -Implementation-Timestamp: 2021-06-09T01:29:30.431684967Z -Git-Commit: 09c65e8 -Git-Branch: master -Build-Number: 0 - -Name: cpw/mods/modlauncher/cpw.mods.modlauncher.serviceapi/ -Specification-Title: modlauncherserviceapi -Specification-Vendor: forge -Specification-Version: 7.0 -Implementation-Title: modlauncher -Implementation-Version: 9.0.1+0+master.09c65e8 -Implementation-Vendor: forge -Implementation-Timestamp: 2021-06-09T01:29:30.433729643Z -Git-Commit: 09c65e8 -Git-Branch: master -Build-Number: 0 - diff --git a/src/main/resources/cpw.mods.modlauncher.resourceroot b/src/main/resources/cpw.mods.modlauncher.resourceroot new file mode 100644 index 0000000..e69de29 diff --git a/src/test/java/cpw/mods/modlauncher/test/TransformingClassLoaderTests.java b/src/test/java/cpw/mods/modlauncher/test/TransformingClassLoaderTests.java index ac0d125..e55719d 100644 --- a/src/test/java/cpw/mods/modlauncher/test/TransformingClassLoaderTests.java +++ b/src/test/java/cpw/mods/modlauncher/test/TransformingClassLoaderTests.java @@ -33,6 +33,7 @@ import java.lang.reflect.Constructor; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -56,16 +57,19 @@ public List> transformers() { }; TransformStore transformStore = new TransformStore(); - ModuleLayerHandler layerHandler = Whitebox.invokeConstructor(ModuleLayerHandler.class); + ModuleLayerHandler layerHandler = new ModuleLayerHandler(); LaunchPluginHandler lph = new LaunchPluginHandler(layerHandler); TransformationServiceDecorator sd = Whitebox.invokeConstructor(TransformationServiceDecorator.class, mockTransformerService); sd.gatherTransformers(transformStore); - Environment environment = Whitebox.invokeConstructor(Environment.class, new Class[]{ Launcher.class }, new Object[]{ null }); + Environment environment = new Environment( + s -> Optional.empty(), + s -> Optional.empty(), + layerHandler + ); new TypesafeMap(IEnvironment.class); - Constructor constructor = Whitebox.getConstructor(TransformingClassLoader.class, TransformStore.class, LaunchPluginHandler.class, Environment.class, Configuration.class, List.class); Configuration configuration = createTestJarsConfiguration(); - TransformingClassLoader tcl = constructor.newInstance(transformStore, lph, environment, configuration, List.of(ModuleLayer.boot())); + TransformingClassLoader tcl = new TransformingClassLoader(transformStore, lph, environment, configuration, List.of(ModuleLayer.boot())); ModuleLayer.boot().defineModules(configuration, s -> tcl); final Class aClass = Class.forName(TARGET_CLASS, true, tcl); From 76e81df1d2322fafebdc88f039da27da132bc1b7 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Wed, 3 Jul 2024 18:20:08 +0200 Subject: [PATCH 3/6] Working on generalized run configuration plugin. --- build.gradle | 2 +- settings.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 41bcfe9..aa7259e 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java-library' id 'eclipse' id 'com.github.ben-manes.versions' version '0.48.0' - id 'net.neoforged.gradleutils' version '3.0.0-alpha.4' + id 'net.neoforged.gradleutils' version '3.0.0' id 'org.gradlex.extra-java-module-info' version '1.4.2' id 'maven-publish' } diff --git a/settings.gradle b/settings.gradle index 08664b0..7c8cbff 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.6.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } rootProject.name = "modlauncher" \ No newline at end of file From b00145552f9eea1853139b178a1769f4adcdd0d6 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Sun, 7 Jul 2024 23:10:56 +0200 Subject: [PATCH 4/6] Be less crashy when run through tests --- src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java index 8e6bdd5..a83f33a 100644 --- a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java +++ b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java @@ -31,7 +31,7 @@ import java.util.function.Consumer; public final class ModuleLayerHandler implements IModuleLayerManager { - record LayerInfo(ModuleLayer layer, ModuleClassLoader cl) {} + public record LayerInfo(ModuleLayer layer, ModuleClassLoader cl) {} private record PathOrJar(NamedPath path, SecureJar jar) { static PathOrJar from(SecureJar jar) { @@ -54,7 +54,8 @@ public ModuleLayerHandler() { // This allows us to launch without BootstrapLauncher. ModuleClassLoader cl = classLoader instanceof ModuleClassLoader moduleCl ? moduleCl : new ModuleClassLoader("BOOT", ModuleLayer.boot().configuration(), List.of()); - completedLayers.put(Layer.BOOT, new LayerInfo(getClass().getModule().getLayer(), cl)); + var ownLayer = Objects.requireNonNullElse(getClass().getModule().getLayer(), ModuleLayer.boot()); + completedLayers.put(Layer.BOOT, new LayerInfo(ownLayer, cl)); } public void addToLayer(final Layer layer, final SecureJar jar) { From 841022e16b4359d31d2d77de4340a570e16e6152 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Mon, 8 Jul 2024 03:15:44 +0200 Subject: [PATCH 5/6] Mixins work --- .../mods/modlauncher/LaunchPluginHandler.java | 2 +- .../TransformationServicesHandler.java | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java b/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java index 0f724c0..cb0cff7 100644 --- a/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java +++ b/src/main/java/cpw/mods/modlauncher/LaunchPluginHandler.java @@ -102,7 +102,7 @@ int offerClassNodeToPlugins(final ILaunchPluginService.Phase phase, final Listp.initializeLaunch((s->transformerLoader.buildTransformedClassNodeFor(s, k)), specialPaths)); } } diff --git a/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java b/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java index 0379244..ed7be6a 100644 --- a/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java +++ b/src/main/java/cpw/mods/modlauncher/TransformationServicesHandler.java @@ -42,6 +42,12 @@ public TransformationServicesHandler(TransformStore transformStore, ModuleLayerH this.layerHandler = layerHandler; } + public TransformationServicesHandler(TransformStore transformStore, ModuleLayerHandler layerHandler, Environment environment, Collection services) { + this.transformStore = transformStore; + this.layerHandler = layerHandler; + setTransformationServices(services, environment); + } + public List initializeTransformationServices(ArgumentHandler argumentHandler, Environment environment) { loadTransformationServices(environment); validateTransformationServices(); @@ -125,14 +131,18 @@ public void discoverServices(final DiscoveryData discoveryData) { additionalPaths.forEach(np->layerHandler.addToLayer(IModuleLayerManager.Layer.SERVICE, np)); var serviceLayer = layerHandler.buildLayer(IModuleLayerManager.Layer.SERVICE); earlyDiscoveryServices.forEach(s->s.earlyInitialization(discoveryData.launchTarget(), discoveryData.arguments())); - serviceLookup = ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(serviceLayer.layer(), ITransformationService.class), sce -> LOGGER.fatal(MODLAUNCHER, "Encountered serious error loading transformation service, expect problems", sce)) - .collect(Collectors.toMap(ITransformationService::name, TransformationServiceDecorator::new)); + setTransformationServices(ServiceLoaderUtils.streamServiceLoader(()->ServiceLoader.load(serviceLayer.layer(), ITransformationService.class), sce -> LOGGER.fatal(MODLAUNCHER, "Encountered serious error loading transformation service, expect problems", sce)) + .toList(), Launcher.INSTANCE.environment()); + } + + private void setTransformationServices(Collection services, Environment environment) { + serviceLookup = services.stream().collect(Collectors.toMap(ITransformationService::name, TransformationServiceDecorator::new)); var modlist = serviceLookup.entrySet().stream().map(e->Map.of( "name", e.getKey(), "type", "TRANSFORMATIONSERVICE", "file", ServiceLoaderUtils.fileNameFor(e.getValue().getClass()) )).toList(); - Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.MODLIST.get()).ifPresent(ml->ml.addAll(modlist)); + environment.getProperty(IEnvironment.Keys.MODLIST.get()).ifPresent(ml->ml.addAll(modlist)); LOGGER.debug(MODLAUNCHER,"Found transformer services : [{}]", () -> String.join(",",serviceLookup.keySet())); } From 735c8b4b99bfbc526a48e6d98d49b077390186e4 Mon Sep 17 00:00:00 2001 From: Sebastian Hartte Date: Tue, 17 Dec 2024 01:43:14 +0100 Subject: [PATCH 6/6] Fixes --- src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java index a83f33a..2275877 100644 --- a/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java +++ b/src/main/java/cpw/mods/modlauncher/ModuleLayerHandler.java @@ -23,6 +23,7 @@ import cpw.mods.jarhandling.SecureJar; import cpw.mods.modlauncher.api.IModuleLayerManager; import cpw.mods.modlauncher.api.NamedPath; +import org.jetbrains.annotations.Nullable; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; @@ -49,11 +50,15 @@ SecureJar build() { private final EnumMap completedLayers = new EnumMap<>(Layer.class); public ModuleLayerHandler() { + this(null); + } + + public ModuleLayerHandler(@Nullable ClassLoader parentLoader) { ClassLoader classLoader = getClass().getClassLoader(); // Create a new ModuleClassLoader from the boot module layer if it doesn't exist already. // This allows us to launch without BootstrapLauncher. ModuleClassLoader cl = classLoader instanceof ModuleClassLoader moduleCl ? moduleCl - : new ModuleClassLoader("BOOT", ModuleLayer.boot().configuration(), List.of()); + : new ModuleClassLoader("BOOT", ModuleLayer.boot().configuration(), List.of(), parentLoader); var ownLayer = Objects.requireNonNullElse(getClass().getModule().getLayer(), ModuleLayer.boot()); completedLayers.put(Layer.BOOT, new LayerInfo(ownLayer, cl)); }