Skip to content

Commit

Permalink
Revamp hk2 injection to support injection in dependent plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
benwoo1110 committed Sep 15, 2024
1 parent 64584cc commit c3674e0
Show file tree
Hide file tree
Showing 15 changed files with 313 additions and 211 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ dependencies {
// Utils
shadowed 'io.vavr:vavr:0.10.4'
shadowed 'org.glassfish.hk2:hk2-locator:3.0.3'
shadowed('org.glassfish.hk2:hk2-inhabitant-generator:3.0.3') {
exclude group: 'org.apache.maven', module: 'maven-core'
}
shadowed('com.dumptruckman.minecraft:Logging:1.1.1') {
exclude group: 'junit', module: 'junit'
}
Expand Down
98 changes: 36 additions & 62 deletions src/main/java/org/mvplugins/multiverse/core/MultiverseCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
package org.mvplugins.multiverse.core;

import java.io.File;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import com.dumptruckman.minecraft.util.Logging;
import io.vavr.control.Try;
Expand All @@ -20,13 +18,10 @@
import me.main__.util.SerializationConfig.SerializationConfig;
import org.bukkit.configuration.serialization.ConfigurationSerialization;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.plugin.java.JavaPluginLoader;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.ServiceHandle;
import org.glassfish.hk2.api.ServiceLocator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jvnet.hk2.annotations.Service;

import org.mvplugins.multiverse.core.anchor.AnchorManager;
Expand All @@ -39,7 +34,8 @@
import org.mvplugins.multiverse.core.destination.DestinationsProvider;
import org.mvplugins.multiverse.core.economy.MVEconomist;
import org.mvplugins.multiverse.core.inject.InjectableListener;
import org.mvplugins.multiverse.core.inject.PluginInjection;
import org.mvplugins.multiverse.core.inject.PluginServiceLocator;
import org.mvplugins.multiverse.core.inject.PluginServiceLocatorFactory;
import org.mvplugins.multiverse.core.placeholders.MultiverseCorePlaceholders;
import org.mvplugins.multiverse.core.utils.TestingMode;
import org.mvplugins.multiverse.core.utils.metrics.MetricsConfigurator;
Expand All @@ -54,7 +50,9 @@
public class MultiverseCore extends JavaPlugin implements MVCore {
private static final int PROTOCOL = 50;

private ServiceLocator serviceLocator;
private PluginServiceLocatorFactory serviceLocatorFactory;
private PluginServiceLocator serviceLocator;

@Inject
private Provider<MVCoreConfig> configProvider;
@Inject
Expand Down Expand Up @@ -150,22 +148,26 @@ public void onDisable() {
}

private void initializeDependencyInjection() {
serviceLocator = PluginInjection.createServiceLocator(new MultiverseCorePluginBinder(this))
.andThenTry(locator -> {
PluginInjection.enable(this, locator);
})
serviceLocatorFactory = new PluginServiceLocatorFactory();
serviceLocator = serviceLocatorFactory.init()
.flatMap(ignore -> serviceLocatorFactory.registerPlugin(new MultiverseCorePluginBinder(this)))
.flatMap(PluginServiceLocator::enable)
.getOrElseThrow(exception -> {
Logging.severe("Failed to initialize dependency injection");
Logging.severe("Failed to initialize dependency injection!");
getServer().getPluginManager().disablePlugin(this);
return new RuntimeException(exception);
});
}

private void shutdownDependencyInjection() {
if (serviceLocator != null) {
PluginInjection.disable(this, serviceLocator);
serviceLocator.disable();
serviceLocator = null;
}
if (serviceLocatorFactory != null) {
serviceLocatorFactory.shutdown();
serviceLocatorFactory = null;
}
}

private boolean shouldShowConfig() {
Expand Down Expand Up @@ -207,10 +209,8 @@ private void registerEvents() {
*/
private void registerCommands() {
Try.of(() -> commandManagerProvider.get())
.andThenTry(commandManager -> {
serviceLocator.getAllServices(MultiverseCommand.class)
.forEach(commandManager::registerCommand);
})
.andThenTry(commandManager -> serviceLocator.getAllServices(MultiverseCommand.class)
.forEach(commandManager::registerCommand))
.onFailure(e -> {
Logging.severe("Failed to register commands");
e.printStackTrace();
Expand All @@ -222,9 +222,7 @@ private void registerCommands() {
*/
private void setUpLocales() {
Try.of(() -> commandManagerProvider.get())
.andThen(commandManager -> {
commandManager.usePerIssuerLocale(true, true);
})
.andThen(commandManager -> commandManager.usePerIssuerLocale(true, true))
.mapTry(commandManager -> pluginLocalesProvider.get())
.andThen(pluginLocales -> {
pluginLocales.addFileResClassLoader(this);
Expand Down Expand Up @@ -282,7 +280,7 @@ private void logEnableMessage() {
private void loadPlaceholderApiIntegration() {
if (configProvider.get().isRegisterPapiHook()
&& getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) {
Try.run(() -> serviceLocator.createAndInitialize(MultiverseCorePlaceholders.class))
Try.run(() -> serviceLocator.getService(MultiverseCorePlaceholders.class))
.onFailure(e -> {
Logging.severe("Failed to load PlaceholderAPI integration.");
e.printStackTrace();
Expand Down Expand Up @@ -330,6 +328,22 @@ public String getAuthors() {
return authors.toString();
}

/**
* {@inheritDoc}
*/
@Override
public PluginServiceLocatorFactory getServiceLocatorFactory() {
return serviceLocatorFactory;
}

/**
* {@inheritDoc}
*/
@Override
public PluginServiceLocator getServiceLocator() {
return serviceLocator;
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -371,46 +385,6 @@ public boolean saveAllConfigs() {
&& anchorManagerProvider.get().saveAnchors();
}

/**
* Gets the best service from this plugin that implements the given contract or has the given implementation.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return An instance of the contract or impl if it is a service and is already instantiated, null otherwise
* @throws MultiException if there was an error during service lookup
*/
@Nullable
public <T> T getService(@NotNull Class<T> contractOrImpl, Annotation... qualifiers) throws MultiException {
var handle = serviceLocator.getServiceHandle(contractOrImpl, qualifiers);
if (handle != null && handle.isActive()) {
return handle.getService();
}
return null;
}

/**
* Gets all services from this plugin that implement the given contract or have the given implementation and have
* the provided qualifiers.
*
* @param contractOrImpl The contract or concrete implementation to get the best instance of
* @param qualifiers The set of qualifiers that must match this service definition
* @param <T> The type of the contract to get
* @return A list of services implementing this contract or concrete implementation. May not return null, but may
* return an empty list.
* @throws MultiException if there was an error during service lookup
*/
@NotNull
public <T> List<T> getAllServices(
@NotNull Class<T> contractOrImpl,
Annotation... qualifiers) throws MultiException {
var handles = serviceLocator.getAllServiceHandles(contractOrImpl, qualifiers);
return handles.stream()
.filter(ServiceHandle::isActive)
.map(ServiceHandle::getService)
.collect(Collectors.toList());
}

/**
* This is for unit testing ONLY. Do not use this constructor.
*
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/org/mvplugins/multiverse/core/api/MVCore.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@

package org.mvplugins.multiverse.core.api;

import org.mvplugins.multiverse.core.inject.PluginServiceLocator;
import org.mvplugins.multiverse.core.inject.PluginServiceLocatorFactory;

/**
* Multiverse 2 Core API
* <p>
* This API contains a bunch of useful things you can get out of Multiverse in general!
*/
public interface MVCore extends MVPlugin {

/**
* Gets the {@link PluginServiceLocatorFactory} used to create {@link PluginServiceLocator}s.
*
* @return The {@link PluginServiceLocatorFactory}
*/
PluginServiceLocatorFactory getServiceLocatorFactory();

/**
* Saves all configs.
*
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/org/mvplugins/multiverse/core/api/MVPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

package org.mvplugins.multiverse.core.api;

import org.mvplugins.multiverse.core.inject.PluginServiceLocator;

/**
* This interface is implemented by every official Multiverse-plugin.
*/
Expand All @@ -33,4 +35,11 @@ public interface MVPlugin {
* @return The readable authors-{@link String}
*/
String getAuthors();

/**
* Gets the {@link PluginServiceLocator} for this plugin.
*
* @return The {@link PluginServiceLocator}
*/
PluginServiceLocator getServiceLocator();
}

This file was deleted.

Loading

0 comments on commit c3674e0

Please sign in to comment.