Skip to content
Browse files

[JENKINS-27392] SimpleBuildWrapper.createLoggerDecorator

  • Loading branch information
jglick committed Mar 31, 2015
1 parent 11ac075 commit a52d665180a7b11dcd64673c3f08b719f6c9f908
@@ -28,6 +28,7 @@
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.console.ConsoleLogFilter;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
@@ -177,12 +178,19 @@ protected boolean runPreCheckout() {

* Allows this wrapper to decorate log output.
* @param build as is passed to {@link #setUp(Context, Run, FilePath, Launcher, TaskListener, EnvVars)}
* @return a filter which ignores its {@code build} parameter and is {@link Serializable}; or null (the default)
* @since 1.608
public @CheckForNull ConsoleLogFilter createLoggerDecorator(@Nonnull Run<?,?> build) {
return null;

@Override public final OutputStream decorateLogger(AbstractBuild build, OutputStream logger) throws IOException, InterruptedException, Run.RunnerAbortedException {
// Doubtful this can be supported.
// Decorating a TaskListener would be more reasonable.
// But for an AbstractBuild this is called early in Run.execute, before setUp.
// And for other kinds of builds, it is unclear what this would even mean.
return logger;
ConsoleLogFilter filter = createLoggerDecorator(build);
return filter != null ? filter.decorateLogger(build, logger) : logger;

@Override public final Launcher decorateLauncher(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, Run.RunnerAbortedException {
@@ -28,7 +28,11 @@
import hudson.FilePath;
import hudson.Functions;
import hudson.Launcher;
import hudson.console.ConsoleLogFilter;
import hudson.console.LineTransformationOutputStream;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Descriptor;
import hudson.model.FreeStyleBuild;
@@ -45,18 +49,26 @@
import hudson.tasks.Shell;
import java.util.Collections;
import java.util.Locale;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Assume;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.CaptureEnvironmentBuilder;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestBuilder;
import org.jvnet.hudson.test.TestExtension;

public class SimpleBuildWrapperTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsRule r = new JenkinsRule();
@Rule public TemporaryFolder tmp = new TemporaryFolder();

@@ -162,7 +174,44 @@
return true;

@Test public void loggerDecorator() throws Exception {
FreeStyleProject p = r.createFreeStyleProject();
p.getBuildWrappersList().add(new WrapperWithLogger());
p.getBuildersList().add(new TestBuilder() {
@Override public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
listener.getLogger().println("sending a message");
return true;
r.assertLogContains("SENDING A MESSAGE", r.buildAndAssertSuccess(p));
public static class WrapperWithLogger extends SimpleBuildWrapper {
@Override public void setUp(Context context, Run<?,?> build, FilePath workspace, Launcher launcher, TaskListener listener, EnvVars initialEnvironment) throws IOException, InterruptedException {}
@Override public ConsoleLogFilter createLoggerDecorator(Run<?,?> build) {
return new UpcaseFilter();
private static class UpcaseFilter extends ConsoleLogFilter implements Serializable {
private static final long serialVersionUID = 1;
@SuppressWarnings("rawtypes") // inherited
@Override public OutputStream decorateLogger(AbstractBuild _ignore, final OutputStream logger) throws IOException, InterruptedException {
return new LineTransformationOutputStream() {
@Override protected void eol(byte[] b, int len) throws IOException {
logger.write(new String(b, 0, len).toUpperCase(Locale.ROOT).getBytes());
@TestExtension("loggerDecorator") public static class DescriptorImpl extends BuildWrapperDescriptor {
@Override public String getDisplayName() {
return "WrapperWithLogger";
@Override public boolean isApplicable(AbstractProject<?,?> item) {
return true;


0 comments on commit a52d665

Please sign in to comment.
You can’t perform that action at this time.