Skip to content

Commit 7056517

Browse files
committed
Move plugin-spi implementation to common
1 parent 75458ad commit 7056517

20 files changed

Lines changed: 732 additions & 510 deletions

File tree

forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/PluginFileParser.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private static IModFileInfo parsePluginFileInfo(final IModFile iModFile) {
6868
final ModFile modFile = (ModFile) iModFile;
6969
AppLaunch.logger().debug("Considering plugin file candidate {}", modFile.getFilePath());
7070

71-
final Path metadataFile = modFile.findResource(PluginPlatformConstants.METADATA_FILE_LOCATION);
71+
final Path metadataFile = modFile.findResource(PluginPlatformConstants.METADATA_FILE_PATH);
7272
if (Files.notExists(metadataFile)) {
7373
AppLaunch.logger().debug("Plugin file '{}' is missing a 'sponge_plugins.json' metadata file in META-INF", modFile);
7474
return null;
@@ -109,7 +109,7 @@ private static boolean useModJarMetadata(final SecureJar jar) {
109109
if (data.findFile(PluginFileParser.MODULE_INFO).isPresent()) {
110110
return false;
111111
}
112-
return data.findFile(PluginFileParser.MODS_TOML).isPresent() || data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent();
112+
return data.findFile(PluginFileParser.MODS_TOML).isPresent() || data.findFile(PluginPlatformConstants.METADATA_FILE_PATH).isPresent();
113113
}
114114

115115
public static ModFile newModFile(final IModProvider provider, boolean allowUnknown, final Path... paths) {
@@ -125,7 +125,7 @@ public static ModFile newModFile(final IModProvider provider, boolean allowUnkno
125125
return modFile;
126126
}
127127

128-
if (data.findFile(PluginPlatformConstants.METADATA_FILE_LOCATION).isPresent()) {
128+
if (data.findFile(PluginPlatformConstants.METADATA_FILE_PATH).isPresent()) {
129129
ModFile modFile = new ModFile(jar, provider, PluginFileParser::parsePluginFileInfo, type == null ? "MOD" : type);
130130
mjm.setModFile(modFile);
131131
return modFile;

forge/src/applaunch/java/org/spongepowered/forge/applaunch/loading/moddiscovery/SpongeForgeModLocator.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,15 @@
2424
*/
2525
package org.spongepowered.forge.applaunch.loading.moddiscovery;
2626

27-
import com.google.common.collect.ImmutableMap;
28-
import cpw.mods.modlauncher.Environment;
29-
import cpw.mods.modlauncher.Launcher;
3027
import net.minecraftforge.fml.loading.FMLEnvironment;
3128
import net.minecraftforge.forgespi.locating.IModLocator;
3229
import org.apache.logging.log4j.LogManager;
3330
import org.apache.logging.log4j.Logger;
31+
import org.spongepowered.common.applaunch.AppLaunch;
32+
import org.spongepowered.common.applaunch.plugin.locator.LocatorHelper;
3433
import org.spongepowered.forge.applaunch.plugin.ForgePluginPlatform;
3534

3635
import java.io.File;
37-
import java.net.URI;
3836
import java.net.URL;
3937
import java.nio.file.FileSystem;
4038
import java.nio.file.FileSystems;
@@ -51,6 +49,8 @@ public final class SpongeForgeModLocator extends AbstractModProvider implements
5149

5250
@Override
5351
public List<ModFileOrException> scanMods() {
52+
// TODO inject plugin-spi candidates
53+
5454
if (!FMLEnvironment.production) {
5555
final List<ModFileOrException> resources = new ArrayList<>();
5656
final String resourcesProp = System.getProperty("sponge.resources");
@@ -74,10 +74,7 @@ public List<ModFileOrException> scanMods() {
7474
.filter(path -> path.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar"))
7575
.map(path -> {
7676
try {
77-
URI jij = new URI("jij:" + path.toAbsolutePath().toUri().getRawSchemeSpecificPart()).normalize();
78-
final Map<String, ?> env = ImmutableMap.of("packagePath", path);
79-
FileSystem jijFS = FileSystems.newFileSystem(jij, env);
80-
return jijFS.getPath("/"); // root of the archive to load
77+
return LocatorHelper.newJarInJar(path);
8178
} catch (Exception e) {
8279
throw new RuntimeException(e);
8380
}
@@ -96,7 +93,6 @@ public String name() {
9693

9794
@Override
9895
public void initArguments(Map<String, ?> arguments) {
99-
final Environment env = Launcher.INSTANCE.environment();
100-
ForgePluginPlatform.bootstrap(env);
96+
AppLaunch.bootstrap(ForgePluginPlatform::new);
10197
}
10298
}

forge/src/applaunch/java/org/spongepowered/forge/applaunch/plugin/ForgePluginPlatform.java

Lines changed: 22 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -24,68 +24,23 @@
2424
*/
2525
package org.spongepowered.forge.applaunch.plugin;
2626

27-
import cpw.mods.modlauncher.Environment;
27+
import cpw.mods.modlauncher.Launcher;
2828
import cpw.mods.modlauncher.api.IEnvironment;
2929
import net.minecraftforge.fml.loading.FMLPaths;
30-
import org.apache.logging.log4j.LogManager;
31-
import org.apache.logging.log4j.Logger;
32-
import org.spongepowered.common.applaunch.AppLaunch;
33-
import org.spongepowered.common.applaunch.config.LaunchConfig;
34-
import org.spongepowered.common.applaunch.config.TokenReplacement;
30+
import org.checkerframework.checker.nullness.qual.Nullable;
3531
import org.spongepowered.common.applaunch.plugin.PluginPlatform;
32+
import org.spongepowered.common.applaunch.plugin.ResourceType;
33+
import org.spongepowered.forge.applaunch.plugin.resource.SecureJarPluginResource;
34+
import org.spongepowered.plugin.builtin.jvm.JVMPluginResource;
3635

37-
import java.io.IOException;
38-
import java.nio.file.Files;
3936
import java.nio.file.Path;
40-
import java.util.List;
37+
import java.util.jar.Attributes;
4138

42-
public final class ForgePluginPlatform implements PluginPlatform {
43-
44-
private static volatile boolean bootstrapped;
45-
46-
private final Environment environment;
47-
private final Logger logger;
48-
private final LaunchConfig config;
49-
private final TokenReplacement tokens;
50-
private final List<Path> pluginDirectories;
51-
52-
public static synchronized void bootstrap(final Environment environment) {
53-
if (ForgePluginPlatform.bootstrapped) {
54-
return;
55-
}
56-
ForgePluginPlatform.bootstrapped = true;
57-
final ForgePluginPlatform platform;
58-
try {
59-
platform = new ForgePluginPlatform(environment);
60-
} catch (final IOException e) {
61-
throw new RuntimeException(e);
62-
}
63-
AppLaunch.setPluginPlatform(platform);
64-
}
65-
66-
private ForgePluginPlatform(final Environment environment) throws IOException {
67-
this.environment = environment;
68-
this.logger = LogManager.getLogger("plugin");
69-
this.config = LaunchConfig.load(this.baseDirectory(), true);
70-
71-
this.tokens = new TokenReplacement();
72-
this.tokens.register("BASE_DIR", this.baseDirectory());
73-
this.tokens.register("CONFIG_DIR", this.configDirectory());
74-
this.tokens.register("MODS_DIR", FMLPaths.MODSDIR.get());
75-
76-
final Path additionalPluginsDirectory = Path.of(this.tokens.replace(this.config.additionalPluginsDirectory()));
77-
Files.createDirectories(additionalPluginsDirectory);
78-
this.pluginDirectories = List.of(FMLPaths.MODSDIR.get(), additionalPluginsDirectory);
79-
}
39+
public final class ForgePluginPlatform extends PluginPlatform {
8040

8141
@Override
8242
public String version() {
83-
return this.environment.getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev");
84-
}
85-
86-
@Override
87-
public Logger logger() {
88-
return this.logger;
43+
return Launcher.INSTANCE.environment().getProperty(IEnvironment.Keys.VERSION.get()).orElse("dev");
8944
}
9045

9146
@Override
@@ -104,17 +59,25 @@ public Path configDirectory() {
10459
}
10560

10661
@Override
107-
public LaunchConfig config() {
108-
return this.config;
62+
public Path modsDirectory() {
63+
return FMLPaths.MODSDIR.get();
10964
}
11065

11166
@Override
112-
public TokenReplacement tokens() {
113-
return this.tokens;
67+
public JVMPluginResource create(String locator, Path[] paths) {
68+
return new SecureJarPluginResource(this, locator, paths);
11469
}
11570

11671
@Override
117-
public List<Path> pluginDirectories() {
118-
return this.pluginDirectories;
72+
protected @Nullable ResourceType identifyResourceType(final Attributes attributes) {
73+
@Nullable ResourceType type = super.identifyResourceType(attributes);
74+
if (type != null) {
75+
return type;
76+
}
77+
return switch (attributes.getValue("FMLModType")) {
78+
case "MOD", "GAMELIBRARY" -> ResourceType.PLUGIN;
79+
case "LANGPROVIDER", "LIBRARY" -> ResourceType.LANGUAGE;
80+
case null, default -> null;
81+
};
11982
}
12083
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* This file is part of Sponge, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) SpongePowered <https://www.spongepowered.org>
5+
* Copyright (c) contributors
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package org.spongepowered.forge.applaunch.plugin.resource;
26+
27+
import cpw.mods.jarhandling.JarMetadata;
28+
import cpw.mods.jarhandling.SecureJar;
29+
import org.checkerframework.checker.nullness.qual.Nullable;
30+
import org.spongepowered.plugin.metadata.PluginMetadata;
31+
32+
import java.lang.module.ModuleDescriptor;
33+
import java.nio.file.Files;
34+
import java.nio.file.Path;
35+
import java.util.Arrays;
36+
37+
public class PluginJarMetadata implements JarMetadata {
38+
private final SecureJar jar;
39+
private final Path[] paths;
40+
41+
private boolean initialized = false;
42+
private ModuleDescriptor descriptor;
43+
44+
public PluginJarMetadata(final SecureJar jar, final Path[] paths) {
45+
this.jar = jar;
46+
this.paths = paths;
47+
}
48+
49+
public void init(final PluginMetadata plugin) {
50+
if (this.initialized) {
51+
return;
52+
}
53+
this.initialized = true;
54+
if (plugin == null) {
55+
if (this.jar.moduleDataProvider().findFile("module-info.class").isEmpty()
56+
&& Arrays.stream(this.paths).allMatch(Files::isDirectory)) {
57+
this.descriptor = PluginJarMetadata.createDescriptor(this.jar, this.jar.getPackages()
58+
.stream()
59+
.sorted()
60+
.findFirst()
61+
.orElseThrow(), null);
62+
} else {
63+
this.descriptor = JarMetadata.from(this.jar, this.paths).descriptor();
64+
}
65+
} else {
66+
this.descriptor = PluginJarMetadata.createDescriptor(this.jar, plugin.id().replace('-', '_'), plugin.version().toString());
67+
}
68+
}
69+
70+
private void checkInitialized() {
71+
if (!this.initialized) {
72+
throw new IllegalStateException("Metadata not initialized");
73+
}
74+
}
75+
76+
@Override
77+
public String name() {
78+
this.checkInitialized();
79+
return this.descriptor.name();
80+
}
81+
82+
@Override
83+
public String version() {
84+
this.checkInitialized();
85+
return this.descriptor.rawVersion().orElse(null);
86+
}
87+
88+
@Override
89+
public ModuleDescriptor descriptor() {
90+
this.checkInitialized();
91+
return this.descriptor;
92+
}
93+
94+
private static ModuleDescriptor createDescriptor(final SecureJar jar, final String name, final @Nullable String version) {
95+
final ModuleDescriptor.Builder builder = ModuleDescriptor.newAutomaticModule(name)
96+
.packages(jar.getPackages());
97+
if (version != null) {
98+
builder.version(version);
99+
}
100+
jar.getProviders().stream()
101+
.filter(p -> !p.providers().isEmpty())
102+
.forEach(p -> builder.provides(p.serviceName(), p.providers()));
103+
return builder.build();
104+
}
105+
}

0 commit comments

Comments
 (0)