use of org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform in project SpongeCommon by SpongePowered.
the class VanillaPluginManager method loadPlugins.
@SuppressWarnings("unchecked")
public void loadPlugins(final VanillaPluginPlatform platform) {
this.locatedResources.putAll(platform.getResources());
final Map<PluginCandidate<PluginResource>, PluginLanguageService<PluginResource>> pluginLanguageLookup = new HashMap<>();
final Map<PluginLanguageService<PluginResource>, PluginLoader<PluginResource, PluginContainer>> pluginLoaders = new HashMap<>();
// Initialise the plugin language loaders.
for (final Map.Entry<PluginLanguageService<PluginResource>, List<PluginCandidate<PluginResource>>> candidate : platform.getCandidates().entrySet()) {
final PluginLanguageService<PluginResource> languageService = candidate.getKey();
final String loaderClass = languageService.pluginLoader();
try {
pluginLoaders.put(languageService, (PluginLoader<PluginResource, PluginContainer>) Class.forName(loaderClass).getConstructor().newInstance());
} catch (final InstantiationException | IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException(e);
}
candidate.getValue().forEach(x -> pluginLanguageLookup.put(x, languageService));
}
// Priority to platform plugins that will already exist here -- meaning the resolver will act upon them first
// and if someone decides to give a plugin an ID that is the same as a platform plugin, the resolver will effectively
// reject it.
final Set<PluginCandidate<PluginResource>> resources = new LinkedHashSet<>();
pluginLanguageLookup.keySet().stream().filter(x -> this.plugins.containsKey(x.metadata().id())).forEach(resources::add);
resources.addAll(pluginLanguageLookup.keySet());
final ResolutionResult<PluginResource> resolutionResult = DependencyResolver.resolveAndSortCandidates(resources, platform.logger());
final Map<PluginCandidate<PluginResource>, String> failedInstances = new HashMap<>();
final Map<PluginCandidate<PluginResource>, String> consequentialFailedInstances = new HashMap<>();
final ClassLoader launchClassloader = VanillaLaunch.instance().getClass().getClassLoader();
for (final PluginCandidate<PluginResource> candidate : resolutionResult.sortedSuccesses()) {
final PluginContainer plugin = this.plugins.get(candidate.metadata().id());
if (plugin != null) {
if (plugin instanceof VanillaDummyPluginContainer) {
continue;
}
// If we get here, we screwed up - duplicate IDs should have been detected earlier.
// Place it in the resolution result... it'll then get picked up in the big error message
resolutionResult.duplicateIds().add(candidate.metadata().id());
// but this is our screw up, let's also make a big point of it
final PrettyPrinter prettyPrinter = new PrettyPrinter(120).add("ATTEMPTED TO CREATE PLUGIN WITH DUPLICATE PLUGIN ID").centre().hr().addWrapped("Sponge attempted to create a second plugin with ID '%s'. This is not allowed - all plugins must have a unique " + "ID. Usually, Sponge will catch this earlier -- but in this case Sponge has validated two plugins with " + "the same ID. Please report this error to Sponge.", candidate.metadata().id()).add().add("Technical Details:").add("Plugins to load:", 4);
resolutionResult.sortedSuccesses().forEach(x -> prettyPrinter.add("*" + x.metadata().id(), 4));
prettyPrinter.add().add("Detected Duplicate IDs:", 4);
resolutionResult.duplicateIds().forEach(x -> prettyPrinter.add("*" + x, 4));
prettyPrinter.log(platform.logger(), Level.ERROR);
continue;
}
// This should work fine, we're sorted so all deps should be in place at this stage.
if (this.stillValid(candidate, consequentialFailedInstances)) {
final PluginLanguageService<PluginResource> languageService = pluginLanguageLookup.get(candidate);
final PluginLoader<PluginResource, PluginContainer> pluginLoader = pluginLoaders.get(languageService);
try {
final PluginContainer container = pluginLoader.loadPlugin(platform.getStandardEnvironment(), candidate, launchClassloader);
this.addPlugin(container);
this.containerToResource.put(container, candidate.resource());
} catch (final InvalidPluginException e) {
failedInstances.put(candidate, "Failed to construct: see stacktrace(s) above this message for details.");
e.printStackTrace();
}
}
}
resolutionResult.printErrorsIfAny(failedInstances, consequentialFailedInstances, platform.logger());
platform.logger().info("Loaded plugin(s): {}", this.sortedPlugins.stream().map(p -> p.metadata().id()).collect(Collectors.toList()));
}
use of org.spongepowered.vanilla.applaunch.plugin.VanillaPluginPlatform in project SpongeCommon by SpongePowered.
the class AbstractVanillaLaunchHandler method configureTransformationClassLoader.
@Override
public void configureTransformationClassLoader(final ITransformingClassLoaderBuilder builder) {
// Specifically requested to be available on the launch loader
final VanillaPluginPlatform platform = AppLaunch.pluginPlatform();
for (final Path path : platform.getStandardEnvironment().blackboard().getOrCreate(VanillaPluginPlatform.EXTRA_TRANSFORMABLE_PATHS, () -> Collections.emptyList())) {
builder.addTransformationPath(path);
}
// todo: we might be able to eliminate this at some point, but that causes complications
for (final URL url : Java9ClassLoaderUtil.getSystemClassPathURLs()) {
try {
final URI uri = url.toURI();
if (!this.isTransformable(uri)) {
this.logger.debug("Non-transformable system classpath entry: {}", uri);
continue;
}
builder.addTransformationPath(Paths.get(uri));
this.logger.debug("Transformable system classpath entry: {}", uri);
} catch (final URISyntaxException | IOException ex) {
this.logger.error("Failed to add {} to transformation path", url, ex);
}
}
builder.setResourceEnumeratorLocator(this.getResourceLocator());
builder.setManifestLocator(this.getManifestLocator());
}
Aggregations