com.mycila.plugin.spi.DefaultPluginResolver Maven / Gradle / Ivy
/**
* Copyright (C) 2008 Mathieu Carbou
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mycila.plugin.spi;
import com.mycila.log.Logger;
import com.mycila.log.Loggers;
import com.mycila.plugin.api.CyclicDependencyException;
import com.mycila.plugin.api.InexistingPluginException;
import com.mycila.plugin.api.Plugin;
import com.mycila.plugin.api.PluginBinding;
import com.mycila.plugin.api.PluginCache;
import com.mycila.plugin.api.PluginResolver;
import static com.mycila.plugin.spi.Ensure.*;
import org.jgrapht.DirectedGraph;
import org.jgrapht.alg.CycleDetector;
import org.jgrapht.graph.DefaultDirectedWeightedGraph;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.traverse.TopologicalOrderIterator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* @author Mathieu Carbou ([email protected])
*/
final class DefaultPluginResolver implements PluginResolver {
private static final Logger LOGGER = Loggers.get(DefaultPluginResolver.class);
final PluginCache cache;
DefaultPluginResolver(PluginCache cache) {
notNull("Plugin cache", cache);
this.cache = cache;
}
public SortedSet> getPlugins() {
return Collections.unmodifiableSortedSet(new TreeSet>(cache.getBindings().values()));
}
public T getPlugin(String name) {
notNull("Plugin name", name);
PluginBinding binding = cache.getBindings().get(name);
if (binding == null) {
throw new InexistingPluginException(name);
}
return binding.getPlugin();
}
public boolean contains(String name) {
notNull("Plugin name", name);
return cache.contains(name);
}
public SortedMap> getMissingDependenciesByPlugin() {
SortedMap> allMiss = new TreeMap>();
Collection> plugins = cache.getBindings().values();
Set loadedPlugins = new HashSet(plugins.size());
for (PluginBinding plugin : plugins) {
loadedPlugins.add(plugin.getName());
}
for (PluginBinding binding : plugins) {
SortedSet pluginDependencies = new TreeSet();
if (binding.getPlugin().getBefore() != null) {
for (String dep : binding.getPlugin().getBefore()) {
if (!isEmpty(dep)) {
pluginDependencies.add(dep);
}
}
}
if (binding.getPlugin().getAfter() != null) {
for (String dep : binding.getPlugin().getAfter()) {
if (!isEmpty(dep)) {
pluginDependencies.add(dep);
}
}
}
pluginDependencies.removeAll(loadedPlugins);
if (!pluginDependencies.isEmpty()) {
allMiss.put(binding.getName(), Collections.unmodifiableSortedSet(pluginDependencies));
}
}
return Collections.unmodifiableSortedMap(allMiss);
}
public SortedSet getMissingDependencies() {
SortedMap> allMiss = getMissingDependenciesByPlugin();
SortedSet misses = new TreeSet();
for (SortedSet plugins : allMiss.values()) {
misses.addAll(plugins);
}
return Collections.unmodifiableSortedSet(misses);
}
public List> getResolvedPlugins() {
List names = getResolvedPluginsName();
List> plugins = new ArrayList>(names.size());
for (String name : names) {
plugins.add(cache.getBindings().get(name));
}
return Collections.unmodifiableList(plugins);
}
public List getResolvedPluginsName() {
SortedSet missingPlugins = getMissingDependencies();
DirectedGraph graph = new DefaultDirectedWeightedGraph(DefaultEdge.class);
for (PluginBinding binding : cache.getBindings().values()) {
graph.addVertex(binding.getName());
if (binding.getPlugin().getBefore() != null) {
for (String before : binding.getPlugin().getBefore()) {
if (!isEmpty(before) && !missingPlugins.contains(before)) {
graph.addVertex(before);
graph.addEdge(before, binding.getName());
}
}
}
if (binding.getPlugin().getAfter() != null) {
for (String after : binding.getPlugin().getAfter()) {
if (!isEmpty(after) && !missingPlugins.contains(after)) {
graph.addVertex(after);
graph.addEdge(binding.getName(), after);
}
}
}
}
if (graph.vertexSet().size() == 0) {
return Collections.emptyList();
}
CycleDetector detector = new CycleDetector(graph);
if (detector.detectCycles()) {
SortedMap cyclics = new TreeMap();
for (String pluginName : detector.findCycles()) {
cyclics.put(pluginName, getPlugin(pluginName));
}
throw new CyclicDependencyException(cyclics);
}
List order = new ArrayList();
Iterator it = new TopologicalOrderIterator(graph);
while (it.hasNext()) {
order.add(it.next());
}
LOGGER.debug("Resolved plugins: {0}", order);
return Collections.unmodifiableList(order);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy