提交 cddcd8f0 编写于 作者: O Olivier Lamy 提交者: Kohsuke Kawaguchi

move maven agents and interceptors to an external repo.

as they don't change a lot build will be faster !
上级 545f670e
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>maven-agent</artifactId>
<packaging>jar</packaging>
<name>Jenkins Maven2 CLI agent</name>
<description>
Code that boots up Maven2 with Jenkins's remoting support in place.
Used for the native maven support.
</description>
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<!-- compile with 1.2 so that we can report JDK version errors nicely -->
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.2</source>
<target>1.2</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>never</forkMode>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.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>
<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>
<!-- test dependencies -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>2.0.9</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>remoting</artifactId>
<version>${project.version}</version>
<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 hudson.maven.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.lang.reflect.InvocationTargetException;
import java.net.Socket;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
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;
/**
* Entry point for launching Maven 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.
*
* @author Kohsuke Kawaguchi
*/
public class Main {
/**
* 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]),
args.length==4?null:new File(args[4]));
}
/**
*
* @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 interceptorJar
* maven-interceptor.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 interceptorOverrideJar
* Possibly null override jar to be placed in front of maven-interceptor.jar
*/
public static void main(File m2Home, File remotingJar, File interceptorJar, int tcpPort, File interceptorOverrideJar) 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("maven.interceptor",interceptorJar.getPath());
System.setProperty("maven.interceptor.override",
// I don't know how classworlds react to undefined variable, so
(interceptorOverrideJar!=null?interceptorOverrideJar:interceptorJar).getPath());
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"));
// have it eventually delegate to this class so that this can be visible
//ClassWorldAdapter classWorldAdapter = ClassWorldAdapter.getInstance( launcher.getWorld() );
// create a realm for loading remoting subsystem.
// this needs to be able to see maven.
//ClassRealm remoting = new DefaultClassRealm(classWorldAdapter,"hudson-remoting", launcher.getSystemClassLoader());
ClassRealm remoting = new DefaultClassRealm(launcher.getWorld(),"hudson-remoting", launcher.getSystemClassLoader());
remoting.setParent(launcher.getWorld().getRealm("plexus.core.maven"));
remoting.addConstituent(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);
}
/**
* 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.
}
}
}
/**
* Called by the code in remoting to launch.
* @throws org.codehaus.plexus.classworlds.realm.NoSuchRealmException
*/
public static int launch(String[] args) throws NoSuchMethodException, IllegalAccessException, NoSuchRealmException, InvocationTargetException, ClassNotFoundException {
//ClassWorld world = ClassWorldAdapter.getInstance( launcher.getWorld() );
ClassWorld world = launcher.getWorld();
Set builtinRealms = new HashSet(world.getRealms());
try {
launcher.launch(args);
} finally {
// 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.
// so unless we discard all the realms multiple invocations
// that use different versions of the same plugin will fail to work correctly.
Set all = new HashSet(world.getRealms());
all.removeAll(builtinRealms);
for (Iterator itr = all.iterator(); itr.hasNext();) {
ClassRealm cr = (ClassRealm) itr.next();
world.disposeRealm(cr.getId());
}
}
return launcher.getExitCode();
}
}
/*
* 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 hudson.maven.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();
}
}
#
# In 2.0.6 the layout changed.
#
main is org.apache.maven.cli.MavenCli from plexus.core
set maven.home default ${user.home}/m2
[plexus.core]
load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
[plexus.core.maven]
\ No newline at end of file
#
# mostly copied as-is from $MAVEN_HOME/bin/m2.conf
# but also loads the interceptor before loading any other components
#
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
[plexus.core.maven]
load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
\ 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 hudson.maven.agent;
import hudson.remoting.Channel;
import hudson.remoting.Launcher;
import hudson.remoting.Which;
import junit.framework.TestCase;
import org.codehaus.classworlds.ClassWorld;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
/**
* @author Kohsuke Kawaguchi
*/
public class LaunchTest extends TestCase {
public void test1() throws Throwable {
/*
List<String> args = new ArrayList<String>();
args.add("java");
args.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8002");
System.out.println(Channel.class);
args.add("-cp");
args.add(Which.jarFile(Main.class)+File.pathSeparator+Which.jarFile(ClassWorld.class));
args.add(Main.class.getName());
// M2_HOME
args.add(System.getProperty("maven.home"));
// remoting.jar
args.add(Which.jarFile(Launcher.class).getPath());
// interceptor.jar
args.add(Which.jarFile(PluginManagerInterceptor.class).getPath());
System.out.println("Launching "+args);
final Process proc = Runtime.getRuntime().exec(args.toArray(new String[0]));
// start copying system err
new Thread() {
public void run() {
try {
copyStream(proc.getErrorStream(),System.err);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
Channel ch = new Channel("maven", Executors.newCachedThreadPool(),
proc.getInputStream(), proc.getOutputStream(), System.err);
System.out.println("exit code="+ch.call(new RunCommand("help:effective-settings")));
ch.close();
System.out.println("done");
*/
}
public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192];
int len;
while((len=in.read(buf))>0)
out.write(buf,0,len);
}
}
/*
* 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 hudson.maven.agent;
import hudson.remoting.Callable;
import org.apache.maven.project.MavenProject;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.reporting.MavenReport;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import java.io.IOException;
/**
* Starts Maven CLI. Remotely executed.
*
* @author Kohsuke Kawaguchi
*/
public class RunCommand implements Callable {
private final String[] args;
public RunCommand(String[] args) {
this.args = args;
}
public Object call() throws Throwable {
// return Main.class.getClassLoader().toString();
PluginManagerInterceptor.setListener(new PluginManagerListener() {
public void preExecute(MavenProject project, MojoExecution exec, Mojo mojo, PlexusConfiguration mergedConfig, ExpressionEvaluator eval) throws IOException, InterruptedException, AbortException {
System.out.println("***** "+exec.getMojoDescriptor().getGoal());
}
public void postExecute(MavenProject project, MojoExecution exec, Mojo mojo, PlexusConfiguration mergedConfig, ExpressionEvaluator eval, Exception exception) throws IOException, InterruptedException, AbortException {
System.out.println("==== "+exec.getMojoDescriptor().getGoal());
}
public void onReportGenerated(MavenReport report, MojoExecution mojoExecution, PlexusConfiguration mergedConfig, ExpressionEvaluator eval) throws IOException, InterruptedException {
System.out.println("//// "+report);
}
});
return new Integer(Main.launch(args));
}
}
<!--
The MIT License
Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Stephen Connolly
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>maven-interceptor</artifactId>
<packaging>jar</packaging>
<name>Jenkins Maven 2 PluginManager interceptor</name>
<description>
Plexus module that intercepts invocations of key Maven components
so that Jenkins can monitor what's going on in Maven.
</description>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>2.0.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
<version>1.1</version>
</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>
</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 hudson.maven.agent;
/**
* Thrown when {@link PluginManagerListener} returned false to orderly
* abort the execution. The caller shouldn't dump the stack trace for
* this exception.
*/
public final class AbortException extends RuntimeException {
public AbortException(String message) {
super(message);
}
public AbortException(String message, Exception e) {
super(message, e);
}
}
/*
* 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 hudson.maven.agent;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.classworlds.ClassRealm;
/**
* {@link ComponentConfigurator} filter.
* The only real method that needs to be implemented is the 5 arg version.
*
* @author Kohsuke Kawaguchi
*/
class ComponentConfiguratorFilter extends AbstractComponentConfigurator {
ComponentConfigurator core;
public ComponentConfiguratorFilter(ComponentConfigurator core) {
this.core = core;
}
@Override
public void configureComponent(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm, ConfigurationListener listener) throws ComponentConfigurationException {
core.configureComponent(component, configuration, expressionEvaluator, containerRealm, listener);
}
}
/*
* 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 hudson.maven.agent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;
/**
* Base class for intercepting components through its interfaces.
*
* @author Kohsuke Kawaguchi
*/
abstract class ComponentInterceptor<T> implements InvocationHandler {
protected T delegate;
/**
* By default, all the methods are simply delegated to the intercepted component.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(delegate,args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
public T wrap(T o) {
if(delegate !=null)
// can't intercept two objects simultaneously
throw new IllegalStateException();
delegate = o;
return (T)Proxy.newProxyInstance(o.getClass().getClassLoader(),
getImplementedInterfaces(o), this);
}
private static Class[] getImplementedInterfaces(Object o) {
Stack<Class> s = new Stack<Class>();
s.push(o.getClass());
Set<Class> interfaces = new HashSet<Class>();
while(!s.isEmpty()) {
Class c = s.pop();
for (Class intf : c.getInterfaces()) {
interfaces.add(intf);
s.push(intf);
}
Class sc = c.getSuperclass();
if(sc!=null)
s.push(sc);
}
return interfaces.toArray(new Class[interfaces.size()]);
}
}
/*
* 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 hudson.maven.agent;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.PlexusContainerException;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.LoggerManager;
import org.codehaus.plexus.configuration.PlexusConfigurationResourceException;
import org.codehaus.plexus.context.Context;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.component.repository.exception.ComponentRepositoryException;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.ComponentDescriptor;
import org.codehaus.plexus.component.factory.ComponentInstantiationException;
import org.codehaus.plexus.component.composition.CompositionException;
import org.codehaus.plexus.component.composition.UndefinedComponentComposerException;
import org.codehaus.plexus.component.discovery.ComponentDiscoveryListener;
import org.codehaus.classworlds.ClassRealm;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.io.Reader;
import java.io.File;
/**
* {@link PlexusContainer} filter.
*
* @author Kohsuke Kawaguchi
*/
class ContainerFilter implements PlexusContainer {
private final PlexusContainer core;
public ContainerFilter(PlexusContainer core) {
this.core = core;
}
public Date getCreationDate() {
return core.getCreationDate();
}
public boolean hasChildContainer(String name) {
return core.hasChildContainer(name);
}
public void removeChildContainer(String name) {
core.removeChildContainer(name);
}
public PlexusContainer getChildContainer(String name) {
return core.getChildContainer(name);
}
public PlexusContainer createChildContainer(String name, List classpathJars, Map context) throws PlexusContainerException {
return core.createChildContainer(name, classpathJars, context);
}
public PlexusContainer createChildContainer(String name, List classpathJars, Map context, List discoveryListeners) throws PlexusContainerException {
return core.createChildContainer(name, classpathJars, context, discoveryListeners);
}
public Object lookup(String componentKey) throws ComponentLookupException {
return core.lookup(componentKey);
}
public Object lookup(String role, String roleHint) throws ComponentLookupException {
return core.lookup(role, roleHint);
}
public Map lookupMap(String role) throws ComponentLookupException {
return core.lookupMap(role);
}
public List lookupList(String role) throws ComponentLookupException {
return core.lookupList(role);
}
public ComponentDescriptor getComponentDescriptor(String componentKey) {
return core.getComponentDescriptor(componentKey);
}
public Map getComponentDescriptorMap(String role) {
return core.getComponentDescriptorMap(role);
}
public List getComponentDescriptorList(String role) {
return core.getComponentDescriptorList(role);
}
public void addComponentDescriptor(ComponentDescriptor componentDescriptor) throws ComponentRepositoryException {
core.addComponentDescriptor(componentDescriptor);
}
public void release(Object component) throws ComponentLifecycleException {
core.release(component);
}
public void releaseAll(Map components) throws ComponentLifecycleException {
core.releaseAll(components);
}
public void releaseAll(List components) throws ComponentLifecycleException {
core.releaseAll(components);
}
public boolean hasComponent(String componentKey) {
return core.hasComponent(componentKey);
}
public boolean hasComponent(String role, String roleHint) {
return core.hasComponent(role, roleHint);
}
public void suspend(Object component) throws ComponentLifecycleException {
core.suspend(component);
}
public void resume(Object component) throws ComponentLifecycleException {
core.resume(component);
}
public void initialize() throws PlexusContainerException {
core.initialize();
}
public boolean isInitialized() {
return core.isInitialized();
}
public void start() throws PlexusContainerException {
core.start();
}
public boolean isStarted() {
return core.isStarted();
}
public void dispose() {
core.dispose();
}
public Context getContext() {
return core.getContext();
}
public void setParentPlexusContainer(PlexusContainer parentContainer) {
core.setParentPlexusContainer(parentContainer);
}
public void addContextValue(Object key, Object value) {
core.addContextValue(key, value);
}
public void setConfigurationResource(Reader configuration) throws PlexusConfigurationResourceException {
core.setConfigurationResource(configuration);
}
public Logger getLogger() {
return core.getLogger();
}
public Object createComponentInstance(ComponentDescriptor componentDescriptor) throws ComponentInstantiationException, ComponentLifecycleException {
return core.createComponentInstance(componentDescriptor);
}
public void composeComponent(Object component, ComponentDescriptor componentDescriptor) throws CompositionException, UndefinedComponentComposerException {
core.composeComponent(component, componentDescriptor);
}
public void registerComponentDiscoveryListener(ComponentDiscoveryListener listener) {
core.registerComponentDiscoveryListener(listener);
}
public void removeComponentDiscoveryListener(ComponentDiscoveryListener listener) {
core.removeComponentDiscoveryListener(listener);
}
public void addJarRepository(File repository) {
core.addJarRepository(repository);
}
public void addJarResource(File resource) throws PlexusContainerException {
core.addJarResource(resource);
}
public ClassRealm getContainerRealm() {
return core.getContainerRealm();
}
public ClassRealm getComponentRealm(String componentKey) {
return core.getComponentRealm(componentKey);
}
public void setLoggerManager(LoggerManager loggerManager) {
core.setLoggerManager(loggerManager);
}
public LoggerManager getLoggerManager() {
return core.getLoggerManager();
}
}
/*
* 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 hudson.maven.agent;
import java.io.IOException;
import java.lang.reflect.Method;
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.Mojo;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.PluginConfigurationException;
import org.apache.maven.plugin.PluginManagerException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.reporting.MavenReportException;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.configuration.PlexusConfiguration;
/**
* Description in META-INF/plexus/components.xml makes it possible to use this instead of the default
* plugin manager.
*
* @author Kohsuke Kawaguchi
*/
public class PluginManagerInterceptor extends DefaultPluginManager {
/**
* {@link PluginManagerListener} that receives events.
* There's no way external code can connect to a running instance of
* {@link PluginManagerInterceptor}, so this cannot be made instance fields.
*/
private static PluginManagerListener listener;
/**
* {@link ComponentConfigurator} filter to intercept the mojo configuration.
*/
private ComponentConfiguratorFilter configuratorFilter;
public static void setListener(PluginManagerListener _listener) {
listener = _listener;
}
@Override
public void initialize() {
super.initialize();
container = new ContainerFilter(container) {
/**
* {@link DefaultPluginManager} uses it to load plugins and their configurators.
*
* @param name
* groupId+':'+artifactId of the plugin.
*/
public PlexusContainer getChildContainer(String name) {
PlexusContainer child = super.getChildContainer(name);
if(child==null) return null;
return new ContainerFilter(child) {
public Object lookup(String componentKey) throws ComponentLookupException {
return wrap(super.lookup(componentKey), componentKey);
}
public Object lookup(String role, String roleHint) throws ComponentLookupException {
return wrap(super.lookup(role,roleHint), role);
}
public void release(Object component) throws ComponentLifecycleException {
if(component==configuratorFilter)
super.release(configuratorFilter.core);
else
super.release(component);
}
private Object wrap(Object c, String componentKey) {
if(configuratorFilter==null)
return c; // not activated
if(c!=null && componentKey.equals(ComponentConfigurator.ROLE)) {
if(configuratorFilter.core!=null)
throw new IllegalStateException("ComponentConfigurationFilter being reused. " +
"This is a bug in Hudson. Please report that to the development team.");
configuratorFilter.core = (ComponentConfigurator)c;
c = configuratorFilter;
}
return c;
}
};
}
};
}
/**
* Intercepts the {@link Mojo} configuration and grabs some key Maven objects that are used for configuration,
* then call {@link #pre(Object, PlexusConfiguration, ExpressionEvaluator)} to provide an opportunity
* to alter the configuration.
*/
private abstract class MojoIntercepter extends ComponentConfiguratorFilter {
// these are the key objects involved in configuring a mojo
PlexusConfiguration config;
ExpressionEvaluator eval;
Mojo mojo;
MojoIntercepter() {
super(null);
// it is the caller's responsibility to set 'configuratorFilter' to null when the interception is over.
configuratorFilter = this;
}
@Override
public void configureComponent(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm, ConfigurationListener configListener) throws ComponentConfigurationException {
try {
this.config = configuration;
this.eval = expressionEvaluator;
this.mojo = (Mojo)component;
pre(component, configuration, expressionEvaluator);
super.configureComponent(component, configuration, expressionEvaluator, containerRealm, configListener);
} catch (IOException e) {
throw new ComponentConfigurationException(e);
} catch (InterruptedException e) {
// orderly abort
throw new AbortException("Execution aborted",e);
}
}
protected abstract void pre(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) throws IOException, InterruptedException;
}
@Override
public void executeMojo(final MavenProject project, final MojoExecution mojoExecution, MavenSession session) throws ArtifactResolutionException, MojoExecutionException, MojoFailureException, ArtifactNotFoundException, InvalidDependencyVersionException, PluginManagerException, PluginConfigurationException {
class MojoIntercepterImpl extends MojoIntercepter {
@Override
protected void pre(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) throws IOException, InterruptedException {
if(listener!=null)
// this lets preExecute a chance to modify the mojo configuration
listener.preExecute(project,mojoExecution, (Mojo)component, configuration,expressionEvaluator);
}
void callPost(Exception exception) throws IOException, InterruptedException {
if(listener!=null)
listener.postExecute(project,mojoExecution,mojo,config,eval,exception);
}
}
// prepare interception of ComponentConfigurator, so that we can get the final PlexusConfiguration object
// representing the configuration before Mojo object is filled with that.
MojoIntercepterImpl interceptor = new MojoIntercepterImpl();
try {
try {
// inside the executeMojo but before the mojo actually gets executed,
// we should be able to trap the mojo configuration.
super.executeMojo(project, mojoExecution, session);
interceptor.callPost(null);
} catch (MojoExecutionException e) {
interceptor.callPost(e);
throw e;
} catch (MojoFailureException e) {
interceptor.callPost(e);
throw e;
}
} catch (InterruptedException e) {
// orderly abort
throw new AbortException("Execution aborted",e);
} catch (IOException e) {
// we can't use two-args constructor. see the comment from steffeng on Mon Sep 14 20:22:32 HUDSON-2373.
throw (PluginManagerException)new PluginManagerException(e.getMessage()).initCause(e);
} finally {
configuratorFilter = null;
}
}
/**
* Intercepts the creation of {@link MavenReport}, to intercept
* the execution of it. This is used to discover the execution
* of certain reporting.
*/
@Override
public MavenReport getReport(MavenProject project, final MojoExecution mojoExecution, MavenSession session) throws ArtifactNotFoundException, PluginConfigurationException, PluginManagerException, ArtifactResolutionException {
// intercept the MavenReport object creation.
final MojoIntercepter interceptor = new MojoIntercepter() {
protected void pre(Object component, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator) throws IOException, InterruptedException {
}
};
MavenReport r;
try {
r = super.getReport(project, mojoExecution, session);
} finally {
configuratorFilter = null;
}
if(r==null) return null;
r = new ComponentInterceptor<MavenReport>() {
/**
* Intercepts the execution of methods on {@link MavenReport}.
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("generate")) {
Object r = super.invoke(proxy, method, args);
// on successul execution of the generate method, raise an event
try {
listener.onReportGenerated(delegate,mojoExecution,interceptor.config,interceptor.eval);
} catch (InterruptedException e) {
// orderly abort
throw new AbortException("Execution aborted",e);
} catch (IOException e) {
throw new MavenReportException(e.getMessage(),e);
}
return r;
}
// delegate by default
return super.invoke(proxy, method, args);
}
}.wrap(r);
return r;
}
}
/*
* 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 hudson.maven.agent;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.reporting.MavenReport;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import java.io.IOException;
/**
* Receives notification from {@link PluginManagerInterceptor},
* before and after a mojo is executed.
*
* @author Kohsuke Kawaguchi
*/
public interface PluginManagerListener {
/**
* Called right before {@link Mojo#execute()} is invoked.
*
* @param mojo
* The mojo object to be invoked. All its configuration values have been populated.
*/
void preExecute(MavenProject project, MojoExecution exec, Mojo mojo, PlexusConfiguration mergedConfig, ExpressionEvaluator eval) throws IOException, InterruptedException;
/**
* Called after the mojo has finished executing.
*
* @param project
* Same object as passed to {@link #preExecute}.
* @param exec
* Same object as passed to {@link #preExecute}.
* @param mojo
* The mojo object that executed.
* @param mergedConfig
* Same object as passed to {@link #preExecute}.
* @param eval
* Same object as passed to {@link #preExecute}.
* @param exception
* If mojo execution failed with {@link MojoFailureException} or
* {@link MojoExecutionException}, this method is still invoked
* with those error objects.
* If mojo executed successfully, this parameter is null.
*/
void postExecute(MavenProject project, MojoExecution exec, Mojo mojo, PlexusConfiguration mergedConfig, ExpressionEvaluator eval, Exception exception) throws IOException, InterruptedException;
/**
* Called after a successful execution of {@link MavenReport#generate(Sink, Locale)}.
*
* @param report
* The {@link MavenReport} object that just successfully completed.
*/
void onReportGenerated(MavenReport report, MojoExecution mojoExecution, PlexusConfiguration mergedConfig, ExpressionEvaluator eval) throws IOException, InterruptedException;
}
/*
* 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.apache.maven.lifecycle;
import hudson.maven.agent.AbortException;
import org.apache.maven.BuildFailureException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.monitor.event.EventMonitor;
import org.apache.maven.monitor.event.MavenEvents;
import java.io.IOException;
/**
* {@link LifecycleExecutor} interceptor.
*
* <p>
* This class is in the same package as in {@link DefaultLifecycleExecutor},
* because Plexus requires the class and its subordinates (like {@link Lifecycle},
* which is referenced in <tt>components.xml</tt>
*
* @author Kohsuke Kawaguchi
*/
public class LifecycleExecutorInterceptor extends DefaultLifecycleExecutor {
/**
* {@link LifecycleExecutorListener} that receives events.
* There's no way external code can connect to a running instance of
* {@link LifecycleExecutorInterceptor}, so this cannot be made instance fields.
*/
private static LifecycleExecutorListener listener;
public static void setListener(LifecycleExecutorListener _listener) {
listener = _listener;
}
public void execute(MavenSession session, ReactorManager rm, EventDispatcher dispatcher) throws BuildFailureException, LifecycleExecutionException {
try {
session.getEventDispatcher().addEventMonitor(new EventMonitorImpl());
if(listener!=null)
listener.preBuild(session,rm,dispatcher);
try {
super.execute(session, rm, dispatcher);
} finally {
if(listener!=null)
listener.postBuild(session,rm,dispatcher);
}
} catch (InterruptedException e) {
throw new BuildFailureException("aborted",e);
} catch (IOException e) {
throw new BuildFailureException(e.getMessage(),e);
} catch (AbortException e) {
throw new BuildFailureException("aborted",e);
}
}
/**
* {@link EventMonitor} offers mostly useless events, but this offers
* the most accurate "end of module" event.
*/
private final class EventMonitorImpl implements EventMonitor {
public void startEvent(String eventName, String target, long timestamp) {
// TODO
}
public void endEvent(String eventName, String target, long timestamp) {
if(eventName.equals(MavenEvents.PROJECT_EXECUTION)) {
if(listener!=null) {
try {
listener.endModule();
} catch (InterruptedException e) {
// can't interrupt now
Thread.currentThread().interrupt();
} catch (IOException e) {
throw new Error(e);
}
}
}
}
public void errorEvent(String eventName, String target, long timestamp, Throwable cause) {
// TODO
}
}
}
/*
* 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.apache.maven.lifecycle;
import org.apache.maven.BuildFailureException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.monitor.event.EventDispatcher;
import java.io.IOException;
/**
* Event notification for the start/end of the maven execution.
*
* <p>
* The exact semantics in Maven is undocumented (as usual!), but apparently
* this is invoked at the beginning of the build and the end, surrounding
* the complete mojo executions.
*
* @author Kohsuke Kawaguchi
*/
public interface LifecycleExecutorListener {
void preBuild(MavenSession session, ReactorManager rm, EventDispatcher dispatcher) throws BuildFailureException, LifecycleExecutionException, InterruptedException, IOException;
void postBuild(MavenSession session, ReactorManager rm, EventDispatcher dispatcher) throws BuildFailureException, LifecycleExecutionException, InterruptedException, IOException;
/**
* This event is avaialble from {@link LifecycleExecutorListener}
* and offers accurate "leaving module" event.
*/
void endModule() throws InterruptedException, IOException;
}
<!-- MAVEN-INTERCEPTION-TO-BE-MASKED: see MavenUtil.java for how we use this marker -->
<!--
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.
-->
<!--
Override the plugin manager.
TODO: this is fragile, as newer versions of Maven may add more <requirement>s
or change configuration. Figure out how to do interception in plexus.
-->
<component-set>
<components>
<component>
<role>org.apache.maven.plugin.PluginManager</role>
<implementation>hudson.maven.agent.PluginManagerInterceptor</implementation>
<requirements>
<requirement>
<role>org.apache.maven.project.path.PathTranslator</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.MavenPluginCollector</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.version.PluginVersionManager</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.factory.ArtifactFactory</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.resolver.ArtifactResolver</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.metadata.ArtifactMetadataSource</role>
</requirement>
<requirement>
<role>org.apache.maven.plugin.PluginMappingManager</role>
</requirement>
<requirement>
<role>org.apache.maven.execution.RuntimeInformation</role>
</requirement>
<requirement>
<role>org.apache.maven.project.MavenProjectBuilder</role>
</requirement>
</requirements>
</component>
<component>
<role>org.apache.maven.lifecycle.LifecycleExecutor</role>
<implementation>org.apache.maven.lifecycle.LifecycleExecutorInterceptor</implementation>
<requirements>
<requirement>
<role>org.apache.maven.plugin.PluginManager</role>
</requirement>
<requirement>
<role>org.apache.maven.extension.ExtensionManager</role>
</requirement>
<requirement>
<role>org.apache.maven.artifact.handler.manager.ArtifactHandlerManager</role>
</requirement>
</requirements>
<configuration>
<lifecycles>
<lifecycle>
<id>default</id>
<!-- START SNIPPET: lifecycle -->
<phases>
<phase>validate</phase>
<phase>initialize</phase>
<phase>generate-sources</phase>
<phase>process-sources</phase>
<phase>generate-resources</phase>
<phase>process-resources</phase>
<phase>compile</phase>
<phase>process-classes</phase>
<phase>generate-test-sources</phase>
<phase>process-test-sources</phase>
<phase>generate-test-resources</phase>
<phase>process-test-resources</phase>
<phase>test-compile</phase>
<phase>process-test-classes</phase>
<phase>test</phase>
<phase>package</phase>
<phase>pre-integration-test</phase>
<phase>integration-test</phase>
<phase>post-integration-test</phase>
<phase>verify</phase>
<phase>install</phase>
<phase>deploy</phase>
</phases>
<!-- END SNIPPET: lifecycle -->
</lifecycle>
<lifecycle>
<id>clean</id>
<phases>
<phase>pre-clean</phase>
<phase>clean</phase>
<phase>post-clean</phase>
</phases>
<default-phases>
<clean>org.apache.maven.plugins:maven-clean-plugin:clean</clean>
</default-phases>
</lifecycle>
<lifecycle>
<id>site</id>
<phases>
<phase>pre-site</phase>
<phase>site</phase>
<phase>post-site</phase>
<phase>site-deploy</phase>
</phases>
<default-phases>
<site>org.apache.maven.plugins:maven-site-plugin:site</site>
<site-deploy>org.apache.maven.plugins:maven-site-plugin:deploy</site-deploy>
</default-phases>
</lifecycle>
</lifecycles>
<!-- START SNIPPET: default-reports -->
<defaultReports>
<report>org.apache.maven.plugins:maven-project-info-reports-plugin</report>
<!-- TODO: currently in mojo - should they be defaults any more?
<report>org.apache.maven.plugins:maven-checkstyle-plugin</report>
<report>org.apache.maven.plugins:maven-javadoc-plugin</report>
<report>org.apache.maven.plugins:maven-changelog-plugin</report>
<report>org.apache.maven.plugins:maven-surefire-report-plugin</report>
<report>org.apache.maven.plugins:maven-jdepend-plugin</report>
<report>org.apache.maven.plugins:maven-jxr-plugin</report>
<report>org.apache.maven.plugins:maven-taglist-plugin</report>
-->
</defaultReports>
<!-- END SNIPPET: default-reports -->
<!-- START SNIPPET: default-lifecycle -->
<!-- NOT USED, ACCORDING TO CODE.
<defaultPhases>
<process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
<compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
<process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
<test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
<test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
<package>
org.apache.maven.plugins:maven-jar-plugin:jar,
org.apache.maven.plugins:maven-source-plugin:jar
</package>
<install>org.apache.maven.plugins:maven-install-plugin:install</install>
<deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
</defaultPhases>
-->
<!-- END SNIPPET: default-lifecycle -->
</configuration>
</component>
</components>
</component-set>
\ No newline at end of file
This file marks components.xml as "interceptor only", so that
Maven embedder won't pick it up.
\ No newline at end of file
......@@ -38,6 +38,15 @@ THE SOFTWARE.
Now it is a plug-in that is installed by default, but can be disabled.</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/Maven+2+Project+Plugin</url>
<properties>
<mavenInterceptorsVersion>1.0</mavenInterceptorsVersion>
<mavenVersion>3.0.3</mavenVersion>
<maven.version>${mavenVersion}</maven.version>
<aetherVersion>1.11</aetherVersion>
<sisuInjectVersion>1.4.3.1</sisuInjectVersion>
<wagonVersion>1.0-beta-7</wagonVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
......@@ -53,9 +62,9 @@ THE SOFTWARE.
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven-agent</artifactId>
<version>${project.version}</version>
<version>${mavenInterceptorsVersion}</version>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
......@@ -65,9 +74,9 @@ THE SOFTWARE.
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven-interceptor</artifactId>
<version>${project.version}</version>
<version>${mavenInterceptorsVersion}</version>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
......@@ -83,15 +92,15 @@ THE SOFTWARE.
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven3-agent</artifactId>
<version>${project.version}</version>
<version>${mavenInterceptorsVersion}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven3-interceptor</artifactId>
<version>${project.version}</version>
<version>${mavenInterceptorsVersion}</version>
</dependency>
<dependency>
......@@ -101,26 +110,50 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-api</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-impl</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-spi</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-util</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-connector-wagon</artifactId>
<version>${aetherVersion}</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
......@@ -132,16 +165,19 @@ THE SOFTWARE.
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
<version>${sisuInjectVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-bean</artifactId>
<version>${sisuInjectVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
<version>${wagonVersion}</version>
<exclusions>
<exclusion>
<groupId>nekohtml</groupId>
......@@ -156,6 +192,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
......@@ -176,19 +213,17 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-provider-api</artifactId>
<version>${wagonVersion}</version>
</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>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.lib</groupId>
......
......@@ -94,6 +94,8 @@ import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.codehaus.plexus.PlexusConstants;
import org.codehaus.plexus.configuration.DefaultPlexusConfiguration;
import org.codehaus.plexus.util.PathTool;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
......
.settings
.project
target
.classpath
build
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>maven3-agent</artifactId>
<name>Jenkins Maven3 CLI Agent</name>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>maven3-interceptor</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-2010, 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 org.jvnet.hudson.maven3.agent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
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 interceptorJar
* 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 interceptorJar,
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.interceptor", (interceptorJar != null ? interceptorJar
: interceptorJar).getPath());
// load the default realms
launcher = new Launcher();
launcher.setSystemClassLoader(Maven3Main.class.getClassLoader());
launcher.configure(getClassWorldsConfStream());
// 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();
}
private static InputStream getClassWorldsConfStream() throws FileNotFoundException {
String classWorldsConfLocation = System.getProperty("classworlds.conf");
if (classWorldsConfLocation == null || classWorldsConfLocation.trim().length() == 0) {
classWorldsConfLocation = System.getenv("classworlds.conf");
if (classWorldsConfLocation == null || classWorldsConfLocation.trim().length() == 0) {
return Maven3Main.class.getResourceAsStream("classworlds.conf");
}
}
return new FileInputStream(new File(classWorldsConfLocation));
}
/**
* 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.jvnet.hudson.maven3.launcher.Maven3Launcher from plexus.core
set maven.home default ${user.home}/m2
[plexus.core]
load ${maven3.interceptor}
load ${maven.home}/lib/*.jar
\ No newline at end of file
.settings
.project
target
.classpath
build
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>maven3-interceptor</artifactId>
<name>Jenkins Maven3 Interceptor</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.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.ParseException;
import org.apache.maven.execution.DefaultMavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.execution.MavenExecutionRequestPopulationException;
import org.apache.maven.execution.MavenExecutionRequestPopulator;
import org.apache.maven.lifecycle.internal.LifecycleWeaveBuilder;
import org.apache.maven.model.building.ModelProcessor;
import org.apache.maven.properties.internal.EnvironmentUtils;
import org.apache.maven.repository.internal.MavenRepositorySystemSession;
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuilder;
import org.apache.maven.settings.building.SettingsBuildingException;
import org.apache.maven.settings.building.SettingsBuildingRequest;
import org.apache.maven.settings.building.SettingsBuildingResult;
import org.apache.maven.settings.building.SettingsProblem;
import org.codehaus.plexus.PlexusContainer;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.StringUtils;
import org.sonatype.aether.impl.internal.EnhancedLocalRepositoryManager;
import org.sonatype.aether.transfer.TransferListener;
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
/**
* Most of code is coming from asf svn repo waiting before having available
* @author Olivier Lamy
*/
@Component( role = MavenExecutionRequestBuilder.class)
public class DefaultMavenExecutionRequestBuilder
implements MavenExecutionRequestBuilder, Initializable
{
@Requirement
private SettingsBuilder settingsBuilder;
@Requirement
private MavenExecutionRequestPopulator executionRequestPopulator;
@Requirement
private Logger plexusLogger;
@Requirement
private ModelProcessor modelProcessor;
@Requirement
private PlexusContainer plexusContainer;
private DefaultSecDispatcher dispatcher;
public void initialize()
throws InitializationException
{
try
{
dispatcher = (DefaultSecDispatcher) plexusContainer.lookup( SecDispatcher.class, "maven" );
}
catch ( ComponentLookupException e )
{
throw new InitializationException( e.getMessage(), e );
}
}
/**
* @throws MavenExecutionRequestPopulationException
* @see org.jvnet.hudson.maven3.MavenExecutionRequestBuilder.MavenExecutionRequestsBuilder#getMavenExecutionRequest(java.lang.String[])
*/
public MavenExecutionRequest getMavenExecutionRequest( String[] args, PrintStream printStream )
throws MavenExecutionRequestPopulationException, SettingsBuildingException,
MavenExecutionRequestsBuilderException
{
try
{
CliRequest cliRequest = new CliRequest( args, null );
initialize( cliRequest, printStream );
// Need to process cli options first to get possible logging options
cli( cliRequest );
logging( cliRequest );
commands( cliRequest );
properties( cliRequest );
// we are in a container so no need
//container( cliRequest );
settings( cliRequest );
populateRequest( cliRequest );
encryption( cliRequest );
MavenExecutionRequest request = executionRequestPopulator.populateDefaults( cliRequest.request );
// TODO move this in ASF sources ?
if (request.getProjectBuildingRequest().getRepositorySession()== null)
{
MavenRepositorySystemSession session = new MavenRepositorySystemSession();
if (session.getLocalRepositoryManager() == null)
{
session.setLocalRepositoryManager( new EnhancedLocalRepositoryManager( request.getLocalRepositoryPath() ) );
}
request.getProjectBuildingRequest().setRepositorySession( session );
}
return request;
}
catch ( Exception e )
{
throw new MavenExecutionRequestsBuilderException( e.getMessage(), e );
}
}
static File resolveFile( File file, String workingDirectory )
{
if ( file == null )
{
return null;
}
else if ( file.isAbsolute() )
{
return file;
}
else if ( file.getPath().startsWith( File.separator ) )
{
// drive-relative Windows path
return file.getAbsoluteFile();
}
else
{
return new File( workingDirectory, file.getPath() ).getAbsoluteFile();
}
}
private void initialize( CliRequest cliRequest, PrintStream printStream )
{
if ( cliRequest.stdout == null )
{
cliRequest.stdout = System.out;
}
if ( cliRequest.stderr == null )
{
cliRequest.stderr = System.err;
}
if ( cliRequest.logger == null )
{
cliRequest.logger = new PrintStreamLogger( cliRequest.stdout );
}
else
{
cliRequest.logger.setStream( cliRequest.stdout );
}
if ( cliRequest.workingDirectory == null )
{
cliRequest.workingDirectory = System.getProperty( "user.dir" );
}
//
// Make sure the Maven home directory is an absolute path to save us from confusion with say drive-relative
// Windows paths.
//
String mavenHome = System.getProperty( "maven.home" );
if ( mavenHome != null )
{
System.setProperty( "maven.home", new File( mavenHome ).getAbsolutePath() );
}
}
private void cli( CliRequest cliRequest )
throws Exception
{
CLIManager cliManager = new CLIManager();
try
{
cliRequest.commandLine = cliManager.parse( cliRequest.args );
}
catch ( ParseException e )
{
cliRequest.stderr.println( "Unable to parse command line options: " + e.getMessage() );
cliManager.displayHelp( cliRequest.stdout );
throw e;
}
// TODO: these should be moved out of here. Wrong place.
//
if ( cliRequest.commandLine.hasOption( CLIManager.HELP ) )
{
cliManager.displayHelp( cliRequest.stdout );
throw new MavenCli.ExitException( 0 );
}
if ( cliRequest.commandLine.hasOption( CLIManager.VERSION ) )
{
CLIReportingUtils.showVersion( cliRequest.stdout );
throw new MavenCli.ExitException( 0 );
}
}
private void logging( CliRequest cliRequest )
{
cliRequest.debug = cliRequest.commandLine.hasOption( CLIManager.DEBUG );
cliRequest.quiet = !cliRequest.debug && cliRequest.commandLine.hasOption( CLIManager.QUIET );
cliRequest.showErrors = cliRequest.debug || cliRequest.commandLine.hasOption( CLIManager.ERRORS );
if ( cliRequest.debug )
{
cliRequest.request.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_DEBUG );
}
else if ( cliRequest.quiet )
{
// TODO: we need to do some more work here. Some plugins use sys out or log errors at info level.
// Ideally, we could use Warn across the board
cliRequest.request.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_ERROR );
// TODO:Additionally, we can't change the mojo level because the component key includes the version and
// it isn't known ahead of time. This seems worth changing.
}
else
{
cliRequest.request.setLoggingLevel( MavenExecutionRequest.LOGGING_LEVEL_INFO );
}
plexusLogger.setThreshold( cliRequest.request.getLoggingLevel() );
if ( cliRequest.commandLine.hasOption( CLIManager.LOG_FILE ) )
{
File logFile = new File( cliRequest.commandLine.getOptionValue( CLIManager.LOG_FILE ) );
logFile = resolveFile( logFile, cliRequest.workingDirectory );
try
{
cliRequest.fileStream = new PrintStream( logFile );
cliRequest.logger.setStream( cliRequest.fileStream );
}
catch ( FileNotFoundException e )
{
cliRequest.stderr.println( e );
cliRequest.logger.setStream( cliRequest.stdout );
}
}
else
{
cliRequest.logger.setStream( cliRequest.stdout );
}
cliRequest.request.setExecutionListener( new ExecutionEventLogger( cliRequest.logger ) );
}
private void commands( CliRequest cliRequest )
{
if ( cliRequest.debug || cliRequest.commandLine.hasOption( CLIManager.SHOW_VERSION ) )
{
CLIReportingUtils.showVersion( cliRequest.stdout );
}
if ( cliRequest.showErrors )
{
cliRequest.logger.info( "Error stacktraces are turned on." );
}
//
// TODO: move checksum policies to
//
if ( MavenExecutionRequest.CHECKSUM_POLICY_WARN.equals( cliRequest.request.getGlobalChecksumPolicy() ) )
{
cliRequest.logger.info( "Disabling strict checksum verification on all artifact downloads." );
}
else if ( MavenExecutionRequest.CHECKSUM_POLICY_FAIL.equals( cliRequest.request.getGlobalChecksumPolicy() ) )
{
cliRequest.logger.info( "Enabling strict checksum verification on all artifact downloads." );
}
}
private void properties( CliRequest cliRequest )
{
populateProperties( cliRequest.commandLine, cliRequest.systemProperties, cliRequest.userProperties );
}
// ----------------------------------------------------------------------
// System properties handling
// ----------------------------------------------------------------------
static void populateProperties( CommandLine commandLine, Properties systemProperties, Properties userProperties )
{
EnvironmentUtils.addEnvVars( systemProperties );
// ----------------------------------------------------------------------
// Options that are set on the command line become system properties
// and therefore are set in the session properties. System properties
// are most dominant.
// ----------------------------------------------------------------------
if ( commandLine.hasOption( CLIManager.SET_SYSTEM_PROPERTY ) )
{
String[] defStrs = commandLine.getOptionValues( CLIManager.SET_SYSTEM_PROPERTY );
if ( defStrs != null )
{
for ( int i = 0; i < defStrs.length; ++i )
{
setCliProperty( defStrs[i], userProperties );
}
}
}
systemProperties.putAll( System.getProperties() );
}
private static void setCliProperty( String property, Properties properties )
{
String name;
String value;
int i = property.indexOf( "=" );
if ( i <= 0 )
{
name = property.trim();
value = "true";
}
else
{
name = property.substring( 0, i ).trim();
value = property.substring( i + 1 );
}
properties.setProperty( name, value );
// ----------------------------------------------------------------------
// I'm leaving the setting of system properties here as not to break
// the SystemPropertyProfileActivator. This won't harm embedding. jvz.
// ----------------------------------------------------------------------
System.setProperty( name, value );
}
private void settings( CliRequest cliRequest )
throws Exception
{
File userSettingsFile;
if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_USER_SETTINGS ) )
{
userSettingsFile = new File( cliRequest.commandLine.getOptionValue( CLIManager.ALTERNATE_USER_SETTINGS ) );
userSettingsFile = resolveFile( userSettingsFile, cliRequest.workingDirectory );
if ( !userSettingsFile.isFile() )
{
throw new FileNotFoundException( "The specified user settings file does not exist: " + userSettingsFile );
}
}
else
{
userSettingsFile = MavenCli.DEFAULT_USER_SETTINGS_FILE;
}
cliRequest.logger.debug( "Reading user settings from " + userSettingsFile );
File globalSettingsFile;
if ( cliRequest.commandLine.hasOption( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) )
{
globalSettingsFile = new File( cliRequest.commandLine.getOptionValue( CLIManager.ALTERNATE_GLOBAL_SETTINGS ) );
globalSettingsFile = resolveFile( globalSettingsFile, cliRequest.workingDirectory );
if ( !globalSettingsFile.isFile() )
{
throw new FileNotFoundException( "The specified global settings file does not exist: "
+ globalSettingsFile );
}
}
else
{
globalSettingsFile = MavenCli.DEFAULT_GLOBAL_SETTINGS_FILE;
}
cliRequest.logger.debug( "Reading global settings from " + globalSettingsFile );
cliRequest.request.setGlobalSettingsFile( globalSettingsFile );
cliRequest.request.setUserSettingsFile( userSettingsFile );
SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest();
settingsRequest.setGlobalSettingsFile( globalSettingsFile );
settingsRequest.setUserSettingsFile( userSettingsFile );
settingsRequest.setSystemProperties( cliRequest.systemProperties );
settingsRequest.setUserProperties( cliRequest.userProperties );
SettingsBuildingResult settingsResult = settingsBuilder.build( settingsRequest );
executionRequestPopulator.populateFromSettings( cliRequest.request, settingsResult.getEffectiveSettings() );
if ( !settingsResult.getProblems().isEmpty() && cliRequest.logger.isWarnEnabled() )
{
cliRequest.logger.warn( "" );
cliRequest.logger.warn( "Some problems were encountered while building the effective settings" );
for ( SettingsProblem problem : settingsResult.getProblems() )
{
cliRequest.logger.warn( problem.getMessage() + " @ " + problem.getLocation() );
}
cliRequest.logger.warn( "" );
}
}
private MavenExecutionRequest populateRequest( CliRequest cliRequest )
{
MavenExecutionRequest request = cliRequest.request;
CommandLine commandLine = cliRequest.commandLine;
String workingDirectory = cliRequest.workingDirectory;
boolean debug = cliRequest.debug;
boolean quiet = cliRequest.quiet;
boolean showErrors = cliRequest.showErrors;
String[] deprecatedOptions = { "up", "npu", "cpu", "npr" };
for ( String deprecatedOption : deprecatedOptions )
{
if ( commandLine.hasOption( deprecatedOption ) )
{
cliRequest.stdout.println( "[WARNING] Command line option -" + deprecatedOption
+ " is deprecated and will be removed in future Maven versions." );
}
}
// ----------------------------------------------------------------------
// Now that we have everything that we need we will fire up plexus and
// bring the maven component to life for use.
// ----------------------------------------------------------------------
if ( commandLine.hasOption( CLIManager.BATCH_MODE ) )
{
request.setInteractiveMode( false );
}
boolean noSnapshotUpdates = false;
if ( commandLine.hasOption( CLIManager.SUPRESS_SNAPSHOT_UPDATES ) )
{
noSnapshotUpdates = true;
}
// ----------------------------------------------------------------------
//
// ----------------------------------------------------------------------
@SuppressWarnings("unchecked")
List<String> goals = commandLine.getArgList();
boolean recursive = true;
// this is the default behavior.
String reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
if ( commandLine.hasOption( CLIManager.NON_RECURSIVE ) )
{
recursive = false;
}
if ( commandLine.hasOption( CLIManager.FAIL_FAST ) )
{
reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST;
}
else if ( commandLine.hasOption( CLIManager.FAIL_AT_END ) )
{
reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_AT_END;
}
else if ( commandLine.hasOption( CLIManager.FAIL_NEVER ) )
{
reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_NEVER;
}
if ( commandLine.hasOption( CLIManager.OFFLINE ) )
{
request.setOffline( true );
}
boolean updateSnapshots = false;
if ( commandLine.hasOption( CLIManager.UPDATE_SNAPSHOTS ) )
{
updateSnapshots = true;
}
String globalChecksumPolicy = null;
if ( commandLine.hasOption( CLIManager.CHECKSUM_FAILURE_POLICY ) )
{
globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_FAIL;
}
else if ( commandLine.hasOption( CLIManager.CHECKSUM_WARNING_POLICY ) )
{
globalChecksumPolicy = MavenExecutionRequest.CHECKSUM_POLICY_WARN;
}
File baseDirectory = new File( workingDirectory, "" ).getAbsoluteFile();
// ----------------------------------------------------------------------
// Profile Activation
// ----------------------------------------------------------------------
List<String> activeProfiles = new ArrayList<String>();
List<String> inactiveProfiles = new ArrayList<String>();
if ( commandLine.hasOption( CLIManager.ACTIVATE_PROFILES ) )
{
String[] profileOptionValues = commandLine.getOptionValues( CLIManager.ACTIVATE_PROFILES );
if ( profileOptionValues != null )
{
for ( int i = 0; i < profileOptionValues.length; ++i )
{
StringTokenizer profileTokens = new StringTokenizer( profileOptionValues[i], "," );
while ( profileTokens.hasMoreTokens() )
{
String profileAction = profileTokens.nextToken().trim();
if ( profileAction.startsWith( "-" ) || profileAction.startsWith( "!" ) )
{
inactiveProfiles.add( profileAction.substring( 1 ) );
}
else if ( profileAction.startsWith( "+" ) )
{
activeProfiles.add( profileAction.substring( 1 ) );
}
else
{
activeProfiles.add( profileAction );
}
}
}
}
}
TransferListener transferListener;
if ( quiet )
{
transferListener = new QuietMavenTransferListener( );
}
else if ( request.isInteractiveMode() )
{
transferListener = new ConsoleMavenTransferListener( cliRequest.stdout );
}
else
{
transferListener = new BatchModeMavenTransferListener( cliRequest.stdout );
}
//transferListener. .setShowChecksumEvents( false );
String alternatePomFile = null;
if ( commandLine.hasOption( CLIManager.ALTERNATE_POM_FILE ) )
{
alternatePomFile = commandLine.getOptionValue( CLIManager.ALTERNATE_POM_FILE );
}
int loggingLevel;
if ( debug )
{
loggingLevel = MavenExecutionRequest.LOGGING_LEVEL_DEBUG;
}
else if ( quiet )
{
// TODO: we need to do some more work here. Some plugins use sys out or log errors at info level.
// Ideally, we could use Warn across the board
loggingLevel = MavenExecutionRequest.LOGGING_LEVEL_ERROR;
// TODO:Additionally, we can't change the mojo level because the component key includes the version and
// it isn't known ahead of time. This seems worth changing.
}
else
{
loggingLevel = MavenExecutionRequest.LOGGING_LEVEL_INFO;
}
File userToolchainsFile;
if ( commandLine.hasOption( CLIManager.ALTERNATE_USER_TOOLCHAINS ) )
{
userToolchainsFile = new File( commandLine.getOptionValue( CLIManager.ALTERNATE_USER_TOOLCHAINS ) );
userToolchainsFile = resolveFile( userToolchainsFile, workingDirectory );
}
else
{
userToolchainsFile = MavenCli.DEFAULT_USER_TOOLCHAINS_FILE;
}
request.setBaseDirectory( baseDirectory ).setGoals( goals ).setSystemProperties( cliRequest.systemProperties )
.setUserProperties( cliRequest.userProperties ).setReactorFailureBehavior( reactorFailureBehaviour ) // default: fail fast
.setRecursive( recursive ) // default: true
.setShowErrors( showErrors ) // default: false
.addActiveProfiles( activeProfiles ) // optional
.addInactiveProfiles( inactiveProfiles ) // optional
.setLoggingLevel( loggingLevel ) // default: info
.setTransferListener( transferListener ) // default: batch mode which goes along with interactive
.setUpdateSnapshots( updateSnapshots ) // default: false
.setNoSnapshotUpdates( noSnapshotUpdates ) // default: false
.setGlobalChecksumPolicy( globalChecksumPolicy ) // default: warn
.setUserToolchainsFile( userToolchainsFile );
if ( alternatePomFile != null )
{
File pom = resolveFile( new File( alternatePomFile ), workingDirectory );
request.setPom( pom );
}
else
{
File pom = modelProcessor.locatePom( baseDirectory );
if ( pom.isFile() )
{
request.setPom( pom );
}
}
if ( ( request.getPom() != null ) && ( request.getPom().getParentFile() != null ) )
{
request.setBaseDirectory( request.getPom().getParentFile() );
}
if ( commandLine.hasOption( CLIManager.RESUME_FROM ) )
{
request.setResumeFrom( commandLine.getOptionValue( CLIManager.RESUME_FROM ) );
}
if ( commandLine.hasOption( CLIManager.PROJECT_LIST ) )
{
String projectList = commandLine.getOptionValue( CLIManager.PROJECT_LIST );
String[] projects = StringUtils.split( projectList, "," );
request.setSelectedProjects( Arrays.asList( projects ) );
}
if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && !commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_UPSTREAM );
}
else if ( !commandLine.hasOption( CLIManager.ALSO_MAKE )
&& commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_DOWNSTREAM );
}
else if ( commandLine.hasOption( CLIManager.ALSO_MAKE )
&& commandLine.hasOption( CLIManager.ALSO_MAKE_DEPENDENTS ) )
{
request.setMakeBehavior( MavenExecutionRequest.REACTOR_MAKE_BOTH );
}
String localRepoProperty = request.getUserProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
if ( localRepoProperty == null )
{
localRepoProperty = request.getSystemProperties().getProperty( MavenCli.LOCAL_REPO_PROPERTY );
}
if ( localRepoProperty != null )
{
request.setLocalRepositoryPath( localRepoProperty );
}
final String threadConfiguration = commandLine.hasOption( CLIManager.THREADS ) ? commandLine
.getOptionValue( CLIManager.THREADS ) : request.getSystemProperties()
.getProperty( MavenCli.THREADS_DEPRECATED ); // TODO: Remove this setting. Note that the int-tests use it
if ( threadConfiguration != null )
{
request.setPerCoreThreadCount( threadConfiguration.contains( "C" ) );
if ( threadConfiguration.contains( "W" ) )
{
LifecycleWeaveBuilder.setWeaveMode( request.getUserProperties() );
}
request.setThreadCount( threadConfiguration.replace( "C", "" ).replace( "W", "" ).replace( "auto", "" ) );
}
return request;
}
private void encryption( CliRequest cliRequest )
throws Exception
{
if ( cliRequest.commandLine.hasOption( CLIManager.ENCRYPT_MASTER_PASSWORD ) )
{
String passwd = cliRequest.commandLine.getOptionValue( CLIManager.ENCRYPT_MASTER_PASSWORD );
DefaultPlexusCipher cipher = new DefaultPlexusCipher();
cliRequest.stdout.println( cipher.encryptAndDecorate( passwd,
DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION ) );
throw new MavenCli.ExitException( 0 );
}
else if ( cliRequest.commandLine.hasOption( CLIManager.ENCRYPT_PASSWORD ) )
{
String passwd = cliRequest.commandLine.getOptionValue( CLIManager.ENCRYPT_PASSWORD );
String configurationFile = dispatcher.getConfigurationFile();
if ( configurationFile.startsWith( "~" ) )
{
configurationFile = System.getProperty( "user.home" ) + configurationFile.substring( 1 );
}
String file = System.getProperty( DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile );
String master = null;
SettingsSecurity sec = SecUtil.read( file, true );
if ( sec != null )
{
master = sec.getMaster();
}
if ( master == null )
{
throw new IllegalStateException( "Master password is not set in the setting security file: " + file );
}
DefaultPlexusCipher cipher = new DefaultPlexusCipher();
String masterPasswd = cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
cliRequest.stdout.println( cipher.encryptAndDecorate( passwd, masterPasswd ) );
throw new MavenCli.ExitException( 0 );
}
}
static class CliRequest
{
String[] args;
CommandLine commandLine;
PrintStream stdout;
PrintStream stderr;
ClassWorld classWorld;
String workingDirectory;
boolean debug;
boolean quiet;
boolean showErrors = true;
PrintStream fileStream;
Properties userProperties = new Properties();
Properties systemProperties = new Properties();
MavenExecutionRequest request;
PrintStreamLogger logger;
CliRequest( String[] args, ClassWorld classWorld )
{
this.args = args;
this.classWorld = classWorld;
this.request = new DefaultMavenExecutionRequest();
}
}
}
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 );
}
}
package org.jvnet.hudson.maven3.launcher;
/*
* Olivier Lamy
* 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 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 );
MavenExecutionResult result = maven.execute( request );
hudsonMavenExecutionResult = new HudsonMavenExecutionResult( result );
// 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;
/*
* Olivier Lamy
* 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.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();
if (mavenProjects != null)
{
for (MavenProject mavenProject : mavenProjects)
{
MavenProjectInfo mavenProjectInfo = new MavenProjectInfo( mavenProject );
mavenProjectInfos.add( mavenProjectInfo );
BuildSummary buildSummary = mavenExecutionResult.getBuildSummary( mavenProject );
// NPE free : looks to have null here when the projects is not finished ie tests failures
if ( buildSummary != null )
{
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;
/*
* Olivier Lamy
* 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.Serializable;
import org.apache.maven.project.ProjectBuildingResult;
/**
* @author Olivier Lamy
* @since
*/
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();
}
}
package org.jvnet.hudson.maven3.listeners;
/*
* Olivier Lamy
* 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.Serializable;
import org.apache.maven.project.MavenProject;
/**
* @author Olivier Lamy
* @since
*/
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;
}
}
......@@ -43,10 +43,6 @@ THE SOFTWARE.
<module>core</module>
<module>maven-plugin</module>
<module>ui-samples-plugin</module>
<module>maven-agent</module>
<module>maven-interceptor</module>
<module>maven3-agent</module>
<module>maven3-interceptor</module>
<module>war</module>
<module>test</module>
<module>cli</module>
......@@ -303,84 +299,7 @@ THE SOFTWARE.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-api</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-impl</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-spi</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-util</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-connector-wagon</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-provider-api</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
<version>${sisuInjectVersion}</version>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-bean</artifactId>
<version>${sisuInjectVersion}</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
......@@ -402,11 +321,6 @@ THE SOFTWARE.
</dependencyManagement>
<properties>
<mavenVersion>3.0.3</mavenVersion>
<maven.version>${mavenVersion}</maven.version>
<aetherVersion>1.11</aetherVersion>
<sisuInjectVersion>1.4.3.1</sisuInjectVersion>
<wagonVersion>1.0-beta-7</wagonVersion>
<!-- *.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>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册