提交 dceafbbf 编写于 作者: O olamy 提交者: Kohsuke Kawaguchi

[HUDSON-4988] push some stuff

to be able to get in an other place (sure git could be better :-) )
some issue when using maven 2
some stuff to do more in maven 3 build (recording mojo execution etc...)



git-svn-id: https://hudson.dev.java.net/svn/hudson/branches/main-maven3-support@36643 71c3de6d-444a-0410-be80-ed276b4c234a
上级 cfd817d2
......@@ -461,7 +461,6 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
......
......@@ -626,6 +626,13 @@ public abstract class PluginManager extends AbstractModelObject {
}
return Collections.enumeration(resources);
}
@Override
public String toString()
{
// only for debugging purpose
return "classLoader " + getClass().getName();
}
}
private static final Logger LOGGER = Logger.getLogger(PluginManager.class.getName());
......
......@@ -73,25 +73,52 @@ THE SOFTWARE.
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven-interceptor</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
<version>1.1</version>
</dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
</dependency>
<dependency>
<!-- default dependency to 2.0.2 confuses IntelliJ. Otherwise this value doesn't really affect build or runtime. -->
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1-rc1</version>
</dependency>
<!--
<dependency>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
<version>1.1</version>
</dependency>
-->
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.8.0</version>
</dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<version>2.0.9</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
......
......@@ -23,25 +23,36 @@
*/
package hudson.maven.agent;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.classworlds.ClassWorld;
import org.codehaus.classworlds.DefaultClassRealm;
import org.codehaus.classworlds.Launcher;
import org.codehaus.classworlds.NoSuchRealmException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.apache.tools.ant.AntClassLoader;
import org.codehaus.classworlds.ClassWorldAdapter;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.classworlds.launcher.ConfigurationException;
import org.codehaus.plexus.classworlds.launcher.Launcher;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
import org.codehaus.plexus.classworlds.realm.NoSuchRealmException;
/**
* Entry point for launching Maven and Hudson remoting in the same VM,
* in the classloader layout that Maven expects.
......@@ -100,26 +111,43 @@ public class Main {
// I don't know how classworlds react to undefined variable, so
(interceptorOverrideJar!=null?interceptorOverrideJar:interceptorJar).getPath());
// FIXME change stuff for 206 earlier !
boolean is206OrLater = !new File(m2Home,"core").exists();
// load the default realms
launcher = new Launcher();
launcher.setSystemClassLoader(Main.class.getClassLoader());
launcher.configure(Main.class.getResourceAsStream(
is206OrLater?"classworlds-2.0.6.conf":"classworlds.conf"));
configureLauncher( m2Home, remotingJar, interceptorJar, interceptorOverrideJar, is206OrLater );
System.out.println( "realms size " + launcher.getWorld().getRealms().size() );
for (Iterator iter = launcher.getWorld().getRealms().iterator();iter.hasNext();)
{
ClassRealm realm = (ClassRealm) iter.next();
System.out.println( "realm " + realm + " urls " + Arrays.asList( realm.getURLs() ) );
}
// have it eventually delegate to this class so that this can be visible
// create a realm for loading remoting subsystem.
// this needs to be able to see maven.
ClassRealm remoting = new DefaultClassRealm(launcher.getWorld(),"hudson-remoting", launcher.getSystemClassLoader());
remoting.setParent(launcher.getWorld().getRealm("plexus.core.maven"));
remoting.addConstituent(remotingJar.toURI().toURL());
System.out.print( "Main classLoader " + Main.class.getClassLoader() );
//test en changeant le parent en plexus.core.maven ?
ClassRealm remoting = launcher.getWorld().newRealm( "hudson-remoting", launcher.getWorld().getClassRealm( "plexus.core" ) );
remoting.importFrom( "plexus.core.maven", "org.apache.maven" );
//remoting.setParentClassLoader( launcher.getWorld().getClassRealm( "plexus.core.maven" ) );
remoting.addURL(remotingJar.toURI().toURL());
final Socket s = new Socket((String)null,tcpPort);
Class remotingLauncher = remoting.loadClass("hudson.remoting.Launcher");
remotingLauncher.getMethod("main",new Class[]{InputStream.class,OutputStream.class}).invoke(null,
Method mainMethod = remotingLauncher.getMethod("main",new Class[]{InputStream.class,OutputStream.class});
mainMethod.invoke(null,
new Object[]{
// do partial close, since socket.getInputStream and getOutputStream doesn't do it by
new BufferedInputStream(new FilterInputStream(s.getInputStream()) {
......@@ -133,6 +161,7 @@ public class Main {
}
})
});
System.out.println(" remoting classLoader " + remoting.toString() );
System.exit(0);
}
......@@ -153,17 +182,129 @@ public class Main {
}
}
}
/**
* old one
* @throws ConfigurationException
* @throws IOException
* @throws NoSuchRealmException
* @throws DuplicateRealmException
*/
private static void configureLauncher(File m2Home, File remotingJar, File interceptorJar, File interceptorOverrideJar, boolean is206OrLater)
throws DuplicateRealmException, NoSuchRealmException, IOException, ConfigurationException {
launcher.configure(Main.class.getResourceAsStream(is206OrLater?"classworlds-2.0.6.conf":"classworlds.conf"));
}
/**
* with various classLoader hierarchy stuff
* @throws MalformedURLException
* @throws DuplicateRealmException
*/
private static void configureLauncher2(File m2Home, File remotingJar, File interceptorJar, File interceptorOverrideJar, boolean is206OrLater)
throws MalformedURLException, DuplicateRealmException {
ClassWorld world = new ClassWorld();
launcher.setWorld( world );
ClassRealm plexusCore = world.newRealm( "plexus.core" );
plexusCore.setParentClassLoader( Main.class.getClassLoader() );
File mavenCore = new File(m2Home, is206OrLater ? "boot" : "core");
String[] coreJars = mavenCore.list( new FilenameFilter()
{
public boolean accept( File dir, String name )
{
return name.endsWith( ".jar" );
}
});
for (int i = 0,size = coreJars.length;i<size;i++)
{
plexusCore.addURL( new File(coreJars[i]).toURI().toURL() );
System.out.println("adding jar to plexusCore " + coreJars[i] );
}
ChildFistClassCloader childFistClassCloader = new ChildFistClassCloader( plexusCore );
File mavenLib = new File(m2Home, "lib");
String[] libJars = mavenLib.list( new FilenameFilter()
{
public boolean accept( File dir, String name )
{
return name.endsWith( ".jar" );
}
});
for (int i = 0,size = libJars.length;i<size;i++)
{
childFistClassCloader.addPathComponent( new File(libJars[i]) );
System.out.println("adding jar " + libJars[i] );
}
childFistClassCloader.addPathComponent( interceptorJar );
if (interceptorOverrideJar!=null)
{
childFistClassCloader.addPathComponent( interceptorOverrideJar );
}
ClassRealm plexusCoreMaven = world.newRealm( "plexus.core.maven" );
plexusCore.setParentClassLoader( childFistClassCloader );
for (int i = 0,size = libJars.length;i<size;i++)
{
plexusCoreMaven.addURL( new File(libJars[i]).toURI().toURL() );
}
plexusCoreMaven.addURL( interceptorJar.toURI().toURL() );
if (interceptorOverrideJar!=null)
{
plexusCoreMaven.addURL( interceptorOverrideJar.toURI().toURL() );
}
}
/**
* Called by the code in remoting to launch.
* @throws org.codehaus.classworlds.DuplicateRealmException
* @throws IllegalArgumentException
*/
public static int launch(String[] args) throws NoSuchMethodException, IllegalAccessException, NoSuchRealmException, InvocationTargetException, ClassNotFoundException {
public static int launch(String[] args)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, IOException, IllegalArgumentException {
ClassWorld world = launcher.getWorld();
Set builtinRealms = new HashSet(world.getRealms());
URLClassLoader orig = (URLClassLoader) Thread.currentThread().getContextClassLoader();
System.out.println("orig " + orig.toString());
Enumeration urls = orig.findResources( "META-INF/plexus/components.xml" );
while(urls.hasMoreElements())
{
System.out.println(" url " + urls.nextElement());
}
try {
launcher.launch(args);
launcher.setAppMain( "org.apache.maven.cli.MavenCli", "plexus.core.maven" );
ClassRealm newCl = launcher.getMainRealm();
System.out.println("urls " + Arrays.asList( newCl.getURLs() ) );
urls = newCl.findResources( "META-INF/plexus/components.xml" );
while(urls.hasMoreElements())
{
System.out.println(" url " + urls.nextElement());
}
System.out.println("launcher cl " + newCl.toString());
//Thread.currentThread().setContextClassLoader( newCl );
Method mainMethod = launcher.getMainClass().getMethod( "main", new Class[]{String[].class, org.codehaus.classworlds.ClassWorld.class} );
//launcher.launch(args);
mainMethod.invoke( null,new Object[]{args,ClassWorldAdapter.getInstance( launcher.getWorld() )} );
//} catch (org.codehaus.classworlds.DuplicateRealmException e) {
// throw new RuntimeException( e.getMessage(), e);
} catch (NoSuchRealmException e) {
throw new RuntimeException( e.getMessage(), e);
} finally {
Thread.currentThread().setContextClassLoader( orig );
// delete all realms created by Maven
// this is because Maven creates a child realm for each plugin it loads,
// and the realm id doesn't include the version.
......@@ -173,9 +314,70 @@ public class Main {
all.removeAll(builtinRealms);
for (Iterator itr = all.iterator(); itr.hasNext();) {
ClassRealm cr = (ClassRealm) itr.next();
world.disposeRealm(cr.getId());
try
{
world.disposeRealm(cr.getId());
}
catch ( NoSuchRealmException e )
{
throw new RuntimeException( e.getMessage(), e);
}
}
}
return launcher.getExitCode();
}
private static org.codehaus.classworlds.ClassWorld convertType(ClassWorld classWorld)
throws org.codehaus.classworlds.DuplicateRealmException
{
org.codehaus.classworlds.ClassWorld old = new org.codehaus.classworlds.ClassWorld();
for (Iterator ite = classWorld.getRealms().iterator();ite.hasNext();)
{
ClassRealm realm = (ClassRealm) ite.next();
old.newRealm( realm.getId(), realm );
}
return old;
}
static class ChildFistClassCloader extends AntClassLoader
{
ChildFistClassCloader (ClassLoader parent)
{
super( parent, false );
}
protected Enumeration findResources( String name )
throws IOException
{
Enumeration enu = super.findResources( name );
return enu;
}
public URL getResource( String name )
{
URL url = super.getResource( name );
return url;
}
public InputStream getResourceAsStream( String name )
{
InputStream is = super.getResourceAsStream( name );
return is;
}
public Class findClass( String name )
throws ClassNotFoundException
{
return super.findClass( name );
}
protected synchronized Class loadClass( String arg0, boolean arg1 )
throws ClassNotFoundException
{
return super.loadClass( arg0, arg1 );
}
}
}
\ No newline at end of file
......@@ -10,4 +10,8 @@ load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
[plexus.core.maven]
load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
......@@ -7,9 +7,11 @@ main is org.apache.maven.cli.MavenCli from plexus.core.maven
set maven.home default ${user.home}/m2
[plexus.core]
load ${maven.home}/core/*.jar
load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
[plexus.core.maven]
load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
\ No newline at end of file
load ${maven.home}/lib/*.jar
......@@ -43,8 +43,20 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<version>2.0.9</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
<dependency>
<!-- default dependency to 2.0.2 confuses IntelliJ. Otherwise this value doesn't really affect build or runtime. -->
......
......@@ -26,7 +26,6 @@ package hudson.maven.agent;
import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
import org.apache.maven.artifact.resolver.ArtifactResolutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.DefaultPluginManager;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
......
......@@ -37,165 +37,206 @@ THE SOFTWARE.
Now it is a plug-in that is installed by default, but can be disabled.</description>
<url>http://wiki.hudson-ci.org/display/HUDSON/Maven+2+Project+Plugin</url>
<dependencies>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>hudson-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>maven-agent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven2.1-interceptor</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven-embedder</artifactId>
<version>2.0.4-hudson-1</version>
<!--exclusions> These are needed for Maven embedder to resolve parent POMs in remote repositories
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
</exclusion>
</exclusions-->
<exclusions>
<exclusion><!-- we'll add our own patched version. see http://www.nabble.com/Issue-1680-td18383889.html -->
<groupId>jtidy</groupId>
<artifactId>jtidy</artifactId>
</exclusion>
<exclusion>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<!-- we bundle our own version below -->
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!-- commonly used wagon provider -->
<groupId>org.jvnet.hudson</groupId>
<dependencies>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>hudson-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>maven-agent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven-interceptor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven2.1-interceptor</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven3-agent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven3-listener</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.0-SNAPSHOT</version>
<!--exclusions> These are needed for Maven embedder to resolve parent POMs in remote repositories
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
</exclusion>
</exclusions-->
<exclusions>
<exclusion><!-- we'll add our own patched version. see http://www.nabble.com/Issue-1680-td18383889.html -->
<groupId>jtidy</groupId>
<artifactId>jtidy</artifactId>
</exclusion>
<exclusion>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<!-- we bundle our own version below -->
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav</artifactId>
<version>1.0-beta-2-hudson-1</version>
<exclusions>
<exclusion>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</exclusion>
</exclusions>
</dependency>
<build>
<!--
Since new versions need to overwrite old versions, it's better
not to have version number in the .hpi file name.
-->
<finalName>${project.artifactId}</finalName>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.jvnet.hudson.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<version>1.54</version>
<extensions>true</extensions>
<configuration>
<showDeprecation>true</showDeprecation>
<disabledTestInjection>true</disabledTestInjection>
</configuration>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<version>1.12</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<fileMask>Messages.properties</fileMask>
<outputDirectory>target/generated-sources/localizer</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>cobertura2</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.4-apb-SNAPSHOT</version>
<inherited>true</inherited>
<dependency>
<!-- commonly used wagon provider -->
<groupId>org.jvnet.hudson</groupId>
<artifactId>wagon-webdav</artifactId>
<version>1.0-beta-2-hudson-1</version>
<exclusions>
<exclusion>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<!--
Since new versions need to overwrite old versions, it's better
not to have version number in the .hpi file name.
-->
<finalName>${project.artifactId}</finalName>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.jvnet.hudson.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<version>1.54</version>
<extensions>true</extensions>
<configuration>
<showDeprecation>true</showDeprecation>
<disabledTestInjection>true</disabledTestInjection>
</configuration>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<version>1.12</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<fileMask>Messages.properties</fileMask>
<outputDirectory>target/generated-sources/localizer</outputDirectory>
</configuration>
<executions>
<execution>
<id>coverage-instrument</id>
<phase>process-test-classes</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>coverage-report</id>
<phase>test</phase>
<goals>
<goal>generate-report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>cobertura2</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.4-apb-SNAPSHOT</version>
<inherited>true</inherited>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
<executions>
<execution>
<id>coverage-instrument</id>
<phase>process-test-classes</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>coverage-report</id>
<phase>test</phase>
<goals>
<goal>generate-report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.remoting.DelegatingCallable;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
/**
* @author Olivier Lamy
*
*/
public abstract class AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Goals to be executed in this Maven execution.
*/
protected final List<String> goals;
/**
* Hudson-defined system properties. These will be made available to Maven,
* and accessible as if they are specified as -Dkey=value
*/
protected final Map<String,String> systemProps;
/**
* Where error messages and so on are sent.
*/
protected final BuildListener listener;
protected AbstractMavenBuilder(BuildListener listener, List<String> goals, Map<String, String> systemProps) {
this.listener = listener;
this.goals = goals;
this.systemProps = systemProps;
}
protected String formatArgs(List<String> args) {
StringBuilder buf = new StringBuilder("Executing Maven: ");
for (String arg : args) {
final String argPassword = "-Dpassword=" ;
String filteredArg = arg ;
// check if current arg is password arg. Then replace password by *****
if (arg.startsWith(argPassword)) {
filteredArg=argPassword+"*********";
}
buf.append(' ').append(filteredArg);
}
return buf.toString();
}
protected String format(NumberFormat n, long nanoTime) {
return n.format(nanoTime/1000000);
}
// since reporters might be from plugins, use the uberjar to resolve them.
public ClassLoader getClassLoader() {
return Hudson.getInstance().getPluginManager().uberClassLoader;
}
}
......@@ -24,22 +24,25 @@
package hudson.maven;
import hudson.model.TaskListener;
import org.apache.maven.embedder.AbstractMavenEmbedderLogger;
import org.apache.maven.embedder.MavenEmbedderLogger;
import java.io.PrintStream;
import java.util.StringTokenizer;
import org.apache.maven.cli.MavenLoggerManager;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
/**
* {@link MavenEmbedderLogger} implementation that
* sends output to {@link TaskListener}.
*
* @author Kohsuke Kawaguchi
*/
public final class EmbedderLoggerImpl extends AbstractMavenEmbedderLogger {
public final class EmbedderLoggerImpl extends MavenLoggerManager {
private final PrintStream logger;
public EmbedderLoggerImpl(TaskListener listener) {
public EmbedderLoggerImpl(TaskListener listener, int threshold) {
super(new ConsoleLogger( threshold, "hudson-logger" ));
logger = listener.getLogger();
}
......@@ -57,22 +60,22 @@ public final class EmbedderLoggerImpl extends AbstractMavenEmbedderLogger {
}
public void debug(String message, Throwable throwable) {
print(message, throwable, LEVEL_DEBUG, "[DEBUG] ");
print(message, throwable, Logger.LEVEL_DEBUG, "[DEBUG] ");
}
public void info(String message, Throwable throwable) {
print(message, throwable, LEVEL_INFO, "[INFO ] ");
print(message, throwable, Logger.LEVEL_INFO, "[INFO ] ");
}
public void warn(String message, Throwable throwable) {
print(message, throwable, LEVEL_WARN, "[WARN ] ");
print(message, throwable, Logger.LEVEL_WARN, "[WARN ] ");
}
public void error(String message, Throwable throwable) {
print(message, throwable, LEVEL_ERROR, "[ERROR] ");
print(message, throwable, Logger.LEVEL_ERROR, "[ERROR] ");
}
public void fatalError(String message, Throwable throwable) {
print(message, throwable, LEVEL_FATAL, "[FATAL] ");
print(message, throwable, Logger.LEVEL_FATAL, "[FATAL] ");
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.remoting.Channel;
import hudson.remoting.DelegatingCallable;
import hudson.remoting.Future;
import hudson.util.IOException2;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.apache.maven.execution.AbstractExecutionListener;
import org.apache.maven.execution.ExecutionEvent;
import org.apache.maven.execution.ExecutionListener;
import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
import org.jvnet.hudson.maven3.listeners.HudsonMavenExecutionResult;
/**
* @author Olivier Lamy
*
*/
public class Maven3Builder extends AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Flag needs to be set at the constructor, so that this reflects
* the setting at master.
*/
private final boolean profile = MavenProcessFactory.profile;
/**
* Record all asynchronous executions as they are scheduled,
* to make sure they are all completed before we finish.
*/
protected transient /*final*/ List<Future<?>> futures;
HudsonMavenExecutionResult mavenExecutionResult;
protected Maven3Builder(BuildListener listener, List<String> goals, Map<String, String> systemProps) {
super( listener, goals, systemProps );
}
public Result call()
throws IOException
{
try {
futures = new ArrayList<Future<?>>();
MavenExecutionListener mavenExecutionListener = new MavenExecutionListener( this );
Maven3Launcher.setMavenExecutionListener( mavenExecutionListener );
markAsSuccess = false;
// working around NPE when someone puts a null value into systemProps.
for (Map.Entry<String,String> e : systemProps.entrySet()) {
if (e.getValue()==null)
throw new IllegalArgumentException("System property "+e.getKey()+" has a null value");
System.getProperties().put(e.getKey(), e.getValue());
}
listener.getLogger().println(formatArgs(goals));
int r = Maven3Main.launch( goals.toArray(new String[goals.size()]));
// now check the completion status of async ops
boolean messageReported = false;
long startTime = System.nanoTime();
for (Future<?> f : futures) {
try {
if(!f.isDone() && !messageReported) {
messageReported = true;
// FIXME messages
listener.getLogger().println("maven builder waiting");
}
f.get();
} catch (InterruptedException e) {
// attempt to cancel all asynchronous tasks
for (Future<?> g : futures)
g.cancel(true);
// FIXME messages
listener.getLogger().println("build aborted");
return Result.ABORTED;
} catch (ExecutionException e) {
// FIXME messages
e.printStackTrace(listener.error("async build failed"));
}
}
mavenExecutionListener.overheadTime += System.nanoTime()-startTime;
futures.clear();
if(profile) {
NumberFormat n = NumberFormat.getInstance();
PrintStream logger = listener.getLogger();
logger.println("Total overhead was "+format(n,mavenExecutionListener.overheadTime)+"ms");
Channel ch = Channel.current();
logger.println("Class loading " +format(n,ch.classLoadingTime.get()) +"ms, "+ch.classLoadingCount+" classes");
logger.println("Resource loading "+format(n,ch.resourceLoadingTime.get())+"ms, "+ch.resourceLoadingCount+" times");
}
mavenExecutionResult = Maven3Launcher.getMavenExecutionResult();
PrintStream logger = listener.getLogger();
logger.println("Maven3Builder classLoaderDebug");
logger.println("getClass().getClassLoader(): " + getClass().getClassLoader());
if(r==0) {
logger.print( "r==0" );
markAsSuccess = true;
}
if(markAsSuccess) {
// FIXME message
//listener.getLogger().println(Messages.MavenBuilder_Failed());
listener.getLogger().println("success");
return Result.SUCCESS;
}
return Result.FAILURE;
} catch (NoSuchMethodException e) {
throw new IOException2(e);
} catch (IllegalAccessException e) {
throw new IOException2(e);
} catch (InvocationTargetException e) {
throw new IOException2(e);
} catch (ClassNotFoundException e) {
throw new IOException2(e);
} catch (Exception e) {
throw new IOException2(e);
}
}
// since reporters might be from plugins, use the uberjar to resolve them.
public ClassLoader getClassLoader() {
return Hudson.getInstance().getPluginManager().uberClassLoader;
}
private static final class MavenExecutionListener extends AbstractExecutionListener implements Serializable, ExecutionListener {
private final Maven3Builder maven3Builder;
/**
* Number of total nanoseconds {@link Maven3Builder} spent.
*/
long overheadTime;
public MavenExecutionListener(Maven3Builder listener) {
this.maven3Builder = listener;
}
/**
* @see org.apache.maven.execution.ExecutionListener#projectDiscoveryStarted(org.apache.maven.execution.ExecutionEvent)
*/
public void projectDiscoveryStarted( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#sessionStarted(org.apache.maven.execution.ExecutionEvent)
*/
public void sessionStarted( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#sessionEnded(org.apache.maven.execution.ExecutionEvent)
*/
public void sessionEnded( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#projectSkipped(org.apache.maven.execution.ExecutionEvent)
*/
public void projectSkipped( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#projectStarted(org.apache.maven.execution.ExecutionEvent)
*/
public void projectStarted( ExecutionEvent event )
{
maven3Builder.listener.getLogger().println( "projectStarted in MavenExecutionListener "
+ event.getProject().getGroupId() + ":"
+ event.getProject().getArtifactId() );
}
/**
* @see org.apache.maven.execution.ExecutionListener#projectSucceeded(org.apache.maven.execution.ExecutionEvent)
*/
public void projectSucceeded( ExecutionEvent event )
{
maven3Builder.listener.getLogger().println("projectSucceeded in adapter" );
}
/**
* @see org.apache.maven.execution.ExecutionListener#projectFailed(org.apache.maven.execution.ExecutionEvent)
*/
public void projectFailed( ExecutionEvent event )
{
maven3Builder.listener.getLogger().println("projectFailed" );
}
/**
* @see org.apache.maven.execution.ExecutionListener#mojoSkipped(org.apache.maven.execution.ExecutionEvent)
*/
public void mojoSkipped( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#mojoStarted(org.apache.maven.execution.ExecutionEvent)
*/
public void mojoStarted( ExecutionEvent event )
{
maven3Builder.listener.getLogger().println("mojoStarted " + event.getMojoExecution().getArtifactId());
}
/**
* @see org.apache.maven.execution.ExecutionListener#mojoSucceeded(org.apache.maven.execution.ExecutionEvent)
*/
public void mojoSucceeded( ExecutionEvent event )
{
maven3Builder.listener.getLogger().println("mojoSucceeded " + event.getMojoExecution().getArtifactId());
}
/**
* @see org.apache.maven.execution.ExecutionListener#mojoFailed(org.apache.maven.execution.ExecutionEvent)
*/
public void mojoFailed( ExecutionEvent event )
{
maven3Builder.listener.getLogger().println("mojoFailed " + event.getMojoExecution().getArtifactId());
}
/**
* @see org.apache.maven.execution.ExecutionListener#forkStarted(org.apache.maven.execution.ExecutionEvent)
*/
public void forkStarted( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#forkSucceeded(org.apache.maven.execution.ExecutionEvent)
*/
public void forkSucceeded( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#forkFailed(org.apache.maven.execution.ExecutionEvent)
*/
public void forkFailed( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#forkedProjectStarted(org.apache.maven.execution.ExecutionEvent)
*/
public void forkedProjectStarted( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#forkedProjectSucceeded(org.apache.maven.execution.ExecutionEvent)
*/
public void forkedProjectSucceeded( ExecutionEvent event )
{
}
/**
* @see org.apache.maven.execution.ExecutionListener#forkedProjectFailed(org.apache.maven.execution.ExecutionEvent)
*/
public void forkedProjectFailed( ExecutionEvent event )
{
}
}
public static boolean markAsSuccess;
private static final long serialVersionUID = 1L;
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import static hudson.Util.fixNull;
import hudson.AbortException;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Executor;
import hudson.model.Hudson;
import hudson.model.JDK;
import hudson.model.Node;
import hudson.model.Run.RunnerAbortedException;
import hudson.model.TaskListener;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.RemoteInputStream;
import hudson.remoting.RemoteOutputStream;
import hudson.remoting.SocketInputStream;
import hudson.remoting.SocketOutputStream;
import hudson.remoting.Which;
import hudson.slaves.Channels;
import hudson.tasks.Maven.MavenInstallation;
import hudson.util.ArgumentListBuilder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Arrays;
import java.util.logging.Logger;
import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
import org.kohsuke.stapler.framework.io.IOException2;
/**
* @author Olivier Lamy
*
*/
public class Maven3ProcessFactory implements ProcessCache.Factory
{
private final MavenModuleSet mms;
private final Launcher launcher;
/**
* Environment variables to be set to the maven process.
* The same variables are exposed to the system property as well.
*/
private final EnvVars envVars;
/**
* Optional working directory. Because of the process reuse, we can't always guarantee
* that the returned Maven process has this as the working directory. But for the
* aggregator style build, the process reuse is disabled, so in practice this always works.
*
* Also, Maven is supposed to work correctly regardless of the process current directory,
* so a good behaving maven project shouldn't rely on the current project.
*/
private final FilePath workDir;
Maven3ProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, FilePath workDir) {
this.mms = mms;
this.launcher = launcher;
this.envVars = envVars;
this.workDir = workDir;
}
/**
* Represents a bi-directional connection.
*
* <p>
* This implementation is remoting aware, so it can be safely sent to the remote callable object.
*
* <p>
* When we run Maven on a slave, the master may not have a direct TCP/IP connectivty to the slave.
* That means the {@link Channel} between the master and the Maven needs to be tunneled through
* the channel between master and the slave, then go to TCP socket to the Maven.
*/
private static final class Connection implements Serializable {
public InputStream in;
public OutputStream out;
Connection(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
private Object writeReplace() {
return new Connection(new RemoteInputStream(in),new RemoteOutputStream(out));
}
private Object readResolve() {
// ObjectInputStream seems to access data at byte-level and do not do any buffering,
// so if we are remoted, buffering would be crucial.
this.in = new BufferedInputStream(in);
this.out = new BufferedOutputStream(out);
return this;
}
private static final long serialVersionUID = 1L;
}
interface Acceptor {
Connection accept() throws IOException;
int getPort();
}
/**
* Opens a server socket and returns {@link Acceptor} so that
* we can accept a connection later on it.
*/
private static final class SocketHandler implements Callable<Acceptor,IOException> {
public Acceptor call() throws IOException {
return new AcceptorImpl();
}
private static final long serialVersionUID = 1L;
static final class AcceptorImpl implements Acceptor, Serializable {
private transient final ServerSocket serverSocket;
private transient Socket socket;
AcceptorImpl() throws IOException {
// open a TCP socket to talk to the launched Maven process.
// let the OS pick up a random open port
this.serverSocket = new ServerSocket();
serverSocket.bind(null); // new InetSocketAddress(InetAddress.getLocalHost(),0));
// prevent a hang at the accept method in case the forked process didn't start successfully
serverSocket.setSoTimeout(MavenProcessFactory.socketTimeOut);
}
public Connection accept() throws IOException {
socket = serverSocket.accept();
// we'd only accept one connection
serverSocket.close();
return new Connection(new SocketInputStream(socket),new SocketOutputStream(socket));
}
public int getPort() {
return serverSocket.getLocalPort();
}
/**
* When sent to the remote node, send a proxy.
*/
private Object writeReplace() {
return Channel.current().export(Acceptor.class, this);
}
}
}
/**
* Starts maven process.
*/
public ProcessCache.NewProcess newProcess(BuildListener listener, OutputStream out) throws IOException, InterruptedException {
if(MavenProcessFactory.debug)
listener.getLogger().println("Using env variables: "+ envVars);
try {
final Acceptor acceptor = launcher.getChannel().call(new SocketHandler());
final ArgumentListBuilder cmdLine = buildMavenAgentCmdLine(listener,acceptor.getPort());
String[] cmds = cmdLine.toCommandArray();
final Proc proc = launcher.launch().cmds(cmds).envs(envVars).stdout(out).pwd(workDir).start();
Connection con;
try {
con = acceptor.accept();
} catch (SocketTimeoutException e) {
// failed to connect. Is the process dead?
// if so, the error should have been provided by the launcher already.
// so abort gracefully without a stack trace.
if(!proc.isAlive())
throw new AbortException("Failed to launch Maven. Exit code = "+proc.join());
throw e;
}
return new ProcessCache.NewProcess(
Channels.forProcess("Channel to Maven "+ Arrays.toString(cmds),
Computer.threadPoolForRemoting, new BufferedInputStream(con.in), new BufferedOutputStream(con.out),
listener.getLogger(), proc),
proc);
} catch (IOException e) {
if(fixNull(e.getMessage()).contains("java: not found")) {
// diagnose issue #659
JDK jdk = mms.getJDK();
if(jdk==null)
throw new IOException2(mms.getDisplayName()+" is not configured with a JDK, but your PATH doesn't include Java",e);
}
throw e;
}
}
/**
* Builds the command line argument list to launch the maven process.
*
*/
private ArgumentListBuilder buildMavenAgentCmdLine(BuildListener listener,int tcpPort) throws IOException, InterruptedException {
MavenInstallation mvn = getMavenInstallation(listener);
if(mvn==null) {
listener.error("Maven version is not configured for this project. Can't determine which Maven to run");
throw new RunnerAbortedException();
}
if(mvn.getHome()==null) {
listener.error("Maven '%s' doesn't have its home set",mvn.getName());
throw new RunnerAbortedException();
}
// find classworlds.jar
String classWorldsJar = launcher.getChannel().call(new GetClassWorldsJar(mvn.getHome(),listener));
boolean isMaster = getCurrentNode()== Hudson.getInstance();
FilePath slaveRoot=null;
if(!isMaster)
slaveRoot = getCurrentNode().getRootPath();
ArgumentListBuilder args = new ArgumentListBuilder();
JDK jdk = getJava(listener);
if(jdk==null) {
args.add("java");
} else {
args.add(jdk.getHome()+"/bin/java"); // use JDK.getExecutable() here ?
}
if(MavenProcessFactory.debugPort!=0)
args.add("-Xrunjdwp:transport=dt_socket,server=y,address="+MavenProcessFactory.debugPort);
if(MavenProcessFactory.yjp)
args.add("-agentlib:yjpagent=tracing");
args.addTokenized(getMavenOpts());
args.add("-cp");
args.add(
(isMaster? Which.jarFile(Maven3Main.class).getAbsolutePath():slaveRoot.child("maven3-agent.jar").getRemote())+
(launcher.isUnix()?":":";")+classWorldsJar);
args.add(Maven3Main.class.getName());
// M2_HOME
args.add(mvn.getHome());
// remoting.jar
String remotingJar = launcher.getChannel().call(new GetRemotingJar());
if(remotingJar==null) {// this shouldn't be possible, but there are still reports indicating this, so adding a probe here.
listener.error("Failed to determine the location of slave.jar");
throw new RunnerAbortedException();
}
args.add(remotingJar);
args.add(isMaster?
Which.jarFile(Maven3Launcher.class).getAbsolutePath():
slaveRoot.child("maven3-listener.jar").getRemote());
// TCP/IP port to establish the remoting infrastructure
args.add(tcpPort);
return args;
}
public String getMavenOpts() {
String mavenOpts = mms.getMavenOpts();
if ((mavenOpts==null) || (mavenOpts.trim().length()==0)) {
Node n = getCurrentNode();
if (n!=null) {
try {
String localMavenOpts = n.toComputer().getEnvironment().get("MAVEN_OPTS");
if ((localMavenOpts!=null) && (localMavenOpts.trim().length()>0)) {
mavenOpts = localMavenOpts;
}
} catch (IOException e) {
} catch (InterruptedException e) {
// Don't do anything - this just means the slave isn't running, so we
// don't want to use its MAVEN_OPTS anyway.
}
}
}
return envVars.expand(mavenOpts);
}
public MavenInstallation getMavenInstallation(TaskListener log) throws IOException, InterruptedException {
MavenInstallation mi = mms.getMaven();
if (mi != null) mi = mi.forNode(getCurrentNode(), log).forEnvironment(envVars);
return mi;
}
public JDK getJava(TaskListener log) throws IOException, InterruptedException {
JDK jdk = mms.getJDK();
if (jdk != null) jdk = jdk.forNode(getCurrentNode(), log).forEnvironment(envVars);
return jdk;
}
/**
* Finds classworlds.jar
*/
private static final class GetClassWorldsJar implements Callable<String,IOException> {
private final String mvnHome;
private final TaskListener listener;
private GetClassWorldsJar(String mvnHome, TaskListener listener) {
this.mvnHome = mvnHome;
this.listener = listener;
}
public String call() throws IOException {
File home = new File(mvnHome);
if (MavenProcessFactory.debug)
listener.getLogger().println("Using mvnHome: "+ mvnHome);
File bootDir = new File(home, "boot");
File[] classworlds = bootDir.listFiles(CLASSWORLDS_FILTER);
if(classworlds==null || classworlds.length==0) {
// Maven 2.0.6 puts it to a different place
bootDir = new File(home, "boot");
classworlds = bootDir.listFiles(CLASSWORLDS_FILTER);
if(classworlds==null || classworlds.length==0) {
// FIXME use messages
//listener.error(Messages.MavenProcessFactory_ClassWorldsNotFound(home));
listener.error("classworld not found");
throw new RunnerAbortedException();
}
}
return classworlds[0].getAbsolutePath();
}
}
private static final class GetRemotingJar implements Callable<String,IOException> {
public String call() throws IOException {
return Which.jarFile(hudson.remoting.Launcher.class).getPath();
}
}
/**
* Returns the current {@link Node} on which we are buildling.
*/
private Node getCurrentNode() {
return Executor.currentExecutor().getOwner().getNode();
}
/**
* Locates classworlds jar file.
*
* Note that Maven 3.0 changed the name to plexus-classworlds
*
* <pre>
* $ find tools/ -name "plexus-classworlds*.jar"
* tools/maven-3.0-alpha-2/boot/plexus-classworlds-1.3.jar
* tools/maven-3.0-alpha-3/boot/plexus-classworlds-2.2.2.jar
* tools/maven-3.0-alpha-4/boot/plexus-classworlds-2.2.2.jar
* tools/maven-3.0-alpha-5/boot/plexus-classworlds-2.2.2.jar
* tools/maven-3.0-alpha-6/boot/plexus-classworlds-2.2.2.jar
* </pre>
*/
private static final FilenameFilter CLASSWORLDS_FILTER = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.contains("plexus-classworlds") && name.endsWith(".jar");
}
};
private static final Logger LOGGER = Logger.getLogger(MavenProcessFactory.class.getName());
}
......@@ -25,7 +25,6 @@ package hudson.maven;
import hudson.maven.agent.AbortException;
import hudson.maven.agent.Main;
import hudson.maven.agent.PluginManagerInterceptor;
import hudson.maven.agent.PluginManagerListener;
import hudson.maven.reporters.SurefireArchiver;
import hudson.model.BuildListener;
......@@ -40,6 +39,7 @@ import hudson.util.IOException2;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
......@@ -50,14 +50,12 @@ import org.apache.maven.BuildFailureException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.LifecycleExecutorInterceptor;
import org.apache.maven.lifecycle.LifecycleExecutorListener;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReport;
import org.codehaus.classworlds.NoSuchRealmException;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
......@@ -74,20 +72,8 @@ import org.codehaus.plexus.configuration.PlexusConfiguration;
* @author Kohsuke Kawaguchi
* @since 1.133
*/
public abstract class MavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Goals to be executed in this Maven execution.
*/
private final List<String> goals;
/**
* Hudson-defined system properties. These will be made available to Maven,
* and accessible as if they are specified as -Dkey=value
*/
private final Map<String,String> systemProps;
/**
* Where error messages and so on are sent.
*/
protected final BuildListener listener;
public abstract class MavenBuilder extends AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Flag needs to be set at the constructor, so that this reflects
......@@ -102,9 +88,7 @@ public abstract class MavenBuilder implements DelegatingCallable<Result,IOExcept
protected transient /*final*/ List<Future<?>> futures;
protected MavenBuilder(BuildListener listener, List<String> goals, Map<String, String> systemProps) {
this.listener = listener;
this.goals = goals;
this.systemProps = systemProps;
super( listener, goals, systemProps );
}
/**
......@@ -147,11 +131,17 @@ public abstract class MavenBuilder implements DelegatingCallable<Result,IOExcept
*/
public Result call() throws IOException {
try {
System.out.println("MavenBuilder in call " + Thread.currentThread().getContextClassLoader());
futures = new ArrayList<Future<?>>();
Adapter a = new Adapter(this);
// FIXME are we using maven 2 or 3
callSetListenerWithReflectOnInterceptors( a );
/*
PluginManagerInterceptor.setListener(a);
LifecycleExecutorInterceptor.setListener(a);
*/
markAsSuccess = false;
// working around NPE when someone puts a null value into systemProps.
......@@ -202,46 +192,78 @@ public abstract class MavenBuilder implements DelegatingCallable<Result,IOExcept
listener.getLogger().println(Messages.MavenBuilder_Failed());
return Result.SUCCESS;
}
return Result.FAILURE;
} catch (NoSuchMethodException e) {
throw new IOException2(e);
} catch (IllegalAccessException e) {
throw new IOException2(e);
} catch (NoSuchRealmException e) {
} catch (RuntimeException e) {
throw new IOException2(e);
} catch (InvocationTargetException e) {
throw new IOException2(e);
} catch (ClassNotFoundException e) {
throw new IOException2(e);
} finally {
PluginManagerInterceptor.setListener(null);
LifecycleExecutorInterceptor.setListener(null);
//PluginManagerInterceptor.setListener(null);
//LifecycleExecutorInterceptor.setListener(null);
callSetListenerWithReflectOnInterceptorsQuietly( null );
}
}
private String formatArgs(List<String> args) {
StringBuilder buf = new StringBuilder("Executing Maven: ");
for (String arg : args) {
final String argPassword = "-Dpassword=" ;
String filteredArg = arg ;
// check if current arg is password arg. Then replace password by *****
if (arg.startsWith(argPassword)) {
filteredArg=argPassword+"*********";
}
buf.append(' ').append(filteredArg);
}
return buf.toString();
}
private String format(NumberFormat n, long nanoTime) {
return n.format(nanoTime/1000000);
private void callSetListenerWithReflectOnInterceptors( PluginManagerListener pluginManagerListener )
throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException
{
Class<?> pluginManagerInterceptorClazz =
Thread.currentThread().getContextClassLoader().loadClass( "hudson.maven.agent.PluginManagerInterceptor" );
Method setListenerMethod =
pluginManagerInterceptorClazz.getMethod( "setListener",
new Class[] { Thread.currentThread().getContextClassLoader().loadClass( "hudson.maven.agent.PluginManagerListener" ) } );
setListenerMethod.invoke( null, new Object[] { pluginManagerListener } );
Class<?> lifecycleInterceptorClazz =
Thread.currentThread().getContextClassLoader().loadClass( "org.apache.maven.lifecycle.LifecycleExecutorInterceptor" );
setListenerMethod =
lifecycleInterceptorClazz.getMethod( "setListener",
new Class[] { Thread.currentThread().getContextClassLoader().loadClass( "org.apache.maven.lifecycle.LifecycleExecutorListener" ) } );
setListenerMethod.invoke( null, new Object[] { pluginManagerListener } );
}
private void callSetListenerWithReflectOnInterceptorsQuietly( PluginManagerListener pluginManagerListener )
{
try
{
callSetListenerWithReflectOnInterceptors(pluginManagerListener);
}
catch ( SecurityException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( IllegalArgumentException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( ClassNotFoundException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( NoSuchMethodException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( IllegalAccessException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch ( InvocationTargetException e )
{
throw new RuntimeException( e.getMessage(), e );
}
}
// since reporters might be from plugins, use the uberjar to resolve them.
public ClassLoader getClassLoader() {
return Hudson.getInstance().getPluginManager().uberClassLoader;
}
/**
* Receives {@link PluginManagerListener} and {@link LifecycleExecutorListener} events
......
......@@ -26,8 +26,8 @@ package hudson.maven;
import hudson.Extension;
import hudson.FilePath;
import hudson.maven.agent.Main;
import hudson.maven.agent.PluginManagerInterceptor;
import hudson.maven.agent.Maven21Interceptor;
import hudson.maven.agent.PluginManagerInterceptor;
import hudson.model.Computer;
import hudson.model.TaskListener;
import hudson.remoting.Channel;
......@@ -38,8 +38,12 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Zip;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
/**
* When a slave is connected, copy <tt>maven-agent.jar</tt> and <tt>maven-intercepter.jar</tt>
......@@ -52,8 +56,13 @@ public class MavenComputerListener extends ComputerListener {
public void preOnline(Computer c, Channel channel,FilePath root, TaskListener listener) throws IOException, InterruptedException {
PrintStream logger = listener.getLogger();
copyJar(logger, root, Main.class, "maven-agent");
copyJar(logger, root, Maven3Main.class, "maven3-agent");
copyJar(logger, root, Maven3Launcher.class, "maven3-listener");
copyJar(logger, root, PluginManagerInterceptor.class, "maven-interceptor");
copyJar(logger, root, Maven21Interceptor.class, "maven2.1-interceptor");
// FIXME not needed
copyJar(logger, root, ClassWorld.class, "plexus-classworld");
copyJar(logger, root, AntClassLoader.class, "maven-plugin-ant");
}
/**
......
......@@ -24,13 +24,29 @@
*/
package hudson.maven;
import hudson.*;
import static hudson.model.Result.FAILURE;
import hudson.AbortException;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.Launcher;
import hudson.Util;
import hudson.maven.MavenBuild.ProxyImpl2;
import hudson.maven.reporters.MavenFingerprinter;
import hudson.maven.reporters.MavenMailer;
import hudson.model.*;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Cause.UpstreamCause;
import hudson.model.Computer;
import hudson.model.Environment;
import hudson.model.Fingerprint;
import hudson.model.Hudson;
import hudson.model.ParametersAction;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
import hudson.scm.ChangeLogSet;
......@@ -40,8 +56,30 @@ import hudson.tasks.Maven.MavenInstallation;
import hudson.util.ArgumentListBuilder;
import hudson.util.IOUtils;
import hudson.util.StreamTaskListener;
import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.BuildFailureException;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.lifecycle.LifecycleExecutionException;
......@@ -50,15 +88,6 @@ import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.apache.commons.io.FilenameUtils;
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import static hudson.model.Result.FAILURE;
/**
* {@link Build} for {@link MavenModuleSet}.
......@@ -371,6 +400,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
PrintStream logger = listener.getLogger();
Result r = null;
try {
EnvVars envVars = getEnvironment(listener);
MavenInstallation mvn = project.getMaven();
if(mvn==null)
......@@ -379,6 +409,8 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
mvn = mvn.forEnvironment(envVars).forNode(Computer.currentComputer().getNode(), listener);
String mavenVersion = getModuleRoot().act( new MavenVersionCallable( mvn.getHome() ));
if(!project.isAggregatorStyleBuild()) {
parsePoms(listener, logger, envVars, mvn);
// start module builds
......@@ -417,9 +449,9 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
// we act as if incrementalBuild is not set if there are no changes.
if (!MavenModuleSetBuild.this.getChangeSet().isEmptySet()
&& project.isIncrementalBuild()) {
// If there are changes for this module, add it.
// Also add it if we've never seen this module before,
// or if the previous build of this module failed or was unstable.
//If there are changes for this module, add it.
// Also add it if we've never seen this module before,
// or if the previous build of this module failed or was unstable.
if ((mb.getPreviousBuiltBuild() == null) ||
(!getChangeSetFor(m).isEmpty())
|| (mb.getPreviousBuiltBuild().getResult().isWorseThan(Result.SUCCESS))) {
......@@ -443,9 +475,21 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
if(!pom.exists() && parentLoc.exists())
pom = parentLoc;
ProcessCache.MavenProcess process = MavenBuild.mavenProcessCache.get(launcher.getChannel(), slistener,
ProcessCache.MavenProcess process = null;
boolean maven3orLater = new ComparableVersion (mavenVersion).compareTo( new ComparableVersion ("3.0") ) >= 0;
if (maven3orLater)
{
LOGGER.info( "using maven 3 " + mavenVersion );
process = MavenBuild.mavenProcessCache.get(launcher.getChannel(), slistener,
new Maven3ProcessFactory(project,launcher,envVars,pom.getParent()));
} else
{
process = MavenBuild.mavenProcessCache.get(launcher.getChannel(), slistener,
new MavenProcessFactory(project,launcher,envVars,pom.getParent()));
}
ArgumentListBuilder margs = new ArgumentListBuilder().add("-B").add("-f", pom.getRemote());
if(project.usesPrivateRepository())
margs.add("-Dmaven.repo.local="+getWorkspace().child(".repository"));
......@@ -471,18 +515,34 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
}
margs.addTokenized(envVars.expand(project.getGoals()));
Builder builder = new Builder(slistener, proxies, project.sortedActiveModules, margs.toList(), envVars);
MavenProbeAction mpa=null;
try {
mpa = new MavenProbeAction(project,process.channel);
addAction(mpa);
r = process.call(builder);
return r;
} finally {
builder.end(launcher);
getActions().remove(mpa);
process.discard();
if (maven3orLater)
{
Maven3Builder maven3Builder = new Maven3Builder( slistener, margs.toList(), envVars );
MavenProbeAction mpa=null;
try {
mpa = new MavenProbeAction(project,process.channel);
addAction(mpa);
r = process.call(maven3Builder);
return r;
} finally {
//builder.end(launcher);
getActions().remove(mpa);
process.discard();
}
} else {
Builder builder = new Builder(slistener, proxies, project.sortedActiveModules, margs.toList(), envVars);
MavenProbeAction mpa=null;
try {
mpa = new MavenProbeAction(project,process.channel);
addAction(mpa);
r = process.call(builder);
return r;
} finally {
builder.end(launcher);
getActions().remove(mpa);
process.discard();
}
}
} finally {
if (r != null) {
......@@ -691,6 +751,7 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
@Override
public Result call() throws IOException {
try {
System.out.println("Builder extends MavenBuilder in call " + Thread.currentThread().getContextClassLoader());
return super.call();
} finally {
if(lastProxy!=null)
......@@ -916,7 +977,6 @@ public class MavenModuleSetBuild extends AbstractMavenBuild<MavenModuleSet,Maven
for (PomInfo pi : infos)
pi.cutCycle();
embedder.stop();
return infos;
} catch (MavenEmbedderException e) {
throw new MavenExecutionException(e);
......
......@@ -70,6 +70,9 @@ import java.nio.charset.UnsupportedCharsetException;
import java.util.Arrays;
import java.util.logging.Logger;
import org.apache.tools.ant.AntClassLoader;
import org.codehaus.plexus.classworlds.ClassWorld;
/**
* Launches the maven process.
......@@ -169,7 +172,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
this.serverSocket = new ServerSocket();
serverSocket.bind(null); // new InetSocketAddress(InetAddress.getLocalHost(),0));
// prevent a hang at the accept method in case the forked process didn't start successfully
serverSocket.setSoTimeout(30*1000);
serverSocket.setSoTimeout(socketTimeOut);
}
public Connection accept() throws IOException {
......@@ -200,6 +203,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
if(debug)
listener.getLogger().println("Using env variables: "+ envVars);
try {
//launcher.getChannel().export( type, instance )
final Acceptor acceptor = launcher.getChannel().call(new SocketHandler());
Charset charset;
try {
......@@ -283,9 +287,17 @@ final class MavenProcessFactory implements ProcessCache.Factory {
args.addTokenized(getMavenOpts());
args.add("-cp");
args.add(
(isMaster? Which.jarFile(Main.class).getAbsolutePath():slaveRoot.child("maven-agent.jar").getRemote())+
(launcher.isUnix()?":":";")+classWorldsJar);
String classPath =
( isMaster ? Which.jarFile( Main.class ).getAbsolutePath()
: slaveRoot.child( "maven-agent.jar" ).getRemote() )
+ ( launcher.isUnix() ? ":" : ";" )
+ ( isMaster ? Which.jarFile( ClassWorld.class ).getAbsolutePath()
: slaveRoot.child( "plexus-classworld.jar" ).getRemote() )
+ ( launcher.isUnix() ? ":" : ";" )
+ ( isMaster ? Which.jarFile( AntClassLoader.class ).getAbsolutePath()
: slaveRoot.child( "maven-plugin-ant.jar" ).getRemote() );
args.add(classPath);
//+classWorldsJar);
args.add(Main.class.getName());
// M2_HOME
......@@ -313,7 +325,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
Which.jarFile(Maven21Interceptor.class).getAbsolutePath():
slaveRoot.child("maven2.1-interceptor.jar").getRemote());
}
return args;
}
......@@ -440,6 +452,9 @@ final class MavenProcessFactory implements ProcessCache.Factory {
if(port!=null)
debugPort = Integer.parseInt(port);
}
public static int socketTimeOut = Integer.parseInt( System.getProperty( "hudson.maven.socketTimeOut", Integer.toString( 30*1000 ) ) );
private static final Logger LOGGER = Logger.getLogger(MavenProcessFactory.class.getName());
}
......@@ -25,32 +25,32 @@ package hudson.maven;
import hudson.AbortException;
import hudson.Util;
import hudson.model.BuildListener;
import hudson.model.TaskListener;
import hudson.model.AbstractProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.TaskListener;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.Maven.ProjectWithMaven;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.embedder.MavenEmbedderLogger;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.commons.io.IOUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
/**
* @author Kohsuke Kawaguchi
*/
......@@ -147,21 +147,10 @@ public class MavenUtil {
*/
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties,
String privateRepository, File alternateSettings) throws MavenEmbedderException, IOException {
MavenEmbedder maven = new MavenEmbedder(mavenHome);
ClassLoader cl = MavenUtil.class.getClassLoader();
maven.setClassLoader(new MaskingClassLoader(cl));
EmbedderLoggerImpl logger = new EmbedderLoggerImpl(listener);
if(debugMavenEmbedder) logger.setThreshold(MavenEmbedderLogger.LEVEL_DEBUG);
maven.setLogger(logger);
{
Enumeration<URL> e = cl.getResources("META-INF/plexus/components.xml");
while (e.hasMoreElements()) {
URL url = e.nextElement();
LOGGER.fine("components.xml from "+url);
}
}
MavenRequest mavenRequest = new MavenRequest();
// make sure ~/.m2 exists to avoid http://www.nabble.com/BUG-Report-tf3401736.html
File m2Home = new File(MavenEmbedder.userHome, ".m2");
m2Home.mkdirs();
......@@ -170,15 +159,41 @@ public class MavenUtil {
"\nSee https://hudson.dev.java.net/cannot-create-.m2.html");
if (privateRepository!=null)
maven.setLocalRepositoryDirectory(new File(privateRepository));
mavenRequest.setLocalRepositoryPath( privateRepository);
maven.setProfiles(profiles);
if (profiles != null)
{
mavenRequest.setProfiles(Arrays.asList( StringUtils.split( profiles, "," ) ));
}
if (alternateSettings!=null)
maven.setAlternateSettings(alternateSettings);
mavenRequest.setUserSettingsFile( alternateSettings.getAbsolutePath() );
// TODO olamy check this sould be userProperties
mavenRequest.setSystemProperties(systemProperties);
EmbedderLoggerImpl logger =
new EmbedderLoggerImpl( listener, debugMavenEmbedder ? org.codehaus.plexus.logging.Logger.LEVEL_DEBUG
: org.codehaus.plexus.logging.Logger.LEVEL_INFO );
mavenRequest.setMavenLoggerManager( logger );
ClassLoader cl = MavenUtil.class.getClassLoader();
// TODO check this MaskingClassLoader with maven 3 artifacts
MavenEmbedder maven = new MavenEmbedder( new MaskingClassLoader(cl), mavenRequest );
{
Enumeration<URL> e = cl.getResources("META-INF/plexus/components.xml");
while (e.hasMoreElements()) {
URL url = e.nextElement();
LOGGER.fine("components.xml from "+url);
}
}
maven.setSystemProperties(systemProperties);
maven.start();
return maven;
}
......@@ -198,11 +213,12 @@ public class MavenUtil {
*
* @throws AbortException
* errors will be reported to the listener and the exception thrown.
* @throws MavenEmbedderException
*/
public static void resolveModules(MavenEmbedder embedder, MavenProject project,
String rel, Map<MavenProject,String> relativePathInfo,
BuildListener listener, boolean nonRecursive) throws ProjectBuildingException,
AbortException {
AbortException, MavenEmbedderException {
File basedir = project.getFile().getParentFile();
relativePathInfo.put(project,rel);
......
package hudson.maven;
/*
* The MIT License
*
* Copyright (c) 2004-2010, Sun Microsystems, Inc. Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import hudson.remoting.Callable;
import java.io.File;
import java.io.IOException;
import org.kohsuke.stapler.framework.io.IOException2;
/**
*
* @author Olivier Lamy
*
*/
public class MavenVersionCallable
implements Callable<String, IOException>
{
private final String mavenHome;
public MavenVersionCallable( String mavenHome )
{
this.mavenHome = mavenHome;
}
public String call()
throws IOException
{
try
{
return MavenEmbedderUtils.getMavenVersion( new File(mavenHome) );
}
catch ( MavenEmbedderException e )
{
throw new IOException2( e );
}
}
}
......@@ -126,13 +126,13 @@ public class MojoInfo {
public <T> T getConfigurationValue(String configName, Class<T> type) throws ComponentConfigurationException {
PlexusConfiguration child = configuration.getChild(configName);
if(child==null) return null; // no such config
ConfigurationConverter converter = converterLookup.lookupConverterForType(type);
return type.cast(converter.fromConfiguration(converterLookup,child,type,
// the implementation seems to expect the type of the bean for which the configuration is done
// in this parameter, but we have no such type. So passing in a dummy
Object.class,
mojoExecution.getMojoDescriptor().getPluginDescriptor().getClassRealm().getClassLoader(),
mojoExecution.getMojoDescriptor().getPluginDescriptor().getClassRealm(),
expressionEvaluator));
}
......
......@@ -23,8 +23,8 @@
*/
package hudson.maven;
import hudson.Launcher;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.maven.reporters.MavenAbstractArtifactRecord;
import hudson.model.AbstractBuild;
......@@ -32,22 +32,23 @@ import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.tasks.BuildStepMonitor;
import hudson.util.FormValidation;
import java.io.IOException;
import net.sf.json.JSONObject;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.embedder.MavenEmbedderException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
/**
* {@link Publisher} for {@link MavenModuleSetBuild} to deploy artifacts
......@@ -108,7 +109,7 @@ public class RedeployPublisher extends Recorder {
MavenEmbedder embedder = MavenUtil.createEmbedder(listener,build);
ArtifactRepositoryLayout layout =
(ArtifactRepositoryLayout) embedder.getContainer().lookup( ArtifactRepositoryLayout.ROLE,"default");
(ArtifactRepositoryLayout) embedder.lookup( ArtifactRepositoryLayout.ROLE,"default");
ArtifactRepositoryFactory factory =
(ArtifactRepositoryFactory) embedder.lookup(ArtifactRepositoryFactory.ROLE);
......@@ -117,7 +118,6 @@ public class RedeployPublisher extends Recorder {
mar.deploy(embedder,repository,listener);
embedder.stop();
return true;
} catch (MavenEmbedderException e) {
e.printStackTrace(listener.error(e.getMessage()));
......
......@@ -25,40 +25,42 @@ package hudson.maven.reporters;
import hudson.console.AnnotatedLargeText;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenUtil;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BallColor;
import hudson.model.BuildBadgeAction;
import hudson.model.Result;
import hudson.model.TaskAction;
import hudson.model.TaskListener;
import hudson.model.TaskThread;
import hudson.model.BuildBadgeAction;
import hudson.model.TaskThread.ListenerAndText;
import hudson.security.Permission;
import hudson.security.ACL;
import hudson.security.Permission;
import hudson.util.Iterators;
import hudson.widgets.HistoryWidget;
import hudson.widgets.HistoryWidget.Adapter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletException;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.embedder.MavenEmbedderException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpRedirect;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* UI to redeploy artifacts after the fact.
......@@ -204,7 +206,7 @@ public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>>
try {
MavenEmbedder embedder = MavenUtil.createEmbedder(listener,getBuild());
ArtifactRepositoryLayout layout =
(ArtifactRepositoryLayout) embedder.getContainer().lookup( ArtifactRepositoryLayout.ROLE,"default");
(ArtifactRepositoryLayout) embedder.lookup( ArtifactRepositoryLayout.class,"default");
ArtifactRepositoryFactory factory =
(ArtifactRepositoryFactory) embedder.lookup(ArtifactRepositoryFactory.ROLE);
......@@ -213,7 +215,6 @@ public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>>
deploy(embedder,repository,listener);
embedder.stop();
record.result = Result.SUCCESS;
} finally {
if(record.result==null)
......
......@@ -26,20 +26,21 @@ package hudson.maven.reporters;
import hudson.maven.MavenAggregatedReport;
import hudson.maven.MavenBuild;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenModule;
import hudson.maven.MavenModuleSet;
import hudson.maven.MavenModuleSetBuild;
import hudson.model.Action;
import hudson.model.TaskListener;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.embedder.MavenEmbedderException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
/**
* Redeploy action for the entire {@link MavenModuleSetBuild}.
*
......
......@@ -36,11 +36,14 @@ import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import com.google.common.collect.Maps;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.logging.Logger;
/**
......@@ -145,14 +148,14 @@ public final class MavenArtifact implements Serializable {
// in the repository during deployment. So simulate that behavior if that's necessary.
final String canonicalExtension = canonicalName.substring(canonicalName.lastIndexOf('.')+1);
ArtifactHandler ah = handlerManager.getArtifactHandler(type);
// Fix for HUDSON-3814 - changed from comparing against canonical extension to canonicalName.endsWith.
if(!canonicalName.endsWith(ah.getExtension())) {
handlerManager.addHandlers(Collections.singletonMap(type,
new DefaultArtifactHandler(type) {
Map<String,ArtifactHandler> handlers = Maps.newHashMap();
handlers.put( type, new DefaultArtifactHandler(type) {
public String getExtension() {
return canonicalExtension;
}
}));
} } );
// Fix for HUDSON-3814 - changed from comparing against canonical extension to canonicalName.endsWith.
if(!canonicalName.endsWith(ah.getExtension())) {
handlerManager.addHandlers(handlers);
}
Artifact a = factory.createArtifactWithClassifier(groupId, artifactId, version, type, classifier);
......
......@@ -27,10 +27,17 @@ import hudson.maven.AggregatableAction;
import hudson.maven.MavenAggregatedReport;
import hudson.maven.MavenBuild;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenModule;
import hudson.maven.MavenModuleSetBuild;
import hudson.model.Action;
import hudson.model.TaskListener;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.deployer.ArtifactDeployer;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
......@@ -39,15 +46,9 @@ import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.installer.ArtifactInstallationException;
import org.apache.maven.artifact.installer.ArtifactInstaller;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
/**
* {@link Action} that remembers {@link MavenArtifact artifact}s that are built.
*
......@@ -105,9 +106,9 @@ public class MavenArtifactRecord extends MavenAbstractArtifactRecord<MavenBuild>
@Override
public void deploy(MavenEmbedder embedder, ArtifactRepository deploymentRepository, TaskListener listener) throws MavenEmbedderException, IOException, ComponentLookupException, ArtifactDeploymentException {
ArtifactHandlerManager handlerManager = (ArtifactHandlerManager) embedder.lookup(ArtifactHandlerManager.ROLE);
ArtifactDeployer deployer = (ArtifactDeployer) embedder.lookup(ArtifactDeployer.ROLE);
ArtifactFactory factory = (ArtifactFactory) embedder.lookup(ArtifactFactory.ROLE);
ArtifactHandlerManager handlerManager = embedder.lookup(ArtifactHandlerManager.class);
ArtifactDeployer deployer = embedder.lookup(ArtifactDeployer.class);
ArtifactFactory factory = embedder.lookup(ArtifactFactory.class);
PrintStream logger = listener.getLogger();
Artifact main = mainArtifact.toArtifact(handlerManager,factory,parent);
......@@ -129,9 +130,9 @@ public class MavenArtifactRecord extends MavenAbstractArtifactRecord<MavenBuild>
* Installs the artifact to the local Maven repository.
*/
public void install(MavenEmbedder embedder) throws MavenEmbedderException, IOException, ComponentLookupException, ArtifactInstallationException {
ArtifactHandlerManager handlerManager = (ArtifactHandlerManager) embedder.lookup(ArtifactHandlerManager.ROLE);
ArtifactInstaller installer = (ArtifactInstaller) embedder.lookup(ArtifactInstaller.class.getName());
ArtifactFactory factory = (ArtifactFactory) embedder.lookup(ArtifactFactory.class.getName());
ArtifactHandlerManager handlerManager = embedder.lookup(ArtifactHandlerManager.class);
ArtifactInstaller installer = embedder.lookup(ArtifactInstaller.class);
ArtifactFactory factory = embedder.lookup(ArtifactFactory.class);
Artifact main = mainArtifact.toArtifact(handlerManager,factory,parent);
if(!isPOM())
......
.settings
.project
target
.classpath
build
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>pom</artifactId>
<version>1.381-SNAPSHOT</version>
</parent>
<artifactId>maven3-agent</artifactId>
<name>maven3-agent</name>
<dependencies>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven3-listener</artifactId>
<scope>provided</scope>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jvnet.hudson.maven3.agent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.codehaus.plexus.classworlds.launcher.Launcher;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
/**
* Entry point for launching Maven 3 and Hudson remoting in the same VM, in the
* classloader layout that Maven expects.
*
* <p>
* The actual Maven execution will be started by the program sent through
* remoting.
* </p>
*
* @author Kohsuke Kawaguchi
* @author Olivier Lamy
*/
public class Maven3Main {
/**
* Used to pass the classworld instance to the code running inside the
* remoting system.
*/
private static Launcher launcher;
public static void main(String[] args) throws Exception {
main(new File(args[0]), new File(args[1]),new File(args[2]),
Integer.parseInt(args[3]));
}
/**
*
* @param m2Home
* Maven2 installation. This is where we find Maven jars that
* we'll run.
* @param remotingJar
* Hudson's remoting.jar that we'll load.
* @param listenerJar
* maven-listener.jar that we'll load.
* @param tcpPort
* TCP socket that the launching Hudson will be listening to.
* This is used for the remoting communication.
* @param projectBuildLaunch
* launch the projectBuilder and not a mavenExecution
*/
public static void main(File m2Home, File remotingJar, File listenerJar,
int tcpPort) throws Exception {
// Unix master with Windows slave ends up passing path in Unix format,
// so convert it to Windows format now so that no one chokes with the
// path format later.
try {
m2Home = m2Home.getCanonicalFile();
} catch (IOException e) {
// ignore. We'll check the error later if m2Home exists anyway
}
if (!m2Home.exists()) {
System.err.println("No such directory exists: " + m2Home);
System.exit(1);
}
versionCheck();
// expose variables used in the classworlds configuration
System.setProperty("maven.home", m2Home.getPath());
System.setProperty("maven3.listener", (listenerJar != null ? listenerJar
: listenerJar).getPath());
// load the default realms
launcher = new Launcher();
launcher.setSystemClassLoader(Maven3Main.class.getClassLoader());
launcher.configure(Maven3Main.class
.getResourceAsStream("classworlds.conf"));
// create a realm for loading remoting subsystem.
// this needs to be able to see maven.
ClassRealm remoting = launcher.getWorld().newRealm( "hudson-remoting", launcher.getSystemClassLoader() );
remoting.setParentRealm(launcher.getWorld().getRealm("plexus.core"));
remoting.addURL(remotingJar.toURI().toURL());
final Socket s = new Socket((String) null, tcpPort);
Class remotingLauncher = remoting.loadClass("hudson.remoting.Launcher");
remotingLauncher.getMethod("main",
new Class[] { InputStream.class, OutputStream.class }).invoke(
null,
new Object[] {
// do partial close, since socket.getInputStream and
// getOutputStream doesn't do it by
new BufferedInputStream(new FilterInputStream(s
.getInputStream()) {
public void close() throws IOException {
s.shutdownInput();
}
}),
new BufferedOutputStream(new RealFilterOutputStream(s
.getOutputStream()) {
public void close() throws IOException {
s.shutdownOutput();
}
}) });
System.exit(0);
}
/**
* Called by the code in remoting to launch.
*/
public static int launch(String[] args) throws Exception {
try {
launcher.launch(args);
} catch (Throwable e)
{
e.printStackTrace();
throw new Exception( e );
}
return launcher.getExitCode();
}
/**
* Makes sure that this is Java5 or later.
*/
private static void versionCheck() {
String v = System.getProperty("java.class.version");
if (v != null) {
try {
if (Float.parseFloat(v) < 49.0) {
System.err
.println("Native maven support requires Java 1.5 or later, but this Maven is using "
+ System.getProperty("java.home"));
System.err.println("Please use the freestyle project.");
System.exit(1);
}
} catch (NumberFormatException e) {
// couldn't check.
}
}
}
}
\ No newline at end of file
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jvnet.hudson.maven3.agent;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FilterOutputStream;
/**
* JDK's {@link FilterOutputStream} has some real issues.
*
* @author Kohsuke Kawaguchi
*/
class RealFilterOutputStream extends FilterOutputStream {
public RealFilterOutputStream(OutputStream core) {
super(core);
}
public void write(byte[] b) throws IOException {
out.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
}
public void close() throws IOException {
out.close();
}
}
#
# mostly copied as-is from $MAVEN_HOME/bin/m2.conf
#
#main is org.apache.maven.cli.MavenCli from plexus.core.maven
main is org.jvnet.hudson.maven3.launcher.Maven3Launcher from plexus.core
set maven.home default ${user.home}/m2
[plexus.core]
load ${maven3.listener}
load ${maven.home}/lib/*.jar
\ No newline at end of file
.settings
.project
target
.classpath
build
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>pom</artifactId>
<version>1.381-SNAPSHOT</version>
</parent>
<artifactId>maven3-listener</artifactId>
<name>maven3-listener</name>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-metadata</artifactId>
<version>1.5.4</version>
<executions>
<execution>
<goals>
<goal>generate-metadata</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package org.apache.maven.cli;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.PrintStream;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.settings.building.SettingsBuildingException;
/**
* @author Olivier Lamy
* @since
*/
public interface MavenExecutionRequestBuilder
{
MavenExecutionRequest getMavenExecutionRequest( String[] args, PrintStream printStream )
throws MavenExecutionRequestPopulationException, SettingsBuildingException, MavenExecutionRequestsBuilderException;
}
package org.apache.maven.cli;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @author Olivier Lamy
* @since
*/
public class MavenExecutionRequestsBuilderException
extends Exception
{
public MavenExecutionRequestsBuilderException(String message, Throwable exception)
{
super( message, exception );
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc.,
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.jvnet.hudson.maven3.launcher;
import org.apache.maven.Maven;
import org.apache.maven.cli.MavenExecutionRequestBuilder;
import org.apache.maven.cli.MavenLoggerManager;
import org.apache.maven.cli.PrintStreamLogger;
import org.apache.maven.execution.ExecutionListener;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionResult;
import org.codehaus.plexus.ContainerConfiguration;
import org.codehaus.plexus.DefaultContainerConfiguration;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.jvnet.hudson.maven3.listeners.HudsonMavenExecutionResult;
/**
* @author olamy
*
*/
public class Maven3Launcher
{
private static HudsonMavenExecutionResult hudsonMavenExecutionResult;
private static ExecutionListener mavenExecutionListener;
public static ExecutionListener getMavenExecutionListener()
{
return mavenExecutionListener;
}
public static void setMavenExecutionListener( ExecutionListener listener )
{
mavenExecutionListener = listener;
}
public static HudsonMavenExecutionResult getMavenExecutionResult()
{
return hudsonMavenExecutionResult;
}
public static void setMavenExecutionResult( HudsonMavenExecutionResult result )
{
hudsonMavenExecutionResult = result;
}
public static int main( String[] args )
throws Exception
{
ClassLoader orig = Thread.currentThread().getContextClassLoader();
try
{
ClassRealm containerRealm = (ClassRealm) Thread.currentThread().getContextClassLoader();
ContainerConfiguration cc = new DefaultContainerConfiguration().setName( "maven" )
.setRealm( containerRealm );
DefaultPlexusContainer container = new DefaultPlexusContainer( cc );
MavenLoggerManager mavenLoggerManager = new MavenLoggerManager( new PrintStreamLogger( System.out ) );
container.setLoggerManager( mavenLoggerManager );
Maven maven = (Maven) container.lookup( "org.apache.maven.Maven", "default" );
MavenExecutionRequest request = getMavenExecutionRequest( args, container );
hudsonMavenExecutionResult = new HudsonMavenExecutionResult( maven.execute( request ) );
System.out.println("---- mavenExecutionResult ----");
System.out.println( "mavenExecutionResult.getMavenProjectInfos().size() " + hudsonMavenExecutionResult.getMavenProjectInfos().size() );
System.out.println("---- mavenExecutionResult ----");
// we don't care about cli mavenExecutionResult will be study in the the plugin
return 0;// cli.doMain( args, null );
}
catch ( ComponentLookupException e )
{
throw new Exception( e.getMessage(), e );
}
finally
{
Thread.currentThread().setContextClassLoader( orig );
}
}
private static MavenExecutionRequest getMavenExecutionRequest( String[] args, DefaultPlexusContainer container )
throws Exception
{
MavenExecutionRequestBuilder mavenExecutionRequestBuilder = container
.lookup( MavenExecutionRequestBuilder.class );
MavenExecutionRequest request = mavenExecutionRequestBuilder.getMavenExecutionRequest( args, System.out );
if ( mavenExecutionListener != null )
{
request.setExecutionListener( mavenExecutionListener );
}
return request;
}
}
/**
*
*/
package org.jvnet.hudson.maven3.listeners;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.execution.BuildSummary;
import org.apache.maven.execution.MavenExecutionResult;
import org.apache.maven.project.MavenProject;
/**
* @author Olivier Lamy
* @since
*/
public class HudsonMavenExecutionResult implements Serializable
{
List<Throwable> throwables = new ArrayList<Throwable>();
List<MavenProjectInfo> mavenProjectInfos = new ArrayList<MavenProjectInfo>();
public HudsonMavenExecutionResult(MavenExecutionResult mavenExecutionResult)
{
if (mavenExecutionResult == null)
{
return;
}
throwables = mavenExecutionResult.getExceptions();
List<MavenProject> mavenProjects = mavenExecutionResult.getTopologicallySortedProjects();
for (MavenProject mavenProject : mavenProjects)
{
MavenProjectInfo mavenProjectInfo = new MavenProjectInfo( mavenProject );
mavenProjectInfos.add( mavenProjectInfo );
BuildSummary buildSummary = mavenExecutionResult.getBuildSummary( mavenProject );
mavenProjectInfo.setBuildTime( buildSummary.getTime() );
}
}
public List<Throwable> getThrowables()
{
return throwables;
}
public void setThrowables( List<Throwable> throwables )
{
this.throwables = throwables;
}
public List<MavenProjectInfo> getMavenProjectInfos()
{
return mavenProjectInfos;
}
public void setMavenProjectInfos( List<MavenProjectInfo> mavenProjectInfos )
{
this.mavenProjectInfos = mavenProjectInfos;
}
}
/**
*
*/
package org.jvnet.hudson.maven3.listeners;
import java.io.Serializable;
import java.util.List;
import org.apache.maven.project.ProjectBuildingResult;
/**
* @author <a href="mailto:Olivier.LAMY@accor.com">olamy</a>
* created 9 août 2010
* @since
* @version $Id$
*/
public class MavenProjectBuildResult implements Serializable
{
private MavenProjectInfo mavenProjectInfo;
public MavenProjectBuildResult()
{
// no op
}
public MavenProjectBuildResult( ProjectBuildingResult projectBuildingResult )
{
// no op
this.mavenProjectInfo = new MavenProjectInfo( projectBuildingResult.getProject() );
}
public MavenProjectInfo getMavenProjectInfo()
{
return mavenProjectInfo;
}
public void setMavenProjectInfo( MavenProjectInfo mavenProjectInfo )
{
this.mavenProjectInfo = mavenProjectInfo;
}
@Override
public String toString()
{
return mavenProjectInfo == null ? "null mavenProjectInfo" : this.mavenProjectInfo.toString();
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jvnet.hudson.maven3.listeners;
import java.io.Serializable;
import org.apache.maven.project.MavenProject;
/**
* @author <a href="mailto:Olivier.LAMY@accor.com">olamy</a>
* created 9 août 2010
* @since
* @version $Id$
*/
public class MavenProjectInfo implements Serializable
{
private String displayName;
private String groupId;
private String artifactId;
private String version;
private long buildTime;
public MavenProjectInfo()
{
// no-op
}
public MavenProjectInfo(MavenProject mavenProject)
{
this.displayName = mavenProject.getName();
this.groupId= mavenProject.getGroupId();
this.artifactId = mavenProject.getArtifactId();
this.version = mavenProject.getVersion();
}
public long getBuildTime()
{
return buildTime;
}
public void setBuildTime( long buildTime )
{
this.buildTime = buildTime;
}
public String getDisplayName()
{
return displayName;
}
public void setDisplayName( String displayName )
{
this.displayName = displayName;
}
public String getGroupId()
{
return groupId;
}
public void setGroupId( String groupId )
{
this.groupId = groupId;
}
public String getArtifactId()
{
return artifactId;
}
public void setArtifactId( String artifactId )
{
this.artifactId = artifactId;
}
public String getVersion()
{
return version;
}
public void setVersion( String version )
{
this.version = version;
}
@Override
public String toString()
{
return groupId + ":" + artifactId + ":" + version;
}
}
......@@ -46,6 +46,8 @@ THE SOFTWARE.
<module>ui-samples-plugin</module>
<module>maven-agent</module>
<module>maven-interceptor</module>
<module>maven3-agent</module>
<module>maven3-listener</module>
<module>war</module>
<module>test</module>
<module>cli</module>
......@@ -197,7 +199,9 @@ THE SOFTWARE.
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.0-beta-1</version>
<executions>
<execution>
<goals>
......@@ -248,10 +252,55 @@ THE SOFTWARE.
<optional>true</optional><!-- no need to have this at runtime -->
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<maven.version>2.0.9</maven.version>
<maven.embedder.version>2.0.4</maven.embedder.version>
<maven.version>3.0</maven.version>
<!-- *.html files are in UTF-8, and *.properties are in iso-8859-1, so this configuration is acturally incorrect,
but this suppresses a warning from Maven, and as long as we don't do filtering we should be OK. -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
......@@ -348,6 +397,37 @@ THE SOFTWARE.
</plugins>
</build>
</profile>
<profile>
<id>m2e</id>
<properties>
<m2BuildDirectory>target</m2BuildDirectory>
</properties>
<activation>
<property>
<name>m2e.version</name>
</property>
</activation>
<build>
<directory>${m2BuildDirectory}</directory>
<plugins>
<plugin>
<groupId>org.maven.ide.eclipse</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>0.10.0</version>
<configuration>
<mappingId>customizable</mappingId>
<configurators>
<configurator id="org.maven.ide.eclipse.jdt.javaConfigurator" />
<configurator id="org.maven.ide.eclipse.plexus.annotations.plexusConfigurator" />
</configurators>
<mojoExecutions>
<mojoExecution>org.apache.maven.plugins:maven-resources-plugin::</mojoExecution>
</mojoExecutions>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<repositories>
......
......@@ -108,7 +108,9 @@ final class UserRequest<RSP,EXC extends Throwable> extends Request<UserResponse<
throw new SecurityException("Execution of "+callable.toString()+" is prohibited because the channel is restricted");
ClassLoader old = Thread.currentThread().getContextClassLoader();
System.out.println("UserRequest current classLoader " + old.toString());
Thread.currentThread().setContextClassLoader(cl);
System.out.println("UserRequest new classLoader " + cl.toString());
// execute the service
try {
r = callable.call();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册