only deactivate plugins with cycle dependencies instead of failing to launch Jenkins

This commit is contained in:
imod committed 2012-02-19 18:29:53 +01:00
1 parent d0c9ee6588
commit aad6e4c66c
3 files changed
+68 -3

No files matched your search

@@ -28,10 +28,12 @@ import hudson.init.InitMilestone;
import hudson.init.InitStrategy;
import hudson.init.InitializerFinder;
import hudson.model.AbstractModelObject;
import hudson.model.AdministrativeMonitor;
import hudson.model.Descriptor;
import hudson.model.Failure;
import hudson.model.UpdateCenter;
import hudson.model.UpdateSite;
import hudson.model.UpdateSite.Data;
import hudson.util.CyclicGraphDetector;
import hudson.util.CyclicGraphDetector.CycleDetectedException;
import hudson.util.FormValidation;
@@ -243,6 +245,18 @@ public abstract class PluginManager extends AbstractModelObject {
r.add(p);
}
}
@Override
protected void reactOnCycle(PluginWrapper q, List<PluginWrapper> cycle)
throws hudson.util.CyclicGraphDetector.CycleDetectedException {
LOGGER.log(Level.SEVERE, "found cycle in plugin dependencies: (root="+q+", deactivating all involved) "+Util.join(cycle," -> "));
for (PluginWrapper pluginWrapper : cycle) {
pluginWrapper.setHasCycleDependency(true);
failedPlugins.add(new FailedPlugin(pluginWrapper.getShortName(), new CycleDetectedException(cycle)));
}
}
};
cgd.run(getPlugins());
@@ -810,4 +824,32 @@ public abstract class PluginManager extends AbstractModelObject {
/*package*/ static final class PluginInstanceStore {
final Map<PluginWrapper,Plugin> store = new Hashtable<PluginWrapper,Plugin>();
}
/**
* {@link AdministrativeMonitor} that checks if there's Jenkins update.
*/
@Extension
public static final class PluginCycleDependenciesMonitor extends AdministrativeMonitor {
private transient volatile boolean isActive = false;
private transient volatile List<String> pluginsWithCycle;
public boolean isActivated() {
if(pluginsWithCycle == null){
pluginsWithCycle = new ArrayList<String>();
for (PluginWrapper p : Jenkins.getInstance().getPluginManager().getPlugins()) {
if(p.hasCycleDependency()){
pluginsWithCycle.add(p.getShortName());
isActive = true;
}
}
}
return true;
}
public List<String> getPluginsWithCycle() {
return pluginsWithCycle;
}
}
}
+13 -1
View File
@@ -125,6 +125,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
* The snapshot of <tt>disableFile.exists()</tt> as of the start up.
*/
private final boolean active;
private boolean hasCycleDependency = false;
private final List<Dependency> dependencies;
private final List<Dependency> optionalDependencies;
@@ -276,6 +278,8 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
return null;
}
@Override
public String toString() {
@@ -379,9 +383,17 @@ public class PluginWrapper implements Comparable<PluginWrapper> {
* Returns true if this plugin is enabled for this session.
*/
public boolean isActive() {
return active;
return active && !hasCycleDependency();
}
public boolean hasCycleDependency(){
return hasCycleDependency;
}
public void setHasCycleDependency(boolean hasCycle){
hasCycleDependency = hasCycle;
}
public boolean isBundled() {
return isBundled;
}
@@ -23,8 +23,9 @@ public abstract class CyclicGraphDetector<N> {
private final List<N> topologicalOrder = new ArrayList<N>();
public void run(Iterable<? extends N> allNodes) throws CycleDetectedException {
for (N n : allNodes)
for (N n : allNodes){
visit(n);
}
}
/**
@@ -62,8 +63,18 @@ public abstract class CyclicGraphDetector<N> {
private void detectedCycle(N q) throws CycleDetectedException {
int i = path.indexOf(q);
path.push(q);
throw new CycleDetectedException(path.subList(i, path.size()));
reactOnCycle(q, path.subList(i, path.size()));
}
/**
* React on detected cycles - default implementation throws an exception.
* @param q
* @param cycle
* @throws CycleDetectedException
*/
protected void reactOnCycle(N q, List<N> cycle) throws CycleDetectedException{
throw new CycleDetectedException(cycle);
}
public static final class CycleDetectedException extends Exception {
public final List cycle;