package org.jenkinsci.plugins.workflow.cps;

import com.cloudbees.groovy.cps.Block;
import com.cloudbees.groovy.cps.Env;
import com.cloudbees.groovy.cps.impl.CpsClosure;
import org.codehaus.groovy.runtime.DefaultGroovyStaticMethods;
import org.codehaus.groovy.runtime.InvokerHelper;

import java.util.List;

/**
 * {@link CpsClosure} that intercepts the {@code sleep} call so that it gets handled via SleepStep,
 * instead of {@link DefaultGroovyStaticMethods#sleep(Object, long)} that Groovy adds to {@code Object}.
 *
 * <p>
 * We had to do this because we made a mistake of having the 'sleep' step pick the same name as
 * a method defined on {@code Object}. Granted, it is a method added by Groovy, not by JDK, but the end result
 * is still the same, and the consequence is as severe as trying to override {@code hashCode()} method
 * and use it for something completely different. We ended up doing this because when we did it, a bug masked
 * the severity of the problem. In hindsight, we should have thought twice before adding a work around
 * like {@link CpsScript#sleep(long)}.
 *
 * @author Kohsuke Kawaguchi
 */
public class CpsClosure2 extends CpsClosure {
    public CpsClosure2(Object owner, Object thisObject, List<String> parameters, Block body, Env capture) {
        super(owner, thisObject, parameters, body, capture);
    }

    /**
     * @see CpsScript#sleep(long)
     */
    public Object sleep(long arg) {
        return InvokerHelper.invokeMethod(getOwner(), "sleep", arg);
    }
}

@@ -163,16 +163,44 @@
 losure;%0A
+import groovy.lang.Closure;%0A
 import o
@@ -1528,11 +1528,981 @@
 );%0A    %7D
+%0A%0A/* Overriding methods defined in DefaultGroovyMethods%0A        if we don't do this, definitions in DefaultGroovyMethods get called. One problem%0A        is that most of them are not whitelisted, and the other problem is that they don't%0A        always forward the call to the closure owner.%0A%0A        In CpsScript we override these methods and redefine them as variants of the 'echo' step,%0A        so for this to work the same from closure body, we need to redefine them.%0A */%0A    public void println(Object arg) %7B%0A        InvokerHelper.invokeMethod(getOwner(), %22println%22, new Object%5B%5D%7Barg%7D);%0A    %7D%0A%0A    public void println() %7B%0A        InvokerHelper.invokeMethod(getOwner(), %22println%22, new Object%5B0%5D);%0A    %7D%0A%0A    public void print(Object arg) %7B%0A        InvokerHelper.invokeMethod(getOwner(), %22print%22, new Object%5B%5D%7Barg%7D);%0A    %7D%0A%0A    public void printf(String format, Object value) %7B%0A        InvokerHelper.invokeMethod(getOwner(), %22printf%22, new Object%5B%5D%7Bformat,value%7D);%0A    %7D
 %0A%7D%0A

print methods must be overriden to forward to CpsScript.