提交 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>
<li class=bug>
Edited description wasn't reflected when pressing the "Apply" button.
(<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=-->
<!-- these changes are controlled by the release process. DO NOT MODIFY -->
......
......@@ -80,6 +80,7 @@ public abstract class AbstractMavenProcessFactory
{
private final MavenModuleSet mms;
private final AbstractMavenBuild<?,?> build;
private final Launcher launcher;
/**
* Environment variables to be set to the maven process.
......@@ -99,7 +100,8 @@ public abstract class AbstractMavenProcessFactory
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.launcher = launcher;
this.envVars = envVars;
......@@ -243,8 +245,8 @@ public abstract class AbstractMavenProcessFactory
Computer.threadPoolForRemoting, new BufferedInputStream(con.in), new BufferedOutputStream(con.out),
listener.getLogger(), proc);
if (!PlexusModuleContributor.all().isEmpty())
applyPlexusModuleContributor(ch);
if (!PlexusModuleContributorFactory.all().isEmpty())
applyPlexusModuleContributor(ch,build);
return new NewProcess(ch,proc);
} catch (IOException e) {
......@@ -260,9 +262,15 @@ public abstract class AbstractMavenProcessFactory
/**
* 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
*/
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.
......
......@@ -26,7 +26,6 @@ package hudson.maven;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.maven.agent.Main;
import hudson.model.BuildListener;
import hudson.model.Run.RunnerAbortedException;
import hudson.model.TaskListener;
......@@ -44,14 +43,15 @@ import org.jvnet.hudson.maven3.agent.Maven3Main;
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
{
Maven3ProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, launcher, envVars, mavenOpts, workDir );
Maven3ProcessFactory(MavenModuleSet mms, AbstractMavenBuild<?,?> build, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, build, launcher, envVars, mavenOpts, workDir );
}
@Override
......@@ -82,12 +82,16 @@ public class Maven3ProcessFactory extends AbstractMavenProcessFactory implements
}
@Override
protected void applyPlexusModuleContributor(Channel channel) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask());
protected void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask(context));
}
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 {
Maven3Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0]));
......
......@@ -707,9 +707,9 @@ public class MavenBuild extends AbstractMavenBuild<MavenModule,MavenBuild> {
ProcessCache.MavenProcess process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), listener, maven3orLater
? new Maven3ProcessFactory(
getParent().getParent(), launcher, envVars, getMavenOpts(listener, envVars), null )
getParent().getParent(), MavenBuild.this, launcher, envVars, getMavenOpts(listener, envVars), null )
: 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");
FilePath localRepo = mms.getLocalRepository().locate(MavenBuild.this);
......
......@@ -683,18 +683,16 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
if ( maven3orLater )
{
LOGGER.fine( "using maven 3 " + mavenVersion );
process =
MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener,
new Maven3ProcessFactory( project, launcher, envVars, getMavenOpts(listener, envVars),
pom.getParent() ) );
process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener,
new Maven3ProcessFactory( project, MavenModuleSetBuild.this, launcher, envVars, getMavenOpts(listener, envVars),
pom.getParent() ) );
}
else
{
LOGGER.fine( "using maven 2 " + mavenVersion );
process =
MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener,
new MavenProcessFactory( project, launcher, envVars,getMavenOpts(listener, envVars),
pom.getParent() ) );
process = MavenBuild.mavenProcessCache.get( launcher.getChannel(), slistener,
new MavenProcessFactory( project, MavenModuleSetBuild.this, launcher, envVars,getMavenOpts(listener, envVars),
pom.getParent() ) );
}
ArgumentListBuilder margs = new ArgumentListBuilder().add("-B").add("-f", pom.getRemote());
......@@ -1045,9 +1043,9 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
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.
MavenModuleSet project = build.getProject();
this.listener = listener;
......@@ -1095,6 +1093,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
project.getScm().getModuleRoot( build.getWorkspace(), project.getLastBuild() ).getRemote();
this.mavenValidationLevel = project.getMavenValidationLevel();
plexusContributors = PlexusModuleContributorFactory.aggregate(build);
}
private boolean isUpdateSnapshots(String goals) {
......
......@@ -43,14 +43,15 @@ import java.net.URL;
/**
* {@link AbstractMavenProcessFactory} for Maven 2.
*
* @author Kohsuke Kawaguchi
*/
final class MavenProcessFactory extends AbstractMavenProcessFactory implements ProcessCache.Factory {
MavenProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, launcher, envVars, mavenOpts, workDir );
MavenProcessFactory(MavenModuleSet mms, AbstractMavenBuild<?,?> build, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, build, launcher, envVars, mavenOpts, workDir );
}
@Override
......@@ -88,12 +89,16 @@ final class MavenProcessFactory extends AbstractMavenProcessFactory implements P
}
@Override
protected void applyPlexusModuleContributor(Channel channel) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask());
protected void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask(context));
}
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 {
Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0]));
......
package hudson.maven;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import jenkins.model.Jenkins;
import hudson.FilePath;
import hudson.remoting.Channel;
import org.apache.maven.AbstractMavenLifecycleParticipant;
import sun.tools.jar.resources.jar;
import java.io.File;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static java.util.Arrays.asList;
/**
* 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.
* This object gets serialized and is sent to Maven JVM to run.
*
* @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();
/**
* 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() {
return Jenkins.getInstance().getExtensionList(PlexusModuleContributor.class);
protected transient Channel channel;
protected Object readResolve() {
channel = Channel.current();
return this;
}
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
* {@link PlexusModuleContributor}s in the system. The instance is remoting portable.
* Convenience method that creates a {@link PlexusModuleContributor} object
* 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() {
// capture in a serializable form
final List<PlexusModuleContributor> all = new ArrayList<PlexusModuleContributor>(all());
public static PlexusModuleContributor of(List<FilePath> jars) {
final List<String> files = new ArrayList<String>(jars.size());
for (FilePath jar : jars) {
files.add(jar.getRemote());
}
return new PlexusModuleContributor() {
@Override
public List<URL> getPlexusComponentJars() {
List<URL> urls = new ArrayList<URL>();
for (PlexusModuleContributor pc : all) {
urls.addAll(pc.getPlexusComponentJars());
try {
List<URL> r = new ArrayList<URL>(files.size());
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;
import hudson.FilePath;
import hudson.model.AbstractBuild;
import hudson.remoting.Which;
import hudson.slaves.DumbSlave;
import hudson.tasks.Maven.MavenInstallation;
import org.junit.Rule;
import org.junit.Test;
......@@ -9,10 +12,8 @@ import org.jvnet.hudson.test.SingleFileSCM;
import org.jvnet.hudson.test.TestExtension;
import test.BogusPlexusComponent;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.List;
/**
* @author Kohsuke Kawaguchi
......@@ -44,21 +45,29 @@ public class PlexusModuleContributorTest {
j.assertBuildStatusSuccess(p.scheduleBuild2(0));
}
@TestExtension
public static class PlexusLoader extends PlexusModuleContributor {
private URL bogusPlexusJar;
@Test
public void testCustomPlexusComponent_Maven3_slave() throws Exception {
j.configureDefaultMaven("apache-maven-3.0.1", MavenInstallation.MAVEN_30);
DumbSlave s = j.createSlave();
s.toComputer().connect(false).get();
public PlexusLoader() {
try {
this.bogusPlexusJar = Which.jarFile(BogusPlexusComponent.class).toURL();
} catch (IOException e) {
throw new AssertionError(e);
}
}
MavenModuleSet p = j.createMavenProject();
p.setAssignedLabel(s.getSelfLabel());
p.setScm(new SingleFileSCM("pom.xml",getClass().getResource("custom-plexus-component.pom")));
p.setGoals("clean");
j.assertBuildStatusSuccess(p.scheduleBuild2(0));
}
@TestExtension
public static class PlexusLoader extends PlexusModuleContributorFactory {
@Override
public List<URL> getPlexusComponentJars() {
return Collections.singletonList(bogusPlexusJar);
public PlexusModuleContributor createFor(AbstractBuild<?, ?> context) throws IOException, InterruptedException {
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.
先完成此消息的编辑!
想要评论请 注册