So the solution is to use a child first classLoader.
This new classLoader has been introduced in hudson 1.378. (see HUDSON-5360).
So you can now use it to made your plugin dependencies win on hudson core classLoader.
Some steps are needed.
Configuring your hpi plugin
<plugin>
<groupid>org.jvnet.hudson.tools</groupid>
<artifactid>maven-hpi-plugin</artifactid>
<version>1.54</version>
<configuration>
<pluginFirstClassLoader>true</pluginFirstClassLoader>
</configuration>
</plugin>
So now your pluginWrapper.classLoader will be of type PluginFirstClassLoader.
// pluginId is project.artifactId from your plugin pom
PluginWrapper pluginWrapper = Hudson.getInstance().getPluginManager().getPlugin( pluginId );
PluginFirstClassLoader pluginFirstClassLoader = (PluginFirstClassLoader) pluginWrapper.classLoader;
Now everthing is ready but some other tricks are needed :-)
Create a PlexusContainer (note you must use the new "plexus-guice" bridge).
This means you need the following dependency :
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
<version>1.4.1</version>
</dependency>
And very important you must exclude dependencies from the original plexus-container
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-connector-wagon</artifactId>
<version>${aetherVersion}</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
</exclusion>
</exclusions>
</dependency>
To prevent this you can add an enforcer rule which will chech plexus-container-default inclusion
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.0-beta-1</version>
<executions>
<execution>
<goals>
<goal>enforce</goal>
</goals>
<phase>validate</phase>
<id>ensure-no-plexus-container</id>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>org.codehaus.plexus:plexus-container-default</exclude>
</excludes>
<message>
ensure-no-plexus-container doesn't work anymore with maven 3 librairies. you have to add some exclusions.
</message>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
How to create the PlexusContainer from the PluginFirstClassLoader :
private PlexusContainer getPlexusContainer(PluginFirstClassLoader pluginFirstClassLoader) throws PlexusContainerException {
DefaultContainerConfiguration conf = new DefaultContainerConfiguration();
ClassWorld world = new ClassWorld();
ClassRealm classRealm = new ClassRealm( world, "project-building", pluginFirstClassLoader );
// olamy yup hackish but it's needed for plexus-shim which needs a URLClassLoader and PluginFirstClassLoader is not
for ( URL url : pluginFirstClassLoader.getURLs() )
{
classRealm.addURL( url );
LOGGER.fine( "add url " + url.toExternalForm() );
}
conf.setRealm( classRealm );
return new DefaultPlexusContainer( conf );
}
Then set the current Thread classLoader (don't miss to restore the original one in a finally statement
PlexusContainer plexusContainer = getPlexusContainer( pluginFirstClassLoader );
Thread.currentThread().setContextClassLoader( plexusContainer.getContainerRealm() );
Now you can play with maven 3 apis
ProjectBuilder projectBuilder = plexusContainer.lookup( ProjectBuilder.class );
A first sample is the plugin called : maven-dependency-update-trigger
: sources and Wiki Page (under construction :-) )
You must have a look at the dependencies used.
The plugin will check your project according to a cron expression and schedule a build if a snapshot dependency has changed (dependency and plugin).
It will be released as son as hudson 1.378 will be released.
Note : hpi:run doesn't work yet for this plugin as it needs some changes in the hpi mojo to handle the new PluginFirstClassLoader.