externalpluginmanager: Mimic PluginManager.scanAndInstantiate closer
This commit is contained in:
@@ -24,6 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins;
|
package net.runelite.client.plugins;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.graph.GraphBuilder;
|
||||||
|
import com.google.common.graph.Graphs;
|
||||||
|
import com.google.common.graph.MutableGraph;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import com.google.inject.Binder;
|
import com.google.inject.Binder;
|
||||||
import com.google.inject.CreationException;
|
import com.google.inject.CreationException;
|
||||||
@@ -400,9 +404,66 @@ public class ExternalPluginManager
|
|||||||
private void scanAndInstantiate(List<Plugin> plugins, boolean init, boolean initConfig)
|
private void scanAndInstantiate(List<Plugin> plugins, boolean init, boolean initConfig)
|
||||||
{
|
{
|
||||||
RuneLiteSplashScreen.stage(.66, "Loading external plugins");
|
RuneLiteSplashScreen.stage(.66, "Loading external plugins");
|
||||||
|
MutableGraph<Class<? extends Plugin>> graph = GraphBuilder
|
||||||
|
.directed()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
for (Plugin plugin : plugins)
|
||||||
|
{
|
||||||
|
Class<? extends Plugin> clazz = plugin.getClass();
|
||||||
|
PluginDescriptor pluginDescriptor = clazz.getAnnotation(PluginDescriptor.class);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (pluginDescriptor == null)
|
||||||
|
{
|
||||||
|
if (Plugin.class.isAssignableFrom(clazz))
|
||||||
|
{
|
||||||
|
log.warn("Class {} is a plugin, but has no plugin descriptor", clazz);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!Plugin.class.isAssignableFrom(clazz))
|
||||||
|
{
|
||||||
|
log.warn("Class {} has plugin descriptor, but is not a plugin", clazz);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (!pluginTypes.contains(pluginDescriptor.type()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (EnumConstantNotPresentException e)
|
||||||
|
{
|
||||||
|
log.warn("{} has an invalid plugin type of {}", clazz, e.getMessage());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") Class<Plugin> pluginClass = (Class<Plugin>) clazz;
|
||||||
|
graph.addNode(pluginClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build plugin graph
|
||||||
|
for (Class<? extends Plugin> pluginClazz : graph.nodes())
|
||||||
|
{
|
||||||
|
net.runelite.client.plugins.PluginDependency[] pluginDependencies = pluginClazz.getAnnotationsByType(net.runelite.client.plugins.PluginDependency.class);
|
||||||
|
|
||||||
|
for (net.runelite.client.plugins.PluginDependency pluginDependency : pluginDependencies)
|
||||||
|
{
|
||||||
|
graph.putEdge(pluginClazz, pluginDependency.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Graphs.hasCycle(graph))
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Plugin dependency graph contains a cycle!");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<List<Class<? extends Plugin>>> sortedPlugins = PluginManager.topologicalGroupSort(graph);
|
||||||
|
sortedPlugins = Lists.reverse(sortedPlugins);
|
||||||
AtomicInteger loaded = new AtomicInteger();
|
AtomicInteger loaded = new AtomicInteger();
|
||||||
List<Plugin> scannedPlugins = new CopyOnWriteArrayList<>();
|
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
|
||||||
// some plugins get stuck on IO, so add some extra threads
|
// some plugins get stuck on IO, so add some extra threads
|
||||||
ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2,
|
ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2,
|
||||||
@@ -412,57 +473,30 @@ public class ExternalPluginManager
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (Plugin plugin : plugins)
|
List<Plugin> scannedPlugins = new CopyOnWriteArrayList<>();
|
||||||
|
sortedPlugins.forEach(group ->
|
||||||
{
|
{
|
||||||
Class<? extends Plugin> clazz = plugin.getClass();
|
|
||||||
PluginDescriptor pluginDescriptor = clazz.getAnnotation(PluginDescriptor.class);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (pluginDescriptor == null)
|
|
||||||
{
|
|
||||||
if (Plugin.class.isAssignableFrom(clazz))
|
|
||||||
{
|
|
||||||
log.warn("Class {} is a plugin, but has no plugin descriptor", clazz);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (!Plugin.class.isAssignableFrom(clazz))
|
|
||||||
{
|
|
||||||
log.warn("Class {} has plugin descriptor, but is not a plugin", clazz);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if (!pluginTypes.contains(pluginDescriptor.type()))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (EnumConstantNotPresentException e)
|
|
||||||
{
|
|
||||||
log.warn("{} has an invalid plugin type of {}", clazz, e.getMessage());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Future<?>> curGroup = new ArrayList<>();
|
List<Future<?>> curGroup = new ArrayList<>();
|
||||||
curGroup.add(exec.submit(() ->
|
group.forEach(pluginClazz ->
|
||||||
{
|
curGroup.add(exec.submit(() ->
|
||||||
Plugin plugininst;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
//noinspection unchecked
|
Plugin plugininst;
|
||||||
plugininst = instantiate(scannedPlugins, (Class<Plugin>) plugin.getClass(), init, initConfig);
|
try
|
||||||
scannedPlugins.add(plugininst);
|
{
|
||||||
}
|
//noinspection unchecked
|
||||||
catch (PluginInstantiationException e)
|
plugininst = instantiate(scannedPlugins, (Class<Plugin>) pluginClazz, init, initConfig);
|
||||||
{
|
scannedPlugins.add(plugininst);
|
||||||
log.warn("Error instantiating plugin!", e);
|
}
|
||||||
return;
|
catch (PluginInstantiationException e)
|
||||||
}
|
{
|
||||||
|
log.warn("Error instantiating plugin!", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
loaded.getAndIncrement();
|
loaded.getAndIncrement();
|
||||||
|
|
||||||
RuneLiteSplashScreen.stage(.67, .75, "Loading external plugins", loaded.get(), scannedPlugins.size());
|
RuneLiteSplashScreen.stage(.67, .75, "Loading external plugins", loaded.get(), scannedPlugins.size());
|
||||||
}));
|
})));
|
||||||
curGroup.forEach(future ->
|
curGroup.forEach(future ->
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -474,7 +508,9 @@ public class ExternalPluginManager
|
|||||||
log.warn("Could not instantiate external plugin", e);
|
log.warn("Could not instantiate external plugin", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
|
log.info("External plugin instantiation took {}ms", System.currentTimeMillis() - start);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ public class PluginManager
|
|||||||
* @param <T>
|
* @param <T>
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private <T> List<List<T>> topologicalGroupSort(Graph<T> graph)
|
static <T> List<List<T>> topologicalGroupSort(Graph<T> graph)
|
||||||
{
|
{
|
||||||
final Set<T> root = graph.nodes().stream()
|
final Set<T> root = graph.nodes().stream()
|
||||||
.filter(node -> graph.inDegree(node) == 0)
|
.filter(node -> graph.inDegree(node) == 0)
|
||||||
@@ -696,7 +696,7 @@ public class PluginManager
|
|||||||
return dependencyGroups;
|
return dependencyGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void incrementChildren(Graph<T> graph, Map<T, Integer> dependencyCount, T n, int val)
|
private static <T> void incrementChildren(Graph<T> graph, Map<T, Integer> dependencyCount, T n, int val)
|
||||||
{
|
{
|
||||||
if (!dependencyCount.containsKey(n) || dependencyCount.get(n) < val)
|
if (!dependencyCount.containsKey(n) || dependencyCount.get(n) < val)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user