/******************************************************************************* * * Copyright (c) 2004-2010 Oracle Corporation. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * * Kohsuke Kawaguchi, Yahoo! Inc. * * *******************************************************************************/ package hudson.tasks; import hudson.ExtensionPoint; import hudson.Launcher; import hudson.DescriptorExtensionList; import hudson.LauncherDecorator; import hudson.model.*; import hudson.model.Run.RunnerAbortedException; import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; /** * Pluggability point for performing pre/post actions for the build process. * * <p> This extension point enables a plugin to set up / tear down additional * services needed to perform a build, such as setting up local X display, or * launching and stopping application servers for testing. * * <p> An instance of {@link BuildWrapper} is associated with a {@link Project} * with configuration information as its state. An instance is persisted along * with {@link Project}. * * <p> The {@link #setUp(Build,Launcher,BuildListener)} method is invoked for * each build. * * @author Kohsuke Kawaguchi */ public abstract class BuildWrapper extends AbstractDescribableImpl<BuildWrapper> implements ExtensionPoint { /** * Represents the environment set up by * {@link BuildWrapper#setUp(Build,Launcher,BuildListener)}. * * <p> It is expected that the subclasses of {@link BuildWrapper} extends * this class and implements its own semantics. */ public abstract class Environment extends hudson.model.Environment { /** * Runs after the {@link Builder} completes, and performs a tear down. * * <p> This method is invoked even when the build failed, so that the * clean up operation can be performed regardless of the build result * (for example, you'll want to stop application server even if a build * fails.) {@link Build#getResult} in this case will return * Result.FAILURE (since 1.339), and a null result indicates * SUCCESS-so-far (post-build actions may still affect the final * result). * * @param build The same {@link Build} object given to the set up * method. * @param listener The same {@link BuildListener} object given to the * set up method. * @return true if the build can continue, false if there was an error * and the build needs to be aborted. * @throws IOException terminates the build abnormally. Hudson will * handle the exception and reports a nice error message. * @since 1.150 */ public boolean tearDown(AbstractBuild build, BuildListener listener) throws IOException, InterruptedException { if (build instanceof Build) { return tearDown((Build) build, listener); } else { return true; } } /** * @deprecated since 2007-10-28. Use * {@link #tearDown(AbstractBuild, BuildListener)} instead. */ @Deprecated public boolean tearDown(Build build, BuildListener listener) throws IOException, InterruptedException { return true; } } /** * Runs before the {@link Builder} runs, and performs a set up. * * @param build The build in progress for which an {@link Environment} * object is created. Never null. * @param launcher This launcher can be used to launch processes for this * build. If the build runs remotely, launcher will also run a job on that * remote machine. Never null. * @param listener Can be used to send any message. * @return non-null if the build can continue, null if there was an error * and the build needs to be aborted. * @throws IOException terminates the build abnormally. Hudson will handle * the exception and reports a nice error message. * @since 1.150 */ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { if (build instanceof Build) { return setUp((Build) build, launcher, listener); } else { throw new AssertionError("The plugin '" + this.getClass().getName() + "' still uses " + "deprecated setUp(Build,Launcher,BuildListener) method. " + "Update the plugin to use setUp(AbstractBuild, Launcher, BuildListener) instead."); } } /** * @deprecated since 2007-10-28. Use * {@link #setUp(AbstractBuild, Launcher, BuildListener)} instead. */ @Deprecated public Environment setUp(Build build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException { throw new UnsupportedOperationException(getClass() + " needs to implement the setUp method"); } /** * Provides an opportunity for a {@link BuildWrapper} to decorate a * {@link Launcher} to be used in the build. * * <p> This hook is called very early on in the build (even before * {@link #setUp(AbstractBuild, Launcher, BuildListener)} is invoked.) The * typical use of {@link Launcher} decoration involves in modifying the * environment that processes run, such as the use of sudo/pfexec/chroot, or * manipulating environment variables. * * <p> The default implementation is no-op, which just returns the * {@code launcher} parameter as-is. * * @param build The build in progress for which this {@link BuildWrapper} is * called. Never null. * @param launcher The default launcher. Never null. This method is expected * to wrap this launcher. This makes sure that when multiple * {@link BuildWrapper}s attempt to decorate the same launcher it will sort * of work. But if you are developing a plugin where such collision is not a * concern, you can also simply discard this {@link Launcher} and create an * entirely different {@link Launcher} and return it, too. * @param listener Connected to the build output. Never null. Can be used * for error reporting. * @return Must not be null. If a fatal error happens, throw an exception. * @throws RunnerAbortedException If a fatal error is detected but the * implementation handled it gracefully, throw this exception to suppress * stack trace. * @since 1.280 * @see LauncherDecorator */ public Launcher decorateLauncher(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, RunnerAbortedException { return launcher; } /** * Provides an opportunity for a {@link BuildWrapper} to decorate the * {@link BuildListener} logger to be used by the build. * * <p> This hook is called very early on in the build (even before * {@link #setUp(AbstractBuild, Launcher, BuildListener)} is invoked.) * * <p> The default implementation is no-op, which just returns the * {@code logger} parameter as-is. * * @param build The build in progress for which this {@link BuildWrapper} is * called. Never null. * @param logger The default logger. Never null. This method is expected to * wrap this logger. This makes sure that when multiple * {@link BuildWrapper}s attempt to decorate the same logger it will sort of * work. * @return Must not be null. If a fatal error happens, throw an exception. * @throws RunnerAbortedException If a fatal error is detected but the * implementation handled it gracefully, throw this exception to suppress * stack trace. * @since 1.374 */ public OutputStream decorateLogger(AbstractBuild build, OutputStream logger) throws IOException, InterruptedException, RunnerAbortedException { return logger; } /** * {@link Action} to be displayed in the job page. * * @param job This object owns the {@link BuildWrapper}. The returned action * will be added to this object. * @return null if there's no such action. * @since 1.226 * @deprecated Use {@link #getProjectActions(AbstractProject)} instead. */ public Action getProjectAction(AbstractProject job) { return null; } /** * {@link Action}s to be displayed in the job page. * * @param job This object owns the {@link BuildWrapper}. The returned action * will be added to this object. * @return can be empty but never null * @since 1.341 */ public Collection<? extends Action> getProjectActions(AbstractProject job) { // delegate to getJobAction (singular) for backward compatible behavior Action a = getProjectAction(job); if (a == null) { return Collections.emptyList(); } return Collections.singletonList(a); } /** * Called to define {@linkplain AbstractBuild#getBuildVariables()}. * * This provides an opportunity for a BuildWrapper to append any additional * build variables defined for the current build. * * @param build The build in progress for which this {@link BuildWrapper} is * called. Never null. * @param variables Contains existing build variables. Add additional build * variables that you contribute to this map. */ public void makeBuildVariables(AbstractBuild build, Map<String, String> variables) { // noop } /** * Called to define sensitive build variables. This provides an opportunity * for a BuildWrapper to denote the names of variables that are sensitive in * nature and should not be exposed in output. * * @param build The build in progress for which this {@link BuildWrapper} is * called. Never null. * @param sensitiveVariables Contains names of sensitive build variables. * Names of sensitive variables that were added with * {@link #makeBuildVariables(hudson.model.AbstractBuild, java.util.Map)} * @since 1.378 */ public void makeSensitiveBuildVariables(AbstractBuild build, Set<String> sensitiveVariables) { // noop } /** * Returns all the registered {@link BuildWrapper} descriptors. */ // for compatibility we can't use BuildWrapperDescriptor public static DescriptorExtensionList<BuildWrapper, Descriptor<BuildWrapper>> all() { // use getDescriptorList and not getExtensionList to pick up legacy instances return Hudson.getInstance().<BuildWrapper, Descriptor<BuildWrapper>>getDescriptorList(BuildWrapper.class); } }