package de.jamba.hudson.jobinjection; import hudson.Launcher; import hudson.model.Build; import hudson.model.BuildListener; import hudson.model.Descriptor; import hudson.model.Hudson; import hudson.model.Project; import hudson.tasks.Builder; import java.io.PrintStream; import java.io.Serializable; import java.util.Date; import org.kohsuke.stapler.StaplerRequest; /** * This builder will start a new job and wait for its completion. The job will * be started on those node (group) where it was configured to run, */ public class JobInjector extends Builder implements Serializable, JobInjectorListenerInterface { // Which job to start and wait for? private String startJobName; // Has the started job finished yet? private boolean done = false; JobInjector(String startJobName) { this.startJobName = startJobName; } /** * Returns the name of the job to start and wait for * * @return the name of the job to start and wait for */ public String getStartJobName() { return startJobName; } /* * Suspends current thread for a given number of seconds. * Should not be interrupted. */ private void sleep(int seconds) { if (seconds > 0) try { Thread.sleep(seconds * 1000); } catch (InterruptedException ignore) { } } /** * Callback method to allow a listener to notify us about job completion. */ public void wakeMeUp() { done = true; } /** * This method does the real job. */ public boolean perform(Build build, Launcher launcher, BuildListener listener) { PrintStream logger = listener.getLogger(); // Find the right project (= job to run). Project proj = null; for (Project p : Hudson.getInstance().getProjects()) if (p.getFullName().equals(getStartJobName())) { proj = p; break; } if (proj == null) { logger.println("Project \"" + getStartJobName() + "\" does not exist."); // Do not continue with the build process. return false; } // Create a new listener JobInjectorListener rrl = new JobInjectorListener(Build.class, getStartJobName(), this); rrl.register(); // Start new job (= run of a project) String builtOn = build.getBuiltOnStr(); logger.println("Starting run of project " + getStartJobName() + " at " + new Date() + " on " + (builtOn == null ? "Master" : builtOn) + '.'); done = false; proj.scheduleBuild(); // Will start a job on a node (as configured). // Wait until started job is done do { sleep(10); // This is not Thread.sleep(milliseconds). } while (!done); logger.println("Project " + getStartJobName() + " finished at " + new Date() + '.'); // Clean up rrl.unregister(); rrl = null; // Continue with the build process. return true; } /** * Returns a JobInjector descriptor. */ public Descriptor<Builder> getDescriptor() { return DESCRIPTOR; } /** * Descriptor should be singleton. */ public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); /** * Descriptor for {@link JobInjector}. Used as a singleton. The class is * marked as public so that it can be accessed from views. * * <p> * See <tt>views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly</tt> * for the actual HTML fragment for the configuration screen. */ public static final class DescriptorImpl extends Descriptor<Builder> { DescriptorImpl() { super(JobInjector.class); } /** * This human readable name is used in the configuration screen. */ public String getDisplayName() { return "Start a job and wait for its completion"; } /** * Creates a new instance of {@link JobInjector} from a submitted form. */ public JobInjector newInstance(StaplerRequest req) throws FormException { return new JobInjector(req.getParameter("startJobName")); } } }