提交 495d97dd 编写于 作者: K Kohsuke Kawaguchi

Based on further conversation with the Artifactory plugin developers,...

Based on further conversation with the Artifactory plugin developers, revisiting this extension point.

This is a breaking change, but this extension point was added very recently, and it's based on the input from Artifactory plugin, so there's not much point in keeping one that doesn't serve the intended use case.
上级 41a9a68a
...@@ -78,6 +78,8 @@ Upcoming changes</a> ...@@ -78,6 +78,8 @@ Upcoming changes</a>
<li class=bug> <li class=bug>
Edited description wasn't reflected when pressing the "Apply" button. Edited description wasn't reflected when pressing the "Apply" button.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18436">issue 18436</a>) </ul> (<a href="https://issues.jenkins-ci.org/browse/JENKINS-18436">issue 18436</a>) </ul>
<li class=rfe>
Revisited the extension point added in 1.519 that adds custom plexus components.
</div><!--=TRUNK-END=--> </div><!--=TRUNK-END=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY --> <!-- these changes are controlled by the release process. DO NOT MODIFY -->
......
...@@ -80,6 +80,7 @@ public abstract class AbstractMavenProcessFactory ...@@ -80,6 +80,7 @@ public abstract class AbstractMavenProcessFactory
{ {
private final MavenModuleSet mms; private final MavenModuleSet mms;
private final AbstractMavenBuild<?,?> build;
private final Launcher launcher; private final Launcher launcher;
/** /**
* Environment variables to be set to the maven process. * Environment variables to be set to the maven process.
...@@ -99,7 +100,8 @@ public abstract class AbstractMavenProcessFactory ...@@ -99,7 +100,8 @@ public abstract class AbstractMavenProcessFactory
private final String mavenOpts; private final String mavenOpts;
AbstractMavenProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) { AbstractMavenProcessFactory(MavenModuleSet mms, AbstractMavenBuild<?,?> build, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
this.build = build;
this.mms = mms; this.mms = mms;
this.launcher = launcher; this.launcher = launcher;
this.envVars = envVars; this.envVars = envVars;
...@@ -243,8 +245,8 @@ public abstract class AbstractMavenProcessFactory ...@@ -243,8 +245,8 @@ public abstract class AbstractMavenProcessFactory
Computer.threadPoolForRemoting, new BufferedInputStream(con.in), new BufferedOutputStream(con.out), Computer.threadPoolForRemoting, new BufferedInputStream(con.in), new BufferedOutputStream(con.out),
listener.getLogger(), proc); listener.getLogger(), proc);
if (!PlexusModuleContributor.all().isEmpty()) if (!PlexusModuleContributorFactory.all().isEmpty())
applyPlexusModuleContributor(ch); applyPlexusModuleContributor(ch,build);
return new NewProcess(ch,proc); return new NewProcess(ch,proc);
} catch (IOException e) { } catch (IOException e) {
...@@ -260,9 +262,15 @@ public abstract class AbstractMavenProcessFactory ...@@ -260,9 +262,15 @@ public abstract class AbstractMavenProcessFactory
/** /**
* Apply extension plexus modules to the newly launched Maven process. * Apply extension plexus modules to the newly launched Maven process.
*
*
* @param channel
* Channel to the Maven process.
* @param context
* Context that {@link PlexusModuleContributor} needs to figure out what it needs to do.
* @since 1.519 * @since 1.519
*/ */
protected abstract void applyPlexusModuleContributor(Channel channel) throws InterruptedException, IOException; protected abstract void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException;
/** /**
* Builds the command line argument list to launch the maven process. * Builds the command line argument list to launch the maven process.
......
...@@ -26,7 +26,6 @@ package hudson.maven; ...@@ -26,7 +26,6 @@ package hudson.maven;
import hudson.EnvVars; import hudson.EnvVars;
import hudson.FilePath; import hudson.FilePath;
import hudson.Launcher; import hudson.Launcher;
import hudson.maven.agent.Main;
import hudson.model.BuildListener; import hudson.model.BuildListener;
import hudson.model.Run.RunnerAbortedException; import hudson.model.Run.RunnerAbortedException;
import hudson.model.TaskListener; import hudson.model.TaskListener;
...@@ -44,14 +43,15 @@ import org.jvnet.hudson.maven3.agent.Maven3Main; ...@@ -44,14 +43,15 @@ import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher; import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
/** /**
* @author Olivier Lamy * {@link AbstractMavenProcessFactory} for Maven 3.
* *
* @author Olivier Lam
*/ */
public class Maven3ProcessFactory extends AbstractMavenProcessFactory implements ProcessCache.Factory public class Maven3ProcessFactory extends AbstractMavenProcessFactory implements ProcessCache.Factory
{ {
Maven3ProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) { Maven3ProcessFactory(MavenModuleSet mms, AbstractMavenBuild<?,?> build, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, launcher, envVars, mavenOpts, workDir ); super( mms, build, launcher, envVars, mavenOpts, workDir );
} }
@Override @Override
...@@ -82,12 +82,16 @@ public class Maven3ProcessFactory extends AbstractMavenProcessFactory implements ...@@ -82,12 +82,16 @@ public class Maven3ProcessFactory extends AbstractMavenProcessFactory implements
} }
@Override @Override
protected void applyPlexusModuleContributor(Channel channel) throws InterruptedException, IOException { protected void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask()); channel.call(new InstallPlexusModulesTask(context));
} }
private static final class InstallPlexusModulesTask implements Callable<Void,IOException> { private static final class InstallPlexusModulesTask implements Callable<Void,IOException> {
PlexusModuleContributor c = PlexusModuleContributor.aggregate(); PlexusModuleContributor c;
public InstallPlexusModulesTask(AbstractMavenBuild<?, ?> context) throws IOException, InterruptedException {
c = PlexusModuleContributorFactory.aggregate(context);
}
public Void call() throws IOException { public Void call() throws IOException {
Maven3Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0])); Maven3Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0]));
......
...@@ -707,9 +707,9 @@ public class MavenBuild extends AbstractMavenBuild<MavenModule,MavenBuild> { ...@@ -707,9 +707,9 @@ public class MavenBuild extends AbstractMavenBuild<MavenModule,MavenBuild> {
ProcessCache.MavenProcess process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), listener, maven3orLater ProcessCache.MavenProcess process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), listener, maven3orLater
? new Maven3ProcessFactory( ? new Maven3ProcessFactory(
getParent().getParent(), launcher, envVars, getMavenOpts(listener, envVars), null ) getParent().getParent(), MavenBuild.this, launcher, envVars, getMavenOpts(listener, envVars), null )
: new MavenProcessFactory( : new MavenProcessFactory(
getParent().getParent(), launcher, envVars, getMavenOpts(listener, envVars), null )); getParent().getParent(), MavenBuild.this, launcher, envVars, getMavenOpts(listener, envVars), null ));
ArgumentListBuilder margs = new ArgumentListBuilder("-N","-B"); ArgumentListBuilder margs = new ArgumentListBuilder("-N","-B");
FilePath localRepo = mms.getLocalRepository().locate(MavenBuild.this); FilePath localRepo = mms.getLocalRepository().locate(MavenBuild.this);
......
...@@ -683,18 +683,16 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -683,18 +683,16 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
if ( maven3orLater ) if ( maven3orLater )
{ {
LOGGER.fine( "using maven 3 " + mavenVersion ); LOGGER.fine( "using maven 3 " + mavenVersion );
process = process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener,
MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener, new Maven3ProcessFactory( project, MavenModuleSetBuild.this, launcher, envVars, getMavenOpts(listener, envVars),
new Maven3ProcessFactory( project, launcher, envVars, getMavenOpts(listener, envVars), pom.getParent() ) );
pom.getParent() ) );
} }
else else
{ {
LOGGER.fine( "using maven 2 " + mavenVersion ); LOGGER.fine( "using maven 2 " + mavenVersion );
process = process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener,
MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener, new MavenProcessFactory( project, MavenModuleSetBuild.this, launcher, envVars,getMavenOpts(listener, envVars),
new MavenProcessFactory( project, launcher, envVars,getMavenOpts(listener, envVars), pom.getParent() ) );
pom.getParent() ) );
} }
ArgumentListBuilder margs = new ArgumentListBuilder().add("-B").add("-f", pom.getRemote()); ArgumentListBuilder margs = new ArgumentListBuilder().add("-B").add("-f", pom.getRemote());
...@@ -1045,9 +1043,9 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -1045,9 +1043,9 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
String rootPOMRelPrefix; String rootPOMRelPrefix;
private final PlexusModuleContributor plexusContributors = PlexusModuleContributor.aggregate(); private final PlexusModuleContributor plexusContributors;
PomParser(BuildListener listener, MavenInstallation mavenHome, String mavenVersion, EnvVars envVars, MavenModuleSetBuild build) { PomParser(BuildListener listener, MavenInstallation mavenHome, String mavenVersion, EnvVars envVars, MavenModuleSetBuild build) throws IOException, InterruptedException {
// project cannot be shipped to the remote JVM, so all the relevant properties need to be captured now. // project cannot be shipped to the remote JVM, so all the relevant properties need to be captured now.
MavenModuleSet project = build.getProject(); MavenModuleSet project = build.getProject();
this.listener = listener; this.listener = listener;
...@@ -1095,6 +1093,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven ...@@ -1095,6 +1093,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
project.getScm().getModuleRoot( build.getWorkspace(), project.getLastBuild() ).getRemote(); project.getScm().getModuleRoot( build.getWorkspace(), project.getLastBuild() ).getRemote();
this.mavenValidationLevel = project.getMavenValidationLevel(); this.mavenValidationLevel = project.getMavenValidationLevel();
plexusContributors = PlexusModuleContributorFactory.aggregate(build);
} }
private boolean isUpdateSnapshots(String goals) { private boolean isUpdateSnapshots(String goals) {
......
...@@ -43,14 +43,15 @@ import java.net.URL; ...@@ -43,14 +43,15 @@ import java.net.URL;
/** /**
* {@link AbstractMavenProcessFactory} for Maven 2.
* *
* @author Kohsuke Kawaguchi * @author Kohsuke Kawaguchi
*/ */
final class MavenProcessFactory extends AbstractMavenProcessFactory implements ProcessCache.Factory { final class MavenProcessFactory extends AbstractMavenProcessFactory implements ProcessCache.Factory {
MavenProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) { MavenProcessFactory(MavenModuleSet mms, AbstractMavenBuild<?,?> build, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, launcher, envVars, mavenOpts, workDir ); super( mms, build, launcher, envVars, mavenOpts, workDir );
} }
@Override @Override
...@@ -88,12 +89,16 @@ final class MavenProcessFactory extends AbstractMavenProcessFactory implements P ...@@ -88,12 +89,16 @@ final class MavenProcessFactory extends AbstractMavenProcessFactory implements P
} }
@Override @Override
protected void applyPlexusModuleContributor(Channel channel) throws InterruptedException, IOException { protected void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask()); channel.call(new InstallPlexusModulesTask(context));
} }
private static final class InstallPlexusModulesTask implements Callable<Void,IOException> { private static final class InstallPlexusModulesTask implements Callable<Void,IOException> {
PlexusModuleContributor c = PlexusModuleContributor.aggregate(); PlexusModuleContributor c;
public InstallPlexusModulesTask(AbstractMavenBuild<?, ?> context) throws IOException, InterruptedException {
c = PlexusModuleContributorFactory.aggregate(context);
}
public Void call() throws IOException { public Void call() throws IOException {
Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0])); Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0]));
......
package hudson.maven; package hudson.maven;
import hudson.ExtensionList; import hudson.FilePath;
import hudson.ExtensionPoint; import hudson.remoting.Channel;
import jenkins.model.Jenkins;
import org.apache.maven.AbstractMavenLifecycleParticipant; import org.apache.maven.AbstractMavenLifecycleParticipant;
import sun.tools.jar.resources.jar;
import java.io.File;
import java.io.Serializable; import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static java.util.Arrays.asList;
/** /**
* Contributes additional code into Plexus container when we run Maven. * Contributes additional code into Plexus container when we run Maven.
* *
* <p> * <p>
* Injecting custom plexus components, such as {@link AbstractMavenLifecycleParticipant}, allows plugins to * This object gets serialized and is sent to Maven JVM to run.
* participate into the Maven internals more deeply.
* *
* @author Kohsuke Kawaguchi * @author Kohsuke Kawaguchi
* @since 1.519 * @since 1.521
* @see PlexusModuleContributorFactory
*/ */
public abstract class PlexusModuleContributor implements ExtensionPoint, Serializable { public abstract class PlexusModuleContributor implements Serializable {
/**
* Designates the list of URLs to be added to the classpath of the core plexus components
* that constitute Maven.
*/
public abstract List<URL> getPlexusComponentJars(); public abstract List<URL> getPlexusComponentJars();
/** /**
* Returns all the registered {@link PlexusModuleContributor}s. * When {@link #getPlexusComponentJars()} is called, this field is set
* to the channel that represents the connection to the master.
*/ */
public static ExtensionList<PlexusModuleContributor> all() { protected transient Channel channel;
return Jenkins.getInstance().getExtensionList(PlexusModuleContributor.class);
protected Object readResolve() {
channel = Channel.current();
return this;
} }
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static PlexusModuleContributor of(FilePath... jars) {
return of(asList(jars));
}
/** /**
* Returns a single {@link PlexusModuleContributor} that aggregates all the registered * Convenience method that creates a {@link PlexusModuleContributor} object
* {@link PlexusModuleContributor}s in the system. The instance is remoting portable. * that adds the given files as classpaths.
*
* These jar files must represent the files on the computer on which Maven process is running.
*/ */
public static PlexusModuleContributor aggregate() { public static PlexusModuleContributor of(List<FilePath> jars) {
// capture in a serializable form final List<String> files = new ArrayList<String>(jars.size());
final List<PlexusModuleContributor> all = new ArrayList<PlexusModuleContributor>(all()); for (FilePath jar : jars) {
files.add(jar.getRemote());
}
return new PlexusModuleContributor() { return new PlexusModuleContributor() {
@Override @Override
public List<URL> getPlexusComponentJars() { public List<URL> getPlexusComponentJars() {
List<URL> urls = new ArrayList<URL>(); try {
for (PlexusModuleContributor pc : all) { List<URL> r = new ArrayList<URL>(files.size());
urls.addAll(pc.getPlexusComponentJars()); for (String file : files) {
r.add(new File(file).toURI().toURL());
}
return r;
} catch (MalformedURLException e) {
throw new IllegalStateException(e);
} }
return urls;
} }
private static final long serialVersionUID = 1L;
}; };
} }
} }
package hudson.maven;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import hudson.model.AbstractBuild;
import jenkins.model.Jenkins;
import org.apache.maven.AbstractMavenLifecycleParticipant;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Contributes additional code into Plexus container when we run Maven.
*
* <p>
* Injecting custom plexus components, such as {@link AbstractMavenLifecycleParticipant}, allows plugins to
* participate into the Maven internals more deeply.
*
* <h2>Lifecycle</h2>
* <p>
* {@link PlexusModuleContributorFactory}s are instantiated as singletons on the master, and whenever a new Maven
* process starts, its {@link #createFor(AbstractBuild)} method is called to instantiate {@link PlexusModuleContributor},
* which gets serialized on the master, then deserialized inside the Maven process, and then its
* {@link PlexusModuleContributor#getPlexusComponentJars()} will be invoked to determine the additional classpaths.
* and then run.
*
* @author Kohsuke Kawaguchi
* @since 1.521
* @see PlexusModuleContributor
*/
public abstract class PlexusModuleContributorFactory implements ExtensionPoint {
public abstract PlexusModuleContributor createFor(AbstractBuild<?,?> context) throws IOException, InterruptedException;
/**
* Returns all the registered {@link PlexusModuleContributor}s.
*/
public static ExtensionList<PlexusModuleContributorFactory> all() {
return Jenkins.getInstance().getExtensionList(PlexusModuleContributorFactory.class);
}
/**
* Returns a single {@link PlexusModuleContributor} that aggregates all the registered
* {@link PlexusModuleContributor}s in the system. The instance is remoting portable.
*/
public static PlexusModuleContributor aggregate(AbstractBuild<?,?> context) throws IOException, InterruptedException {
// capture in a serializable form
final List<PlexusModuleContributor> all = new ArrayList<PlexusModuleContributor>();
for (PlexusModuleContributorFactory pmcf : all()) {
PlexusModuleContributor pmc = pmcf.createFor(context);
if (pmc!=null)
all.add(pmc);
}
return new PlexusModuleContributor() {
@Override
public List<URL> getPlexusComponentJars() {
List<URL> urls = new ArrayList<URL>();
for (PlexusModuleContributor pc : all) {
urls.addAll(pc.getPlexusComponentJars());
}
return urls;
}
};
}
}
package hudson.maven; package hudson.maven;
import hudson.FilePath;
import hudson.model.AbstractBuild;
import hudson.remoting.Which; import hudson.remoting.Which;
import hudson.slaves.DumbSlave;
import hudson.tasks.Maven.MavenInstallation; import hudson.tasks.Maven.MavenInstallation;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
...@@ -9,10 +12,8 @@ import org.jvnet.hudson.test.SingleFileSCM; ...@@ -9,10 +12,8 @@ import org.jvnet.hudson.test.SingleFileSCM;
import org.jvnet.hudson.test.TestExtension; import org.jvnet.hudson.test.TestExtension;
import test.BogusPlexusComponent; import test.BogusPlexusComponent;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
/** /**
* @author Kohsuke Kawaguchi * @author Kohsuke Kawaguchi
...@@ -44,21 +45,29 @@ public class PlexusModuleContributorTest { ...@@ -44,21 +45,29 @@ public class PlexusModuleContributorTest {
j.assertBuildStatusSuccess(p.scheduleBuild2(0)); j.assertBuildStatusSuccess(p.scheduleBuild2(0));
} }
@TestExtension @Test
public static class PlexusLoader extends PlexusModuleContributor { public void testCustomPlexusComponent_Maven3_slave() throws Exception {
private URL bogusPlexusJar; j.configureDefaultMaven("apache-maven-3.0.1", MavenInstallation.MAVEN_30);
DumbSlave s = j.createSlave();
s.toComputer().connect(false).get();
public PlexusLoader() { MavenModuleSet p = j.createMavenProject();
try { p.setAssignedLabel(s.getSelfLabel());
this.bogusPlexusJar = Which.jarFile(BogusPlexusComponent.class).toURL();
} catch (IOException e) { p.setScm(new SingleFileSCM("pom.xml",getClass().getResource("custom-plexus-component.pom")));
throw new AssertionError(e); p.setGoals("clean");
} j.assertBuildStatusSuccess(p.scheduleBuild2(0));
} }
@TestExtension
public static class PlexusLoader extends PlexusModuleContributorFactory {
@Override @Override
public List<URL> getPlexusComponentJars() { public PlexusModuleContributor createFor(AbstractBuild<?, ?> context) throws IOException, InterruptedException {
return Collections.singletonList(bogusPlexusJar); File bogusPlexusJar = Which.jarFile(BogusPlexusComponent.class);
final FilePath localJar = context.getBuiltOn().getRootPath().child("cache/bogusPlexus.jar");
localJar.copyFrom(new FilePath(bogusPlexusJar));
return PlexusModuleContributor.of(localJar);
} }
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册