Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #50 from jglick/CCL-JENKINS-37538
Browse files Browse the repository at this point in the history
[FIXED JENKINS-37538] Set the context class loader to a neutral value inside step executions
  • Loading branch information
jglick committed Aug 25, 2016
2 parents 6719c9f + 399c76c commit 6f65f3c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
Expand Up @@ -60,10 +60,12 @@ private static class ThreadContext {
this.thread = thread;
this.name = thread.getName();
this.classLoader = thread.getContextClassLoader();
ORIGINAL_CONTEXT_CLASS_LOADER.set(classLoader);
}
void restore() {
thread.setName(name);
thread.setContextClassLoader(classLoader);
ORIGINAL_CONTEXT_CLASS_LOADER.set(null);
}
}

Expand All @@ -90,4 +92,7 @@ private void tearDown(ThreadContext context) {
}

static ThreadLocal<CpsThreadGroup> CURRENT = new ThreadLocal<CpsThreadGroup>();
/** {@link Thread#getContextClassLoader} to be used for plugin code, as opposed to Groovy. */
static ThreadLocal<ClassLoader> ORIGINAL_CONTEXT_CLASS_LOADER = new ThreadLocal<>();

}
4 changes: 4 additions & 0 deletions src/main/java/org/jenkinsci/plugins/workflow/cps/DSL.java
Expand Up @@ -170,8 +170,10 @@ protected Object invokeStep(StepDescriptor d, Object args) {
final CpsStepContext context = new CpsStepContext(d,thread,handle,an,ps.body);
Step s;
boolean sync;
ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
try {
d.checkContextAvailability(context);
Thread.currentThread().setContextClassLoader(CpsVmExecutorService.ORIGINAL_CONTEXT_CLASS_LOADER.get());
s = d.newInstance(ps.namedArgs);
StepExecution e = s.start(context);
thread.setStep(e);
Expand All @@ -182,6 +184,8 @@ protected Object invokeStep(StepDescriptor d, Object args) {
context.onFailure(e);
s = null;
sync = true;
} finally {
Thread.currentThread().setContextClassLoader(originalLoader);
}

if (sync) {
Expand Down
32 changes: 32 additions & 0 deletions src/test/java/org/jenkinsci/plugins/workflow/DSLTest.java
Expand Up @@ -25,20 +25,29 @@
package org.jenkinsci.plugins.workflow;

import hudson.model.Result;
import javax.inject.Inject;
import org.jenkinsci.plugins.scriptsecurity.scripts.ScriptApproval;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl;
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.TestExtension;
import org.kohsuke.stapler.DataBoundConstructor;

/**
* Verifies general DSL functionality.
*/
public class DSLTest {

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

@Test public void overrideFunction() throws Exception {
Expand Down Expand Up @@ -139,4 +148,27 @@ public void nonexistentFunctions() throws Exception {
r.assertLogContains("constructible with compass and straightedge", b);
}

@Test public void contextClassLoader() throws Exception {
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("try {def c = classLoad(getClass().name); error(/did not expect to be able to load ${c} from ${c.classLoader}/)} catch (ClassNotFoundException x) {echo(/good, got ${x}/)}", false));
r.assertBuildStatusSuccess(p.scheduleBuild2(0));
}
public static class CLStep extends AbstractStepImpl {
public final String name;
@DataBoundConstructor public CLStep(String name) {this.name = name;}
public static class Execution extends AbstractSynchronousStepExecution<Class<?>> {
@Inject CLStep step;
protected Class<?> run() throws Exception {
return Thread.currentThread().getContextClassLoader().loadClass(step.name);
}
}
@TestExtension("contextClassLoader") public static class DescriptorImpl extends AbstractStepDescriptorImpl {
public DescriptorImpl() {super(Execution.class);}
@Override public String getFunctionName() {
return "classLoad";
}
}
}


}

0 comments on commit 6f65f3c

Please sign in to comment.