提交 28e403ac 编写于 作者: J Jesse Glick

Providing a documented abstraction for Items.updatingByXml.

(Turns out cloudbees-template at least needs this, and it is possible other things besides Trigger could use it too.)
上级 6a9ce7f9
......@@ -34,6 +34,7 @@ import hudson.cli.declarative.CLIMethod;
import hudson.cli.declarative.CLIResolver;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.remoting.Callable;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.security.ACL;
......@@ -593,12 +594,12 @@ public abstract class AbstractItem extends Actionable implements Item, HttpDelet
// try to reflect the changes by reloading
new XmlFile(Items.XSTREAM, out.getTemporaryFile()).unmarshal(this);
Items.updatingByXml.set(true);
try {
onLoad(getParent(), getRootDir().getName());
} finally {
Items.updatingByXml.set(false);
}
Items.whileUpdatingByXml(new Callable<Void,IOException>() {
@Override public Void call() throws IOException {
onLoad(getParent(), getRootDir().getName());
return null;
}
});
Jenkins.getInstance().rebuildDependencyGraphAsync();
// if everything went well, commit this new version
......
......@@ -326,8 +326,9 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
}
this.builds = builds;
triggers().setOwner(this);
for (Trigger t : triggers())
t.start(this, Items.updatingByXml.get());
for (Trigger t : triggers()) {
t.start(this, Items.currentlyUpdatingByXml());
}
if(scm==null)
scm = new NullSCM(); // perhaps it was pointing to a plugin that no longer exists.
......
......@@ -25,6 +25,7 @@ package hudson.model;
import hudson.Util;
import hudson.model.listeners.ItemListener;
import hudson.remoting.Callable;
import hudson.security.AccessControlled;
import hudson.util.CopyOnWriteMap;
import hudson.util.Function1;
......@@ -206,12 +207,12 @@ public abstract class ItemGroupMixIn {
Util.copyFile(Items.getConfigFile(src).getFile(),Items.getConfigFile(result).getFile());
// reload from the new config
Items.updatingByXml.set(true);
try {
result = (T)Items.load(parent,result.getRootDir());
} finally {
Items.updatingByXml.set(false);
}
final File rootDir = result.getRootDir();
result = Items.whileUpdatingByXml(new Callable<T,IOException>() {
@Override public T call() throws IOException {
return (T) Items.load(parent, rootDir);
}
});
result.onCopiedFrom(src);
add(result);
......@@ -231,18 +232,17 @@ public abstract class ItemGroupMixIn {
// place it as config.xml
File configXml = Items.getConfigFile(getRootDirFor(name)).getFile();
configXml.getParentFile().mkdirs();
final File dir = configXml.getParentFile();
dir.mkdirs();
try {
IOUtils.copy(xml,configXml);
// load it
TopLevelItem result;
Items.updatingByXml.set(true);
try {
result = (TopLevelItem)Items.load(parent,configXml.getParentFile());
} finally {
Items.updatingByXml.set(false);
}
TopLevelItem result = Items.whileUpdatingByXml(new Callable<TopLevelItem,IOException>() {
@Override public TopLevelItem call() throws IOException {
return (TopLevelItem) Items.load(parent, dir);
}
});
add(result);
ItemListener.fireOnCreated(result);
......@@ -251,7 +251,7 @@ public abstract class ItemGroupMixIn {
return result;
} catch (IOException e) {
// if anything fails, delete the config file to avoid further confusion
Util.deleteRecursive(configXml.getParentFile());
Util.deleteRecursive(dir);
throw e;
}
}
......
......@@ -30,6 +30,7 @@ import hudson.matrix.MatrixProject;
import hudson.matrix.MatrixConfiguration;
import hudson.XmlFile;
import hudson.matrix.Axis;
import hudson.remoting.Callable;
import hudson.triggers.Trigger;
import hudson.util.DescriptorList;
import hudson.util.EditDistance;
......@@ -61,12 +62,41 @@ public class Items {
* @see Trigger#start
* @since 1.482
*/
static final ThreadLocal<Boolean> updatingByXml = new ThreadLocal<Boolean>() {
private static final ThreadLocal<Boolean> updatingByXml = new ThreadLocal<Boolean>() {
@Override protected Boolean initialValue() {
return false;
}
};
/**
* Runs a block while making {@link #currentlyUpdatingByXml} be temporarily true.
* Use this when you are creating or changing an item.
* @param <V> a return value type (may be {@link Void})
* @param <T> an error type (may be {@link Error})
* @param callable a block, typically running {@link #load} or {@link Item#onLoad}
* @return whatever {@code callable} returned
* @throws T anything {@code callable} throws
* @since 1.546
*/
public static <V,T extends Throwable> V whileUpdatingByXml(Callable<V,T> callable) throws T {
updatingByXml.set(true);
try {
return callable.call();
} finally {
updatingByXml.set(false);
}
}
/**
* Checks whether we are in the middle of creating or configuring an item via XML.
* Used to determine the {@code newInstance} parameter for {@link Trigger#start}.
* @return true if {@link #whileUpdatingByXml} is currently being called, false for example when merely starting Jenkins or reloading from disk
* @since 1.546
*/
public static boolean currentlyUpdatingByXml() {
return updatingByXml.get();
}
/**
* Returns all the registered {@link TopLevelItemDescriptor}s.
*/
......
......@@ -58,6 +58,7 @@ import java.util.logging.Logger;
import antlr.ANTLRException;
import javax.annotation.CheckForNull;
import edu.umd.cs.findbugs.annotations.SuppressWarnings;
import hudson.model.Items;
/**
* Triggers a {@link Build}.
......@@ -78,6 +79,7 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
* @param newInstance
* True if this may be a newly created trigger first attached to the {@link Project} (generally if the project is being created or configured).
* False if this is invoked for a {@link Project} loaded from disk.
* @see Items#currentlyUpdatingByXml
*/
public void start(J project, boolean newInstance) {
this.job = project;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册