package hudson.plugins.parameterizedtrigger;
import hudson.Extension;
import hudson.Launcher;
import hudson.matrix.MatrixAggregatable;
import hudson.matrix.MatrixAggregator;
import hudson.matrix.MatrixBuild;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.DependecyDeclarer;
import hudson.model.DependencyGraph;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.DescriptorList;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
public class BuildTrigger extends Notifier implements DependecyDeclarer, MatrixAggregatable {
private final ArrayList<BuildTriggerConfig> configs;
public BuildTrigger(List<BuildTriggerConfig> configs) {
this.configs = new ArrayList<BuildTriggerConfig>(configs);
}
public BuildTrigger(BuildTriggerConfig... configs) {
this(Arrays.asList(configs));
}
public List<BuildTriggerConfig> getConfigs() {
return configs;
}
@Override
public boolean needsToRunAfterFinalized() {
return true;
}
@Override
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
}
@Override @SuppressWarnings("deprecation")
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
// In Hudson 1.341+ builds will be triggered via DependencyGraph
if (canDeclare(build.getProject())) return true;
for (BuildTriggerConfig config : configs) {
config.perform(build, launcher, listener);
}
return true;
}
@Override
public void buildDependencyGraph(AbstractProject owner, DependencyGraph graph) {
// Can only add dependencies in Hudson 1.341 or higher
if (!canDeclare(owner)) return;
for (BuildTriggerConfig config : configs)
for (AbstractProject project : config.getProjectList())
ParameterizedDependency.add(owner, project, config, graph);
}
private boolean canDeclare(AbstractProject owner) {
// Inner class added in Hudson 1.341
return DependencyGraph.class.getClasses().length > 0
// See HUDSON-6274 -- currently Maven projects call scheduleProject
// directly, so would not get parameters from DependencyGraph.
// Remove this condition when HUDSON-6274 is implemented.
&& !owner.getClass().getName().equals("hudson.maven.MavenModuleSet");
}
public MatrixAggregator createAggregator(MatrixBuild build, Launcher launcher, BuildListener listener) {
return new MatrixAggregator(build, launcher, listener) {
@Override
public boolean endBuild() throws InterruptedException, IOException {
return hudson.tasks.BuildTrigger.execute(build, listener);
}
};
}
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
@Override
public Publisher newInstance(StaplerRequest req, JSONObject json)
throws FormException {
List<BuildTriggerConfig> result = new ArrayList<BuildTriggerConfig>();
Object c = json.get("configs");
if (c instanceof JSONObject) {
JSONObject j = (JSONObject) c;
result.add(bindBuildTrigger(req, j));
}
if (c instanceof JSONArray) {
JSONArray a = (JSONArray) c;
for (Object o : a) {
if (o instanceof JSONObject) {
JSONObject j = (JSONObject) o;
result.add(bindBuildTrigger(req, j));
}
}
}
return new BuildTrigger(result);
}
private BuildTriggerConfig bindBuildTrigger(StaplerRequest req,
JSONObject o) throws FormException {
return new BuildTriggerConfig(o.getString("projects"),
ResultCondition.valueOf(o.getString("condition")),
newInstancesFromHeteroList(req, o, "configs", CONFIGS));
}
@Override
public String getHelpFile() {
return "/plugin/parameterized-trigger/help/plugin.html";
}
@Override
public String getDisplayName() {
return "Trigger parameterized build on other projects";
}
public DescriptorList<AbstractBuildParameters> getBuilderConfigDescriptors() {
return CONFIGS;
}
public ResultCondition[] getPossibleResultConditions() {
return ResultCondition.values();
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
}
public static final DescriptorList<AbstractBuildParameters> CONFIGS = new DescriptorList<AbstractBuildParameters>(
AbstractBuildParameters.class);
}