提交 c85e60f1 编写于 作者: S Seiji Sogabe

Sorry my mistake.

上级 535e9686
......@@ -6,11 +6,13 @@ work
*.iws
*.ipr
.idea
=======
# eclipse project file
.settings
.classpath
.project
build
war/images/16x16
war/images/24x24
......@@ -29,3 +31,5 @@ debian/configure-stamp
*.debhelper.log
hudson_*.build
hudson_*.changes
=======
push-build.sh
......@@ -461,7 +461,6 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
......
......@@ -646,6 +646,13 @@ public abstract class PluginManager extends AbstractModelObject {
}
return Collections.enumeration(resources);
}
@Override
public String toString()
{
// only for debugging purpose
return "classLoader " + getClass().getName();
}
}
private static final Logger LOGGER = Logger.getLogger(PluginManager.class.getName());
......
......@@ -362,6 +362,7 @@ public class Maven extends Builder {
*/
public static final int MAVEN_20 = 0;
public static final int MAVEN_21 = 1;
public static final int MAVEN_30 = 2;
/**
......@@ -405,6 +406,8 @@ public class Maven extends Builder {
* Represents the minimum required Maven version - constants defined above.
*/
public boolean meetsMavenReqVersion(Launcher launcher, int mavenReqVersion) throws IOException, InterruptedException {
// FIXME using similar stuff as in the maven plugin could be better
// olamy : but will add a dependency on maven in core -> so not so good
String mavenVersion = launcher.getChannel().call(new Callable<String,IOException>() {
public String call() throws IOException {
File[] jars = new File(getHomeDir(),"lib").listFiles();
......@@ -428,6 +431,10 @@ public class Maven extends Builder {
if(mavenVersion.startsWith("maven-2.") && !mavenVersion.startsWith("maven-2.0"))
return true;
}
else if (mavenReqVersion == MAVEN_30) {
if(mavenVersion.startsWith("maven-3.") && !mavenVersion.startsWith("maven-2.0"))
return true;
}
}
return false;
......
......@@ -33,10 +33,10 @@ THE SOFTWARE.
<artifactId>maven-agent</artifactId>
<packaging>jar</packaging>
<name>Hudson Maven CLI agent</name>
<name>Hudson Maven2 CLI agent</name>
<description>
Code that boots up Maven2 with Hudson's remoting support in place.
Used for the native m2 support.
Used for the native maven support.
</description>
<build>
......@@ -73,12 +73,24 @@ THE SOFTWARE.
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven-interceptor</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
<version>1.1</version>
</dependency>
<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>
......@@ -90,8 +102,14 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<scope>test</scope>
<version>2.0.9</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
......
......@@ -23,25 +23,25 @@
*/
package hudson.maven.agent;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.classworlds.ClassWorld;
import org.codehaus.classworlds.DefaultClassRealm;
import org.codehaus.classworlds.Launcher;
import org.codehaus.classworlds.NoSuchRealmException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.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.
......@@ -110,9 +110,14 @@ public class Main {
// 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());
......@@ -156,10 +161,13 @@ public class Main {
/**
* 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 = launcher.getWorld();
//ClassWorld world = ClassWorldAdapter.getInstance( launcher.getWorld() );
ClassWorld world = launcher.getWorld();
Set builtinRealms = new HashSet(world.getRealms());
try {
launcher.launch(args);
......@@ -178,4 +186,4 @@ public class Main {
}
return launcher.getExitCode();
}
}
\ No newline at end of file
}
......@@ -10,4 +10,4 @@ load ${maven.interceptor.override}
load ${maven.interceptor}
load ${maven.home}/lib/*.jar
[plexus.core.maven]
[plexus.core.maven]
\ No newline at end of file
......@@ -33,7 +33,7 @@ THE SOFTWARE.
<artifactId>maven-interceptor</artifactId>
<packaging>jar</packaging>
<name>Hudson Maven PluginManager interceptor</name>
<name>Hudson Maven 2 PluginManager interceptor</name>
<description>
Plexus module that intercepts invocations of key Maven components
so that Hudson can monitor what's going on in Maven.
......@@ -43,9 +43,17 @@ THE SOFTWARE.
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven.version}</version>
<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>
......
......@@ -23,16 +23,19 @@
*/
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.plugin.Mojo;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.InvalidDependencyVersionException;
import org.apache.maven.reporting.MavenReport;
......@@ -43,13 +46,10 @@ import org.codehaus.plexus.component.configurator.ComponentConfigurationExceptio
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.ComponentLookupException;
import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* Description in META-INF/plexus/components.xml makes it possible to use this instead of the default
* plugin manager.
......
......@@ -37,165 +37,308 @@ THE SOFTWARE.
Now it is a plug-in that is installed by default, but can be disabled.</description>
<url>http://wiki.hudson-ci.org/display/HUDSON/Maven+2+Project+Plugin</url>
<dependencies>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>hudson-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>maven-agent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven2.1-interceptor</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven-embedder</artifactId>
<version>2.0.4-hudson-1</version>
<!--exclusions> These are needed for Maven embedder to resolve parent POMs in remote repositories
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
</exclusion>
</exclusions-->
<exclusions>
<exclusion><!-- we'll add our own patched version. see http://www.nabble.com/Issue-1680-td18383889.html -->
<groupId>jtidy</groupId>
<artifactId>jtidy</artifactId>
</exclusion>
<exclusion>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<!-- we bundle our own version below -->
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependencies>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>hudson-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>maven-agent</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven-interceptor</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>maven2.1-interceptor</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven3-agent</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>maven3-interceptor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-api</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-impl</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-spi</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-util</artifactId>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
<artifactId>aether-connector-wagon</artifactId>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
<exclusions>
<exclusion>
<groupId>nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</exclusion>
<exclusion>
<groupId>nekohtml</groupId>
<artifactId>xercesMinimal</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ftp</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<!-- commonly used wagon provider -->
<groupId>org.jvnet.hudson</groupId>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-provider-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>hudson-maven-artifact-manager</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>hudson-maven-embedder</artifactId>
<version>3.0</version>
<exclusions>
<exclusion><!-- we'll add our own patched version. see http://www.nabble.com/Issue-1680-td18383889.html -->
<groupId>jtidy</groupId>
<artifactId>jtidy</artifactId>
</exclusion>
<exclusion>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<!-- we bundle our own version below -->
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav</artifactId>
<version>1.0-beta-2-hudson-1</version>
<exclusions>
<exclusion>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</exclusion>
<build>
<!--
Since new versions need to overwrite old versions, it's better
not to have version number in the .hpi file name.
-->
<finalName>${project.artifactId}</finalName>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.jvnet.hudson.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<version>1.54</version>
<extensions>true</extensions>
<configuration>
<showDeprecation>true</showDeprecation>
<disabledTestInjection>true</disabledTestInjection>
</configuration>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<version>1.12</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<fileMask>Messages.properties</fileMask>
<outputDirectory>target/generated-sources/localizer</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>cobertura2</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.4-apb-SNAPSHOT</version>
<inherited>true</inherited>
<!-- prefer net.sourceforge.nekohtml:nekohtml:jar:1.9.13 so that we use consistent version across Hudson -->
<exclusion>
<groupId>nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</exclusion>
<exclusion>
<groupId>nekohtml</groupId>
<artifactId>xercesMinimal</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<!-- commonly used wagon provider -->
<groupId>org.jvnet.hudson</groupId>
<artifactId>wagon-webdav</artifactId>
<version>1.0-beta-2-hudson-1</version>
<exclusions>
<exclusion>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.13</version>
</dependency>
</dependencies>
<build>
<!--
Since new versions need to overwrite old versions, it's better
not to have version number in the .hpi file name.
-->
<finalName>${project.artifactId}</finalName>
<defaultGoal>package</defaultGoal>
<plugins>
<plugin>
<groupId>org.jvnet.hudson.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<version>1.54</version>
<extensions>true</extensions>
<configuration>
<showDeprecation>true</showDeprecation>
<disabledTestInjection>true</disabledTestInjection>
</configuration>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<version>1.12</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<fileMask>Messages.properties</fileMask>
<outputDirectory>target/generated-sources/localizer</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jvnet.maven-antrun-extended-plugin</groupId>
<artifactId>maven-antrun-extended-plugin</artifactId>
<executions>
<execution>
<id>resgen</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
<verifyArtifact>false</verifyArtifact>
<tasks>
<mkdir dir="target/classes" />
<!-- classworld 1.1 for maven 2 builds -->
<resolveArtifact groupId="classworlds" artifactId="classworlds" version="1.1" type="jar" tofile="target/classes/classworlds.jar" />
</tasks>
</configuration>
<executions>
<execution>
<id>coverage-instrument</id>
<phase>process-test-classes</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>coverage-report</id>
<phase>test</phase>
<goals>
<goal>generate-report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>cobertura2</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.4-apb-SNAPSHOT</version>
<inherited>true</inherited>
<configuration>
<formats>
<format>html</format>
<format>xml</format>
</formats>
</configuration>
<executions>
<execution>
<id>coverage-instrument</id>
<phase>process-test-classes</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
<execution>
<id>coverage-report</id>
<phase>test</phase>
<goals>
<goal>generate-report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.remoting.DelegatingCallable;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.List;
import java.util.Map;
/**
* @author Olivier Lamy
*
*/
public abstract class AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Goals to be executed in this Maven execution.
*/
protected final List<String> goals;
/**
* Hudson-defined system properties. These will be made available to Maven,
* and accessible as if they are specified as -Dkey=value
*/
protected final Map<String,String> systemProps;
/**
* Where error messages and so on are sent.
*/
protected final BuildListener listener;
protected AbstractMavenBuilder(BuildListener listener, List<String> goals, Map<String, String> systemProps) {
this.listener = listener;
this.goals = goals;
this.systemProps = systemProps;
}
protected String formatArgs(List<String> args) {
StringBuilder buf = new StringBuilder("Executing Maven: ");
for (String arg : args) {
final String argPassword = "-Dpassword=" ;
String filteredArg = arg ;
// check if current arg is password arg. Then replace password by *****
if (arg.startsWith(argPassword)) {
filteredArg=argPassword+"*********";
}
buf.append(' ').append(filteredArg);
}
return buf.toString();
}
protected String format(NumberFormat n, long nanoTime) {
return n.format(nanoTime/1000000);
}
// since reporters might be from plugins, use the uberjar to resolve them.
public ClassLoader getClassLoader() {
return Hudson.getInstance().getPluginManager().uberClassLoader;
}
}
......@@ -24,22 +24,25 @@
package hudson.maven;
import hudson.model.TaskListener;
import org.apache.maven.embedder.AbstractMavenEmbedderLogger;
import org.apache.maven.embedder.MavenEmbedderLogger;
import java.io.PrintStream;
import java.util.StringTokenizer;
import org.apache.maven.cli.MavenLoggerManager;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
/**
* {@link MavenEmbedderLogger} implementation that
* sends output to {@link TaskListener}.
*
* @author Kohsuke Kawaguchi
*/
public final class EmbedderLoggerImpl extends AbstractMavenEmbedderLogger {
public final class EmbedderLoggerImpl extends MavenLoggerManager {
private final PrintStream logger;
public EmbedderLoggerImpl(TaskListener listener) {
public EmbedderLoggerImpl(TaskListener listener, int threshold) {
super(new ConsoleLogger( threshold, "hudson-logger" ));
logger = listener.getLogger();
}
......@@ -57,22 +60,22 @@ public final class EmbedderLoggerImpl extends AbstractMavenEmbedderLogger {
}
public void debug(String message, Throwable throwable) {
print(message, throwable, LEVEL_DEBUG, "[DEBUG] ");
print(message, throwable, Logger.LEVEL_DEBUG, "[DEBUG] ");
}
public void info(String message, Throwable throwable) {
print(message, throwable, LEVEL_INFO, "[INFO ] ");
print(message, throwable, Logger.LEVEL_INFO, "[INFO ] ");
}
public void warn(String message, Throwable throwable) {
print(message, throwable, LEVEL_WARN, "[WARN ] ");
print(message, throwable, Logger.LEVEL_WARN, "[WARN ] ");
}
public void error(String message, Throwable throwable) {
print(message, throwable, LEVEL_ERROR, "[ERROR] ");
print(message, throwable, Logger.LEVEL_ERROR, "[ERROR] ");
}
public void fatalError(String message, Throwable throwable) {
print(message, throwable, LEVEL_FATAL, "[FATAL] ");
print(message, throwable, Logger.LEVEL_FATAL, "[FATAL] ");
}
}
......@@ -23,22 +23,24 @@
*/
package hudson.maven;
import static hudson.Util.intern;
import hudson.Util;
import hudson.model.Hudson;
import hudson.remoting.Which;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.kohsuke.stapler.Stapler;
import hudson.util.ReflectionUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.logging.Logger;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import static hudson.Util.intern;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.kohsuke.stapler.Stapler;
/**
* Persisted record of mojo execution.
......@@ -80,7 +82,7 @@ public final class ExecutedMojo implements Serializable {
*/
public final String digest;
ExecutedMojo(MojoInfo mojo, long duration) throws IOException, InterruptedException {
public ExecutedMojo(MojoInfo mojo, long duration) throws IOException, InterruptedException {
this.groupId = mojo.pluginName.groupId;
this.artifactId = mojo.pluginName.artifactId;
this.version = mojo.pluginName.version;
......@@ -92,7 +94,7 @@ public final class ExecutedMojo implements Serializable {
MojoDescriptor md = mojo.mojoExecution.getMojoDescriptor();
PluginDescriptor pd = md.getPluginDescriptor();
try {
Class clazz = pd.getClassRealm().loadClass(md.getImplementation());
Class clazz = getMojoClass( md, pd );// pd.getClassRealm().loadClass(md.getImplementation());
digest = Util.getDigestOf(new FileInputStream(Which.jarFile(clazz)));
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING, "Failed to locate jar for "+md.getImplementation(),e);
......@@ -101,6 +103,28 @@ public final class ExecutedMojo implements Serializable {
}
this.digest = digest;
}
private Class<?> getMojoClass(MojoDescriptor md, PluginDescriptor pd) throws ClassNotFoundException {
try {
return pd.getClassRealm().loadClass( md.getImplementation() );
} catch (NoSuchMethodError e) {
// maybe we are in maven2 build ClassRealm package has changed
return getMojoClassForMaven2( md, pd );
}
}
private Class<?> getMojoClassForMaven2(MojoDescriptor md, PluginDescriptor pd) throws ClassNotFoundException {
Method method = ReflectionUtils.getPublicMethodNamed( pd.getClass(), "getClassRealm" );
org.codehaus.classworlds.ClassRealm cl =
(org.codehaus.classworlds.ClassRealm) ReflectionUtils.invokeMethod( method, pd );
Class<?> clazz = cl.loadClass( md.getImplementation() );
return clazz;
}
/**
* Copy constructor used for interning.
......
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import static hudson.Util.fixNull;
import hudson.AbortException;
import hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Executor;
import hudson.model.Hudson;
import hudson.model.JDK;
import hudson.model.Node;
import hudson.model.Run.RunnerAbortedException;
import hudson.model.TaskListener;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.RemoteInputStream;
import hudson.remoting.RemoteOutputStream;
import hudson.remoting.SocketInputStream;
import hudson.remoting.SocketOutputStream;
import hudson.remoting.Which;
import hudson.slaves.Channels;
import hudson.tasks.Maven.MavenInstallation;
import hudson.util.ArgumentListBuilder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Arrays;
import java.util.logging.Logger;
import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
import org.kohsuke.stapler.framework.io.IOException2;
/**
* @author Olivier Lamy
*
*/
public class Maven3ProcessFactory implements ProcessCache.Factory
{
private final MavenModuleSet mms;
private final Launcher launcher;
/**
* Environment variables to be set to the maven process.
* The same variables are exposed to the system property as well.
*/
private final EnvVars envVars;
/**
* Optional working directory. Because of the process reuse, we can't always guarantee
* that the returned Maven process has this as the working directory. But for the
* aggregator style build, the process reuse is disabled, so in practice this always works.
*
* Also, Maven is supposed to work correctly regardless of the process current directory,
* so a good behaving maven project shouldn't rely on the current project.
*/
private final FilePath workDir;
Maven3ProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, FilePath workDir) {
this.mms = mms;
this.launcher = launcher;
this.envVars = envVars;
this.workDir = workDir;
}
/**
* Represents a bi-directional connection.
*
* <p>
* This implementation is remoting aware, so it can be safely sent to the remote callable object.
*
* <p>
* When we run Maven on a slave, the master may not have a direct TCP/IP connectivty to the slave.
* That means the {@link Channel} between the master and the Maven needs to be tunneled through
* the channel between master and the slave, then go to TCP socket to the Maven.
*/
private static final class Connection implements Serializable {
public InputStream in;
public OutputStream out;
Connection(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
private Object writeReplace() {
return new Connection(new RemoteInputStream(in),new RemoteOutputStream(out));
}
private Object readResolve() {
// ObjectInputStream seems to access data at byte-level and do not do any buffering,
// so if we are remoted, buffering would be crucial.
this.in = new BufferedInputStream(in);
this.out = new BufferedOutputStream(out);
return this;
}
private static final long serialVersionUID = 1L;
}
interface Acceptor {
Connection accept() throws IOException;
int getPort();
}
/**
* Opens a server socket and returns {@link Acceptor} so that
* we can accept a connection later on it.
*/
private static final class SocketHandler implements Callable<Acceptor,IOException> {
public Acceptor call() throws IOException {
return new AcceptorImpl();
}
private static final long serialVersionUID = 1L;
static final class AcceptorImpl implements Acceptor, Serializable {
private transient final ServerSocket serverSocket;
private transient Socket socket;
AcceptorImpl() throws IOException {
// open a TCP socket to talk to the launched Maven process.
// let the OS pick up a random open port
this.serverSocket = new ServerSocket();
serverSocket.bind(null); // new InetSocketAddress(InetAddress.getLocalHost(),0));
// prevent a hang at the accept method in case the forked process didn't start successfully
serverSocket.setSoTimeout(MavenProcessFactory.socketTimeOut);
}
public Connection accept() throws IOException {
socket = serverSocket.accept();
// we'd only accept one connection
serverSocket.close();
return new Connection(new SocketInputStream(socket),new SocketOutputStream(socket));
}
public int getPort() {
return serverSocket.getLocalPort();
}
/**
* When sent to the remote node, send a proxy.
*/
private Object writeReplace() {
return Channel.current().export(Acceptor.class, this);
}
}
}
/**
* Starts maven process.
*/
public ProcessCache.NewProcess newProcess(BuildListener listener, OutputStream out) throws IOException, InterruptedException {
if(MavenProcessFactory.debug)
listener.getLogger().println("Using env variables: "+ envVars);
try {
final Acceptor acceptor = launcher.getChannel().call(new SocketHandler());
final ArgumentListBuilder cmdLine = buildMavenAgentCmdLine(listener,acceptor.getPort());
String[] cmds = cmdLine.toCommandArray();
final Proc proc = launcher.launch().cmds(cmds).envs(envVars).stdout(out).pwd(workDir).start();
Connection con;
try {
con = acceptor.accept();
} catch (SocketTimeoutException e) {
// failed to connect. Is the process dead?
// if so, the error should have been provided by the launcher already.
// so abort gracefully without a stack trace.
if(!proc.isAlive())
throw new AbortException("Failed to launch Maven. Exit code = "+proc.join());
throw e;
}
return new ProcessCache.NewProcess(
Channels.forProcess("Channel to Maven "+ Arrays.toString(cmds),
Computer.threadPoolForRemoting, new BufferedInputStream(con.in), new BufferedOutputStream(con.out),
listener.getLogger(), proc),
proc);
} catch (IOException e) {
if(fixNull(e.getMessage()).contains("java: not found")) {
// diagnose issue #659
JDK jdk = mms.getJDK();
if(jdk==null)
throw new IOException2(mms.getDisplayName()+" is not configured with a JDK, but your PATH doesn't include Java",e);
}
throw e;
}
}
/**
* Builds the command line argument list to launch the maven process.
*
*/
private ArgumentListBuilder buildMavenAgentCmdLine(BuildListener listener,int tcpPort) throws IOException, InterruptedException {
MavenInstallation mvn = getMavenInstallation(listener);
if(mvn==null) {
listener.error("Maven version is not configured for this project. Can't determine which Maven to run");
throw new RunnerAbortedException();
}
if(mvn.getHome()==null) {
listener.error("Maven '%s' doesn't have its home set",mvn.getName());
throw new RunnerAbortedException();
}
// find classworlds.jar
String classWorldsJar = launcher.getChannel().call(new GetClassWorldsJar(mvn.getHome(),listener));
boolean isMaster = getCurrentNode()== Hudson.getInstance();
FilePath slaveRoot=null;
if(!isMaster)
slaveRoot = getCurrentNode().getRootPath();
ArgumentListBuilder args = new ArgumentListBuilder();
JDK jdk = getJava(listener);
if(jdk==null) {
args.add("java");
} else {
args.add(jdk.getHome()+"/bin/java"); // use JDK.getExecutable() here ?
}
if(MavenProcessFactory.debugPort!=0)
args.add("-Xrunjdwp:transport=dt_socket,server=y,address="+MavenProcessFactory.debugPort);
if(MavenProcessFactory.yjp)
args.add("-agentlib:yjpagent=tracing");
args.addTokenized(getMavenOpts());
args.add("-cp");
args.add(
(isMaster? Which.jarFile(Maven3Main.class).getAbsolutePath():slaveRoot.child("maven3-agent.jar").getRemote())+
(launcher.isUnix()?":":";")+classWorldsJar);
args.add(Maven3Main.class.getName());
// M2_HOME
args.add(mvn.getHome());
// remoting.jar
String remotingJar = launcher.getChannel().call(new GetRemotingJar());
if(remotingJar==null) {// this shouldn't be possible, but there are still reports indicating this, so adding a probe here.
listener.error("Failed to determine the location of slave.jar");
throw new RunnerAbortedException();
}
args.add(remotingJar);
args.add(isMaster?
Which.jarFile(Maven3Launcher.class).getAbsolutePath():
slaveRoot.child("maven3-interceptor.jar").getRemote());
// TCP/IP port to establish the remoting infrastructure
args.add(tcpPort);
return args;
}
public String getMavenOpts() {
String mavenOpts = mms.getMavenOpts();
if ((mavenOpts==null) || (mavenOpts.trim().length()==0)) {
Node n = getCurrentNode();
if (n!=null) {
try {
String localMavenOpts = n.toComputer().getEnvironment().get("MAVEN_OPTS");
if ((localMavenOpts!=null) && (localMavenOpts.trim().length()>0)) {
mavenOpts = localMavenOpts;
}
} catch (IOException e) {
} catch (InterruptedException e) {
// Don't do anything - this just means the slave isn't running, so we
// don't want to use its MAVEN_OPTS anyway.
}
}
}
return envVars.expand(mavenOpts);
}
public MavenInstallation getMavenInstallation(TaskListener log) throws IOException, InterruptedException {
MavenInstallation mi = mms.getMaven();
if (mi != null) mi = mi.forNode(getCurrentNode(), log).forEnvironment(envVars);
return mi;
}
public JDK getJava(TaskListener log) throws IOException, InterruptedException {
JDK jdk = mms.getJDK();
if (jdk != null) jdk = jdk.forNode(getCurrentNode(), log).forEnvironment(envVars);
return jdk;
}
/**
* Finds classworlds.jar
*/
private static final class GetClassWorldsJar implements Callable<String,IOException> {
private final String mvnHome;
private final TaskListener listener;
private GetClassWorldsJar(String mvnHome, TaskListener listener) {
this.mvnHome = mvnHome;
this.listener = listener;
}
public String call() throws IOException {
File home = new File(mvnHome);
if (MavenProcessFactory.debug)
listener.getLogger().println("Using mvnHome: "+ mvnHome);
File bootDir = new File(home, "boot");
File[] classworlds = bootDir.listFiles(CLASSWORLDS_FILTER);
if(classworlds==null || classworlds.length==0) {
// Maven 2.0.6 puts it to a different place
bootDir = new File(home, "boot");
classworlds = bootDir.listFiles(CLASSWORLDS_FILTER);
if(classworlds==null || classworlds.length==0) {
// FIXME use messages
//listener.error(Messages.MavenProcessFactory_ClassWorldsNotFound(home));
listener.error("classworld not found");
throw new RunnerAbortedException();
}
}
return classworlds[0].getAbsolutePath();
}
}
private static final class GetRemotingJar implements Callable<String,IOException> {
public String call() throws IOException {
return Which.jarFile(hudson.remoting.Launcher.class).getPath();
}
}
/**
* Returns the current {@link Node} on which we are buildling.
*/
private Node getCurrentNode() {
return Executor.currentExecutor().getOwner().getNode();
}
/**
* Locates classworlds jar file.
*
* Note that Maven 3.0 changed the name to plexus-classworlds
*
* <pre>
* $ find tools/ -name "plexus-classworlds*.jar"
* tools/maven-3.0-alpha-2/boot/plexus-classworlds-1.3.jar
* tools/maven-3.0-alpha-3/boot/plexus-classworlds-2.2.2.jar
* tools/maven-3.0-alpha-4/boot/plexus-classworlds-2.2.2.jar
* tools/maven-3.0-alpha-5/boot/plexus-classworlds-2.2.2.jar
* tools/maven-3.0-alpha-6/boot/plexus-classworlds-2.2.2.jar
* </pre>
*/
private static final FilenameFilter CLASSWORLDS_FILTER = new FilenameFilter() {
public boolean accept(File dir, String name) {
return name.contains("plexus-classworlds") && name.endsWith(".jar");
}
};
private static final Logger LOGGER = Logger.getLogger(MavenProcessFactory.class.getName());
}
......@@ -30,6 +30,7 @@ import hudson.slaves.WorkspaceList;
import hudson.slaves.WorkspaceList.Lease;
import hudson.maven.agent.AbortException;
import hudson.model.BuildListener;
import hudson.model.Computer;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.Environment;
......@@ -40,8 +41,10 @@ import hudson.remoting.Channel;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Maven.MavenInstallation;
import hudson.util.ArgumentListBuilder;
import org.apache.maven.BuildFailureException;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.lifecycle.LifecycleExecutionException;
......@@ -407,7 +410,7 @@ public class MavenBuild extends AbstractMavenBuild<MavenModule,MavenBuild> {
}
}
class ProxyImpl2 extends ProxyImpl implements MavenBuildProxy2 {
public class ProxyImpl2 extends ProxyImpl implements MavenBuildProxy2 {
private final SplittableBuildListener listener;
long startTime;
private final OutputStream log;
......@@ -522,8 +525,35 @@ public class MavenBuild extends AbstractMavenBuild<MavenModule,MavenBuild> {
EnvVars envVars = getEnvironment(listener); // buildEnvironments should be set up first
ProcessCache.MavenProcess process = mavenProcessCache.get(launcher.getChannel(), listener,
new MavenProcessFactory(getParent().getParent(),launcher,envVars,null));
MavenInstallation mvn = getProject().getParent().getMaven();
mvn = mvn.forEnvironment(envVars).forNode(Computer.currentComputer().getNode(), listener);
MavenInformation mavenInformation = getModuleRoot().act( new MavenVersionCallable( mvn.getHome() ));
String mavenVersion = mavenInformation.getVersion();
listener.getLogger().println("Found mavenVersion " + mavenVersion + " from file " + mavenInformation.getVersionResourcePath());
ProcessCache.MavenProcess process = null;
boolean maven3orLater = new ComparableVersion (mavenVersion).compareTo( new ComparableVersion ("3.0") ) >= 0;
if ( maven3orLater )
{
process =
MavenBuild.mavenProcessCache.get( launcher.getChannel(), listener,
new Maven3ProcessFactory( getParent().getParent(), launcher,
envVars, null ) );
}
else
{
process =
MavenBuild.mavenProcessCache.get( launcher.getChannel(), listener,
new MavenProcessFactory( getParent().getParent(), launcher,
envVars, null ) );
}
ArgumentListBuilder margs = new ArgumentListBuilder("-N","-B");
if(mms.usesPrivateRepository())
......@@ -538,25 +568,33 @@ public class MavenBuild extends AbstractMavenBuild<MavenModule,MavenBuild> {
systemProps.put("hudson.build.number",String.valueOf(getNumber()));
boolean normalExit = false;
try {
Result r = process.call(new Builder(
listener,new ProxyImpl(),
reporters.toArray(new MavenReporter[reporters.size()]), margs.toList(), systemProps));
normalExit = true;
return r;
} finally {
if(normalExit) process.recycle();
else process.discard();
// tear down in reverse order
boolean failed=false;
for( int i=buildEnvironments.size()-1; i>=0; i-- ) {
if (!buildEnvironments.get(i).tearDown(MavenBuild.this,listener)) {
failed=true;
}
if (maven3orLater)
{
// FIXME here for maven 3 builds
return Result.ABORTED;
}
else
{
try {
Result r = process.call(new Builder(
listener,new ProxyImpl(),
reporters.toArray(new MavenReporter[reporters.size()]), margs.toList(), systemProps));
normalExit = true;
return r;
} finally {
if(normalExit) process.recycle();
else process.discard();
// tear down in reverse order
boolean failed=false;
for( int i=buildEnvironments.size()-1; i>=0; i-- ) {
if (!buildEnvironments.get(i).tearDown(MavenBuild.this,listener)) {
failed=true;
}
}
// WARNING The return in the finally clause will trump any return before
if (failed) return Result.FAILURE;
}
// WARNING The return in the finally clause will trump any return before
if (failed) return Result.FAILURE;
}
}
......
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
......@@ -25,11 +26,9 @@ package hudson.maven;
import hudson.maven.agent.AbortException;
import hudson.maven.agent.Main;
import hudson.maven.agent.PluginManagerInterceptor;
import hudson.maven.agent.PluginManagerListener;
import hudson.maven.reporters.SurefireArchiver;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.Result;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
......@@ -40,6 +39,7 @@ import hudson.util.IOException2;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
......@@ -50,7 +50,6 @@ import org.apache.maven.BuildFailureException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.execution.ReactorManager;
import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.lifecycle.LifecycleExecutorInterceptor;
import org.apache.maven.lifecycle.LifecycleExecutorListener;
import org.apache.maven.monitor.event.EventDispatcher;
import org.apache.maven.plugin.Mojo;
......@@ -74,20 +73,8 @@ import org.codehaus.plexus.configuration.PlexusConfiguration;
* @author Kohsuke Kawaguchi
* @since 1.133
*/
public abstract class MavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Goals to be executed in this Maven execution.
*/
private final List<String> goals;
/**
* Hudson-defined system properties. These will be made available to Maven,
* and accessible as if they are specified as -Dkey=value
*/
private final Map<String,String> systemProps;
/**
* Where error messages and so on are sent.
*/
protected final BuildListener listener;
public abstract class MavenBuilder extends AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
/**
* Flag needs to be set at the constructor, so that this reflects
......@@ -102,9 +89,7 @@ public abstract class MavenBuilder implements DelegatingCallable<Result,IOExcept
protected transient /*final*/ List<Future<?>> futures;
protected MavenBuilder(BuildListener listener, List<String> goals, Map<String, String> systemProps) {
this.listener = listener;
this.goals = goals;
this.systemProps = systemProps;
super( listener, goals, systemProps );
}
/**
......@@ -142,16 +127,30 @@ public abstract class MavenBuilder implements DelegatingCallable<Result,IOExcept
*/
abstract void onReportGenerated(MavenProject project, MavenReportInfo report) throws IOException, InterruptedException, AbortException;
private Class<?> pluginManagerInterceptorClazz;
private Class<?> lifecycleInterceptorClazz;
/**
* This code is executed inside the maven jail process.
*/
public Result call() throws IOException {
// hold a ref on correct classloader for finally call as something is changing tccl
// and not restore it !
ClassLoader mavenJailProcessClassLoader = Thread.currentThread().getContextClassLoader();
try {
futures = new ArrayList<Future<?>>();
Adapter a = new Adapter(this);
callSetListenerWithReflectOnInterceptors( a, mavenJailProcessClassLoader );
/*
PluginManagerInterceptor.setListener(a);
LifecycleExecutorInterceptor.setListener(a);
*/
markAsSuccess = false;
// working around NPE when someone puts a null value into systemProps.
......@@ -202,46 +201,83 @@ public abstract class MavenBuilder implements DelegatingCallable<Result,IOExcept
listener.getLogger().println(Messages.MavenBuilder_Failed());
return Result.SUCCESS;
}
return Result.FAILURE;
} catch (NoSuchMethodException e) {
throw new IOException2(e);
} catch (IllegalAccessException e) {
throw new IOException2(e);
} catch (NoSuchRealmException e) {
} catch (RuntimeException e) {
throw new IOException2(e);
} catch (InvocationTargetException e) {
throw new IOException2(e);
} catch (ClassNotFoundException e) {
throw new IOException2(e);
}
catch ( NoSuchRealmException e ) {
throw new IOException2(e);
} finally {
PluginManagerInterceptor.setListener(null);
LifecycleExecutorInterceptor.setListener(null);
//PluginManagerInterceptor.setListener(null);
//LifecycleExecutorInterceptor.setListener(null);
callSetListenerWithReflectOnInterceptorsQuietly( null, mavenJailProcessClassLoader );
}
}
private String formatArgs(List<String> args) {
StringBuilder buf = new StringBuilder("Executing Maven: ");
for (String arg : args) {
final String argPassword = "-Dpassword=" ;
String filteredArg = arg ;
// check if current arg is password arg. Then replace password by *****
if (arg.startsWith(argPassword)) {
filteredArg=argPassword+"*********";
}
buf.append(' ').append(filteredArg);
private void callSetListenerWithReflectOnInterceptors( PluginManagerListener pluginManagerListener, ClassLoader cl )
throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException
{
if (pluginManagerInterceptorClazz == null)
{
pluginManagerInterceptorClazz = cl.loadClass( "hudson.maven.agent.PluginManagerInterceptor" );
}
return buf.toString();
}
Method setListenerMethod =
pluginManagerInterceptorClazz.getMethod( "setListener",
new Class[] { cl.loadClass( "hudson.maven.agent.PluginManagerListener" ) } );
setListenerMethod.invoke( null, new Object[] { pluginManagerListener } );
if (lifecycleInterceptorClazz == null)
{
lifecycleInterceptorClazz = cl.loadClass( "org.apache.maven.lifecycle.LifecycleExecutorInterceptor" );
}
setListenerMethod =
lifecycleInterceptorClazz.getMethod( "setListener",
new Class[] { cl.loadClass( "org.apache.maven.lifecycle.LifecycleExecutorListener" ) } );
private String format(NumberFormat n, long nanoTime) {
return n.format(nanoTime/1000000);
setListenerMethod.invoke( null, new Object[] { pluginManagerListener } );
}
private void callSetListenerWithReflectOnInterceptorsQuietly( PluginManagerListener pluginManagerListener, ClassLoader cl )
{
try
{
callSetListenerWithReflectOnInterceptors(pluginManagerListener, cl);
}
catch ( SecurityException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( IllegalArgumentException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( ClassNotFoundException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( NoSuchMethodException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( IllegalAccessException e )
{
throw new RuntimeException( e.getMessage(), e );
}
catch ( InvocationTargetException e )
{
throw new RuntimeException( e.getMessage(), e );
}
}
// since reporters might be from plugins, use the uberjar to resolve them.
public ClassLoader getClassLoader() {
return Hudson.getInstance().getPluginManager().uberClassLoader;
}
/**
* Receives {@link PluginManagerListener} and {@link LifecycleExecutorListener} events
......
......@@ -25,10 +25,11 @@ package hudson.maven;
import hudson.Extension;
import hudson.FilePath;
import hudson.maven.agent.AbortException;
import hudson.maven.agent.Main;
import hudson.maven.agent.PluginManagerInterceptor;
import hudson.maven.agent.Maven21Interceptor;
import hudson.model.Computer;
import hudson.model.Hudson;
import hudson.model.TaskListener;
import hudson.remoting.Channel;
import hudson.remoting.Which;
......@@ -38,8 +39,11 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Zip;
import org.codehaus.plexus.classworlds.ClassWorld;
import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
/**
* When a slave is connected, copy <tt>maven-agent.jar</tt> and <tt>maven-intercepter.jar</tt>
......@@ -52,8 +56,15 @@ public class MavenComputerListener extends ComputerListener {
public void preOnline(Computer c, Channel channel,FilePath root, TaskListener listener) throws IOException, InterruptedException {
PrintStream logger = listener.getLogger();
copyJar(logger, root, Main.class, "maven-agent");
copyJar(logger, root, PluginManagerInterceptor.class, "maven-interceptor");
copyJar(logger, root, Maven3Main.class, "maven3-agent");
copyJar(logger, root, Maven3Launcher.class, "maven3-interceptor");
copyJar(logger, root, AbortException.class, "maven-interceptor");
copyJar(logger, root, Maven21Interceptor.class, "maven2.1-interceptor");
copyJar(logger, root, ClassWorld.class, "plexus-classworld");
// copy classworlds 1.1 for maven2 builds
root.child( "classworlds.jar" ).copyFrom(getClass().getClassLoader().getResource("classworlds.jar"));
logger.println("Copied classworlds.jar");
}
/**
......
/**
*
*/
package hudson.maven;
/*
* 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 hudson.model.TaskListener;
import java.io.File;
import java.util.Properties;
import org.sonatype.aether.transfer.TransferListener;
/**
* @author Olivier Lamy
*/
public class MavenEmbedderRequest
{
private TaskListener listener;
private File mavenHome;
private String profiles;
private Properties systemProperties;
private String privateRepository;
private File alternateSettings;
private TransferListener transferListener;
/**
* @param listener
* This is where the log messages from Maven will be recorded.
* @param mavenHome
* Directory of the Maven installation. We read {@code conf/settings.xml}
* from here. Can be null.
* @param profiles
* Profiles to activate/deactivate. Can be null.
* @param systemProperties
* The system properties that the embedded Maven sees. See {@link MavenEmbedder#setSystemProperties(Properties)}.
* @param privateRepository
* Optional private repository to use as the local repository.
* @param alternateSettings
* Optional alternate settings.xml file.
*/
public MavenEmbedderRequest( TaskListener listener, File mavenHome, String profiles, Properties systemProperties,
String privateRepository, File alternateSettings )
{
this.listener = listener;
this.mavenHome = mavenHome;
this.profiles = profiles;
this.systemProperties = systemProperties;
this.privateRepository = privateRepository;
this.alternateSettings = alternateSettings;
}
public TaskListener getListener()
{
return listener;
}
public MavenEmbedderRequest setListener( TaskListener listener )
{
this.listener = listener;
return this;
}
public File getMavenHome()
{
return mavenHome;
}
public MavenEmbedderRequest setMavenHome( File mavenHome )
{
this.mavenHome = mavenHome;
return this;
}
public String getProfiles()
{
return profiles;
}
public MavenEmbedderRequest setProfiles( String profiles )
{
this.profiles = profiles;
return this;
}
public Properties getSystemProperties()
{
return systemProperties;
}
public MavenEmbedderRequest setSystemProperties( Properties systemProperties )
{
this.systemProperties = systemProperties;
return this;
}
public String getPrivateRepository()
{
return privateRepository;
}
public MavenEmbedderRequest setPrivateRepository( String privateRepository )
{
this.privateRepository = privateRepository;
return this;
}
public File getAlternateSettings()
{
return alternateSettings;
}
public MavenEmbedderRequest setAlternateSettings( File alternateSettings )
{
this.alternateSettings = alternateSettings;
return this;
}
public TransferListener getTransferListener()
{
return transferListener;
}
public MavenEmbedderRequest setTransferListener( TransferListener transferListener )
{
this.transferListener = transferListener;
return this;
}
}
......@@ -23,34 +23,70 @@
*/
package hudson.maven;
import hudson.*;
import hudson.model.*;
import static hudson.Util.fixEmpty;
import static hudson.model.ItemGroupMixIn.loadChildren;
import hudson.CopyOnWrite;
import hudson.Extension;
import hudson.FilePath;
import hudson.Indenter;
import hudson.Util;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildableItemWithBuildWrappers;
import hudson.model.DependencyGraph;
import hudson.model.Descriptor;
import hudson.model.Descriptor.FormException;
import hudson.model.Executor;
import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.ItemGroup;
import hudson.model.Job;
import hudson.model.Queue;
import hudson.model.Queue.Task;
import hudson.model.ResourceActivity;
import hudson.model.SCMedItem;
import hudson.model.Saveable;
import hudson.model.TopLevelItem;
import hudson.search.CollectionSearchIndex;
import hudson.search.SearchIndexBuilder;
import hudson.tasks.*;
import hudson.tasks.BuildStep;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrappers;
import hudson.tasks.Fingerprinter;
import hudson.tasks.JavadocArchiver;
import hudson.tasks.Mailer;
import hudson.tasks.Maven;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.Publisher;
import hudson.tasks.junit.JUnitResultArchiver;
import hudson.util.CopyOnWriteMap;
import hudson.util.DescribableList;
import hudson.util.FormValidation;
import hudson.util.Function1;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import javax.servlet.ServletException;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.util.*;
import static hudson.Util.fixEmpty;
import static hudson.model.ItemGroupMixIn.loadChildren;
/**
* Group of {@link MavenModule}s.
*
......@@ -144,6 +180,8 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
* If true, do not archive artifacts to the master.
*/
private boolean archivingDisabled = false;
private String mavenVersionUsed;
/**
* Reporters configured at {@link MavenModuleSet} level. Applies to all {@link MavenModule} builds.
......@@ -598,6 +636,15 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
this.alternateSettings = alternateSettings;
save();
}
public String getMavenVersionUsed() {
return mavenVersionUsed;
}
public void setMavenVersionUsed( String mavenVersionUsed ) throws IOException {
this.mavenVersionUsed = mavenVersionUsed;
save();
}
/**
* If the list of configured goals contain the "-P" option,
......@@ -837,4 +884,6 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
JUnitResultArchiver.class // done by SurefireArchiver
));
}
}
......@@ -32,7 +32,6 @@ import hudson.slaves.Channels;
import static hudson.Util.fixNull;
import hudson.maven.agent.Main;
import hudson.maven.agent.Maven21Interceptor;
import hudson.maven.agent.PluginManagerInterceptor;
import hudson.maven.ProcessCache.NewProcess;
import hudson.model.BuildListener;
import hudson.model.Computer;
......@@ -169,7 +168,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
this.serverSocket = new ServerSocket();
serverSocket.bind(null); // new InetSocketAddress(InetAddress.getLocalHost(),0));
// prevent a hang at the accept method in case the forked process didn't start successfully
serverSocket.setSoTimeout(30*1000);
serverSocket.setSoTimeout(socketTimeOut);
}
public Connection accept() throws IOException {
......@@ -200,6 +199,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
if(debug)
listener.getLogger().println("Using env variables: "+ envVars);
try {
//launcher.getChannel().export( type, instance )
final Acceptor acceptor = launcher.getChannel().call(new SocketHandler());
Charset charset;
try {
......@@ -282,10 +282,14 @@ final class MavenProcessFactory implements ProcessCache.Factory {
args.addTokenized(getMavenOpts());
args.add("-cp");
args.add(
(isMaster? Which.jarFile(Main.class).getAbsolutePath():slaveRoot.child("maven-agent.jar").getRemote())+
(launcher.isUnix()?":":";")+classWorldsJar);
args.add( "-cp" );
String classPath =
( isMaster ? Which.jarFile( Main.class ).getAbsolutePath()
: slaveRoot.child( "maven-agent.jar" ).getRemote() )
+ ( launcher.isUnix() ? ":" : ";" )
+ ( isMaster ? classWorldsJar : slaveRoot.child( "classworlds.jar" ).getRemote() );
args.add( classPath );
//+classWorldsJar);
args.add(Main.class.getName());
// M2_HOME
......@@ -301,7 +305,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
// interceptor.jar
args.add(isMaster?
Which.jarFile(PluginManagerInterceptor.class).getAbsolutePath():
Which.jarFile(hudson.maven.agent.AbortException.class).getAbsolutePath():
slaveRoot.child("maven-interceptor.jar").getRemote());
// TCP/IP port to establish the remoting infrastructure
......@@ -313,7 +317,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
Which.jarFile(Maven21Interceptor.class).getAbsolutePath():
slaveRoot.child("maven2.1-interceptor.jar").getRemote());
}
return args;
}
......@@ -440,6 +444,9 @@ final class MavenProcessFactory implements ProcessCache.Factory {
if(port!=null)
debugPort = Integer.parseInt(port);
}
public static int socketTimeOut = Integer.parseInt( System.getProperty( "hudson.maven.socketTimeOut", Integer.toString( 30*1000 ) ) );
private static final Logger LOGGER = Logger.getLogger(MavenProcessFactory.class.getName());
}
......@@ -25,32 +25,33 @@ package hudson.maven;
import hudson.AbortException;
import hudson.Util;
import hudson.model.BuildListener;
import hudson.model.TaskListener;
import hudson.model.AbstractProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Hudson;
import hudson.model.TaskListener;
import hudson.tasks.Maven.MavenInstallation;
import hudson.tasks.Maven.ProjectWithMaven;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.embedder.MavenEmbedderLogger;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.commons.io.IOUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingException;
/**
* @author Kohsuke Kawaguchi
*/
......@@ -107,12 +108,12 @@ public class MavenUtil {
systemProperties = ((MavenModuleSet) project).getMavenProperties();
}
return createEmbedder(listener,
return createEmbedder(new MavenEmbedderRequest(listener,
m!=null?m.getHomeDir():null,
profiles,
systemProperties,
privateRepository,
settingsLoc);
settingsLoc ));
}
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles) throws MavenEmbedderException, IOException {
......@@ -123,45 +124,23 @@ public class MavenUtil {
return createEmbedder(listener,mavenHome,profiles,systemProperties,null);
}
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties,
String privateRepository) throws MavenEmbedderException, IOException {
return createEmbedder(listener,mavenHome,profiles,systemProperties,privateRepository,null);
public static MavenEmbedder createEmbedder( TaskListener listener, File mavenHome, String profiles,
Properties systemProperties, String privateRepository )
throws MavenEmbedderException, IOException
{
return createEmbedder( new MavenEmbedderRequest( listener, mavenHome, profiles, systemProperties,
privateRepository, null ) );
}
/**
* Creates a fresh {@link MavenEmbedder} instance.
*
* @param listener
* This is where the log messages from Maven will be recorded.
* @param mavenHome
* Directory of the Maven installation. We read {@code conf/settings.xml}
* from here. Can be null.
* @param profiles
* Profiles to activate/deactivate. Can be null.
* @param systemProperties
* The system properties that the embedded Maven sees. See {@link MavenEmbedder#setSystemProperties(Properties)}.
* @param privateRepository
* Optional private repository to use as the local repository.
* @param alternateSettings
* Optional alternate settings.xml file.
*/
public static MavenEmbedder createEmbedder(TaskListener listener, File mavenHome, String profiles, Properties systemProperties,
String privateRepository, File alternateSettings) throws MavenEmbedderException, IOException {
MavenEmbedder maven = new MavenEmbedder(mavenHome);
ClassLoader cl = MavenUtil.class.getClassLoader();
maven.setClassLoader(new MaskingClassLoader(cl));
EmbedderLoggerImpl logger = new EmbedderLoggerImpl(listener);
if(debugMavenEmbedder) logger.setThreshold(MavenEmbedderLogger.LEVEL_DEBUG);
maven.setLogger(logger);
{
Enumeration<URL> e = cl.getResources("META-INF/plexus/components.xml");
while (e.hasMoreElements()) {
URL url = e.nextElement();
LOGGER.fine("components.xml from "+url);
}
}
public static MavenEmbedder createEmbedder(MavenEmbedderRequest mavenEmbedderRequest) throws MavenEmbedderException, IOException {
MavenRequest mavenRequest = new MavenRequest();
// make sure ~/.m2 exists to avoid http://www.nabble.com/BUG-Report-tf3401736.html
File m2Home = new File(MavenEmbedder.userHome, ".m2");
m2Home.mkdirs();
......@@ -169,22 +148,57 @@ public class MavenUtil {
throw new AbortException("Failed to create "+m2Home+
"\nSee https://hudson.dev.java.net/cannot-create-.m2.html");
if (privateRepository!=null)
maven.setLocalRepositoryDirectory(new File(privateRepository));
if (mavenEmbedderRequest.getPrivateRepository()!=null)
mavenRequest.setLocalRepositoryPath( mavenEmbedderRequest.getPrivateRepository() );
maven.setProfiles(profiles);
if (mavenEmbedderRequest.getProfiles() != null) {
mavenRequest.setProfiles(Arrays.asList( StringUtils.split( mavenEmbedderRequest.getProfiles(), "," ) ));
}
if (alternateSettings!=null)
maven.setAlternateSettings(alternateSettings);
if ( mavenEmbedderRequest.getAlternateSettings() != null ) {
mavenRequest.setUserSettingsFile( mavenEmbedderRequest.getAlternateSettings().getAbsolutePath() );
} else {
mavenRequest.setUserSettingsFile( new File( m2Home, "settings.xml" ).getAbsolutePath() );
}
maven.setSystemProperties(systemProperties);
maven.start();
// FIXME configure those !!
mavenRequest.setGlobalSettingsFile( new File( mavenEmbedderRequest.getMavenHome(), "conf/settings.xml" ).getAbsolutePath() );
// TODO olamy check this sould be userProperties
mavenRequest.setSystemProperties(mavenEmbedderRequest.getSystemProperties());
if (mavenEmbedderRequest.getTransferListener() != null) {
if (debugMavenEmbedder) {
mavenEmbedderRequest.getListener().getLogger()
.println( "use transfertListener " + mavenEmbedderRequest.getTransferListener().getClass().getName() );
}
mavenRequest.setTransferListener( mavenEmbedderRequest.getTransferListener() );
}
EmbedderLoggerImpl logger =
new EmbedderLoggerImpl( mavenEmbedderRequest.getListener(), debugMavenEmbedder ? org.codehaus.plexus.logging.Logger.LEVEL_DEBUG
: org.codehaus.plexus.logging.Logger.LEVEL_INFO );
mavenRequest.setMavenLoggerManager( logger );
ClassLoader cl = MavenUtil.class.getClassLoader();
// TODO check this MaskingClassLoader with maven 3 artifacts
MavenEmbedder maven = new MavenEmbedder( new MaskingClassLoader(cl), mavenRequest );
{
Enumeration<URL> e = cl.getResources("META-INF/plexus/components.xml");
while (e.hasMoreElements()) {
URL url = e.nextElement();
LOGGER.fine("components.xml from "+url);
}
}
return maven;
}
/**
* @deprecated MavenEmbedder has now a method to read all projects
* Recursively resolves module POMs that are referenced from
* the given {@link MavenProject} and parses them into
* {@link MavenProject}s.
......@@ -198,39 +212,43 @@ public class MavenUtil {
*
* @throws AbortException
* errors will be reported to the listener and the exception thrown.
* @throws MavenEmbedderException
*/
public static void resolveModules(MavenEmbedder embedder, MavenProject project,
String rel, Map<MavenProject,String> relativePathInfo,
BuildListener listener, boolean nonRecursive) throws ProjectBuildingException,
AbortException {
public static void resolveModules( MavenEmbedder embedder, MavenProject project, String rel,
Map<MavenProject, String> relativePathInfo, BuildListener listener,
boolean nonRecursive )
throws ProjectBuildingException, AbortException, MavenEmbedderException
{
File basedir = project.getFile().getParentFile();
relativePathInfo.put(project,rel);
if (!nonRecursive) {
List<MavenProject> modules = new ArrayList<MavenProject>();
for (String modulePath : (List<String>) project.getModules()) {
if (Util.fixEmptyAndTrim(modulePath)!=null) {
File moduleFile = new File(basedir, modulePath);
if (moduleFile.exists() && moduleFile.isDirectory()) {
moduleFile = new File(basedir, modulePath + "/pom.xml");
}
if(!moduleFile.exists())
throw new AbortException(moduleFile+" is referenced from "+project.getFile()+" but it doesn't exist");
String relativePath = rel;
if(relativePath.length()>0) relativePath+='/';
relativePath+=modulePath;
MavenProject child = embedder.readProject(moduleFile);
resolveModules(embedder,child,relativePath,relativePathInfo,listener,nonRecursive);
modules.add(child);
}
}
project.setCollectedProjects(modules);
}
relativePathInfo.put( project, rel );
List<MavenProject> modules = new ArrayList<MavenProject>();
if ( !nonRecursive ) {
for ( String modulePath : project.getModules()) {
if ( Util.fixEmptyAndTrim( modulePath ) != null ) {
File moduleFile = new File( basedir, modulePath );
if ( moduleFile.exists() && moduleFile.isDirectory() ) {
moduleFile = new File( basedir, modulePath + "/pom.xml" );
}
if ( !moduleFile.exists() )
throw new AbortException( moduleFile + " is referenced from " + project.getFile()
+ " but it doesn't exist" );
String relativePath = rel;
if ( relativePath.length() > 0 )
relativePath += '/';
relativePath += modulePath;
MavenProject child = embedder.readProject( moduleFile );
resolveModules( embedder, child, relativePath, relativePathInfo, listener, nonRecursive );
modules.add( child );
}
}
}
project.setCollectedProjects( modules );
}
/**
......@@ -305,11 +323,20 @@ public class MavenUtil {
};
}
}
public static boolean maven3orLater(String mavenVersion) {
// null or empty so false !
if (StringUtils.isBlank( mavenVersion )) {
return false;
}
return new ComparableVersion (mavenVersion).compareTo( new ComparableVersion ("3.0") ) >= 0;
}
/**
* If set to true, maximize the logging level of Maven embedder.
*/
public static boolean debugMavenEmbedder = false;
public static boolean debugMavenEmbedder = Boolean.getBoolean( "debugMavenEmbedder" );
private static final Logger LOGGER = Logger.getLogger(MavenUtil.class.getName());
}
package hudson.maven;
/*
* The MIT License
*
* Copyright (c) 2004-2010, Sun Microsystems, Inc. Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import hudson.remoting.Callable;
import java.io.File;
import java.io.IOException;
import org.kohsuke.stapler.framework.io.IOException2;
/**
*
* @author Olivier Lamy
* @since 3.0
*
*/
public class MavenVersionCallable
implements Callable<MavenInformation, IOException>
{
private final String mavenHome;
public MavenVersionCallable( String mavenHome )
{
this.mavenHome = mavenHome;
}
public MavenInformation call()
throws IOException
{
try
{
return MavenEmbedderUtils.getMavenVersion( new File(mavenHome) );
}
catch ( MavenEmbedderException e )
{
throw new IOException2( e );
}
}
}
......@@ -25,6 +25,9 @@ package hudson.maven;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.classworlds.ClassRealm;
import org.codehaus.classworlds.ClassRealmAdapter;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup;
......@@ -39,6 +42,7 @@ import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
import hudson.util.InvocationInterceptor;
import hudson.util.ReflectionUtils;
/**
* Information about Mojo to be executed. This object provides
......@@ -126,13 +130,26 @@ public class MojoInfo {
public <T> T getConfigurationValue(String configName, Class<T> type) throws ComponentConfigurationException {
PlexusConfiguration child = configuration.getChild(configName);
if(child==null) return null; // no such config
ClassLoader cl = null;
PluginDescriptor pd = mojoExecution.getMojoDescriptor().getPluginDescriptor();
// for maven2 builds ClassRealm doesn't extends ClassLoader !
// so check stuff with reflection
Method method = ReflectionUtils.getPublicMethodNamed( pd.getClass(), "getClassRealm" );
if ( ReflectionUtils.invokeMethod( method, pd ) instanceof ClassRealm)
{
ClassRealm cr = (ClassRealm) ReflectionUtils.invokeMethod( method, pd );
cl = cr.getClassLoader();
} else {
cl = mojoExecution.getMojoDescriptor().getPluginDescriptor().getClassRealm();
}
ConfigurationConverter converter = converterLookup.lookupConverterForType(type);
return type.cast(converter.fromConfiguration(converterLookup,child,type,
// the implementation seems to expect the type of the bean for which the configuration is done
// in this parameter, but we have no such type. So passing in a dummy
Object.class,
mojoExecution.getMojoDescriptor().getPluginDescriptor().getClassRealm().getClassLoader(),
cl,
expressionEvaluator));
}
......
......@@ -23,6 +23,7 @@
*/
package hudson.maven;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.model.CiManagement;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Extension;
......@@ -94,6 +95,16 @@ final class PomInfo implements Serializable {
* Parent module.
*/
public final PomInfo parent;
/**
* maven groupId
*/
private final String groupId;
/**
* maven artifactId
*/
private final String artifactId;
public final Notifier mailNotifier;
......@@ -140,6 +151,9 @@ final class PomInfo implements Serializable {
this.mailNotifier = mailNotifier;
} else
this.mailNotifier = null;
this.groupId = project.getGroupId();
this.artifactId = project.getArtifactId();
}
/**
......@@ -189,4 +203,29 @@ final class PomInfo implements Serializable {
}
private static final long serialVersionUID = 1L;
@Override
public int hashCode()
{
int hash = 23 + this.groupId == null ? 1 : this.groupId.hashCode();
hash += this.artifactId == null ? 1 : this.artifactId.hashCode();
return hash;
}
@Override
public boolean equals( Object obj )
{
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!(obj instanceof PomInfo)) {
return false;
}
PomInfo pomInfo = (PomInfo) obj;
return StringUtils.equals( pomInfo.groupId, this.groupId )
&& StringUtils.equals( pomInfo.artifactId, this.artifactId );
}
}
......@@ -23,8 +23,8 @@
*/
package hudson.maven;
import hudson.Launcher;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.maven.reporters.MavenAbstractArtifactRecord;
import hudson.model.AbstractBuild;
......@@ -32,22 +32,32 @@ import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.tasks.BuildStepMonitor;
import hudson.util.FormValidation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.Authentication;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.repository.Proxy;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import java.io.IOException;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
/**
* {@link Publisher} for {@link MavenModuleSetBuild} to deploy artifacts
......@@ -96,8 +106,8 @@ public class RedeployPublisher extends Recorder {
return true;
}
MavenAbstractArtifactRecord mar = getAction(build);
if(mar==null) {
List<MavenAbstractArtifactRecord> mars = getActions( build, listener );
if(mars==null || mars.isEmpty()) {
listener.getLogger().println("No artifacts are recorded. Is this a Maven project?");
build.setResult(Result.FAILURE);
return true;
......@@ -108,16 +118,16 @@ public class RedeployPublisher extends Recorder {
MavenEmbedder embedder = MavenUtil.createEmbedder(listener,build);
ArtifactRepositoryLayout layout =
(ArtifactRepositoryLayout) embedder.getContainer().lookup( ArtifactRepositoryLayout.ROLE,"default");
(ArtifactRepositoryLayout) embedder.lookup( ArtifactRepositoryLayout.ROLE,"default");
ArtifactRepositoryFactory factory =
(ArtifactRepositoryFactory) embedder.lookup(ArtifactRepositoryFactory.ROLE);
ArtifactRepository repository = factory.createDeploymentArtifactRepository(
final ArtifactRepository repository = factory.createDeploymentArtifactRepository(
id, url, layout, uniqueVersion);
WrappedArtifactRepository repo = new WrappedArtifactRepository(repository,uniqueVersion);
for (MavenAbstractArtifactRecord mar : mars)
mar.deploy(embedder,repo,listener);
mar.deploy(embedder,repository,listener);
embedder.stop();
return true;
} catch (MavenEmbedderException e) {
e.printStackTrace(listener.error(e.getMessage()));
......@@ -131,6 +141,8 @@ public class RedeployPublisher extends Recorder {
return true;
}
/**
* Obtains the {@link MavenAbstractArtifactRecord} that we'll work on.
* <p>
......@@ -139,6 +151,23 @@ public class RedeployPublisher extends Recorder {
protected MavenAbstractArtifactRecord getAction(AbstractBuild<?, ?> build) {
return build.getAction(MavenAbstractArtifactRecord.class);
}
protected List<MavenAbstractArtifactRecord> getActions(AbstractBuild<?, ?> build, BuildListener listener) {
List<MavenAbstractArtifactRecord> actions = new ArrayList<MavenAbstractArtifactRecord>();
if (!(build instanceof MavenModuleSetBuild)) {
return actions;
}
for (Entry<MavenModule, MavenBuild> e : ((MavenModuleSetBuild)build).getModuleLastBuilds().entrySet()) {
MavenAbstractArtifactRecord a = e.getValue().getAction( MavenAbstractArtifactRecord.class );
if (a == null) {
listener.getLogger().println("No artifacts are recorded for module" + e.getKey().getName() + ". Is this a Maven project?");
} else {
actions.add( a );
}
}
return actions;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.NONE;
......@@ -190,4 +219,126 @@ public class RedeployPublisher extends Recorder {
return FormValidation.ok();
}
}
//---------------------------------------------
public static class WrappedArtifactRepository implements ArtifactRepository {
private ArtifactRepository artifactRepository;
private boolean uniqueVersion;
public WrappedArtifactRepository (ArtifactRepository artifactRepository, boolean uniqueVersion)
{
this.artifactRepository = artifactRepository;
this.uniqueVersion = uniqueVersion;
}
public String pathOf( Artifact artifact )
{
return artifactRepository.pathOf( artifact );
}
public String pathOfRemoteRepositoryMetadata( ArtifactMetadata artifactMetadata )
{
return artifactRepository.pathOfRemoteRepositoryMetadata( artifactMetadata );
}
public String pathOfLocalRepositoryMetadata( ArtifactMetadata metadata, ArtifactRepository repository )
{
return artifactRepository.pathOfLocalRepositoryMetadata( metadata, repository );
}
public String getUrl()
{
return artifactRepository.getUrl();
}
public void setUrl( String url )
{
artifactRepository.setUrl( url );
}
public String getBasedir()
{
return artifactRepository.getBasedir();
}
public String getProtocol()
{
return artifactRepository.getProtocol();
}
public String getId()
{
return artifactRepository.getId();
}
public void setId( String id )
{
artifactRepository.setId( id );
}
public ArtifactRepositoryPolicy getSnapshots()
{
return artifactRepository.getSnapshots();
}
public void setSnapshotUpdatePolicy( ArtifactRepositoryPolicy policy )
{
artifactRepository.setSnapshotUpdatePolicy( policy );
}
public ArtifactRepositoryPolicy getReleases()
{
return artifactRepository.getReleases();
}
public void setReleaseUpdatePolicy( ArtifactRepositoryPolicy policy )
{
artifactRepository.setReleaseUpdatePolicy( policy );
}
public ArtifactRepositoryLayout getLayout()
{
return artifactRepository.getLayout();
}
public void setLayout( ArtifactRepositoryLayout layout )
{
artifactRepository.setLayout( layout );
}
public String getKey()
{
return artifactRepository.getKey();
}
public boolean isUniqueVersion()
{
return this.uniqueVersion;
}
public void setUniqueVersion(boolean uniqueVersion) {
this.uniqueVersion = uniqueVersion;
}
public boolean isBlacklisted()
{
return artifactRepository.isBlacklisted();
}
public void setBlacklisted( boolean blackListed )
{
artifactRepository.setBlacklisted( blackListed );
}
public Artifact find( Artifact artifact )
{
return artifactRepository.find( artifact );
}
public List<String> findVersions( Artifact artifact )
{
return artifactRepository.findVersions( artifact );
}
public boolean isProjectAware()
{
return artifactRepository.isProjectAware();
}
public void setAuthentication( Authentication authentication )
{
artifactRepository.setAuthentication( authentication );
}
public Authentication getAuthentication()
{
return artifactRepository.getAuthentication();
}
public void setProxy( Proxy proxy )
{
artifactRepository.setProxy( proxy );
}
public Proxy getProxy()
{
return artifactRepository.getProxy();
}
}
}
......@@ -25,40 +25,43 @@ package hudson.maven.reporters;
import hudson.console.AnnotatedLargeText;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenUtil;
import hudson.maven.RedeployPublisher.WrappedArtifactRepository;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BallColor;
import hudson.model.BuildBadgeAction;
import hudson.model.Result;
import hudson.model.TaskAction;
import hudson.model.TaskListener;
import hudson.model.TaskThread;
import hudson.model.BuildBadgeAction;
import hudson.model.TaskThread.ListenerAndText;
import hudson.security.Permission;
import hudson.security.ACL;
import hudson.security.Permission;
import hudson.util.Iterators;
import hudson.widgets.HistoryWidget;
import hudson.widgets.HistoryWidget.Adapter;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletException;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
import org.apache.maven.embedder.MavenEmbedderException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.kohsuke.stapler.HttpRedirect;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.HttpRedirect;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* UI to redeploy artifacts after the fact.
......@@ -204,16 +207,15 @@ public abstract class MavenAbstractArtifactRecord<T extends AbstractBuild<?,?>>
try {
MavenEmbedder embedder = MavenUtil.createEmbedder(listener,getBuild());
ArtifactRepositoryLayout layout =
(ArtifactRepositoryLayout) embedder.getContainer().lookup( ArtifactRepositoryLayout.ROLE,"default");
(ArtifactRepositoryLayout) embedder.lookup( ArtifactRepositoryLayout.class,"default");
ArtifactRepositoryFactory factory =
(ArtifactRepositoryFactory) embedder.lookup(ArtifactRepositoryFactory.ROLE);
ArtifactRepository repository = factory.createDeploymentArtifactRepository(
id, repositoryUrl, layout, uniqueVersion);
WrappedArtifactRepository repo = new WrappedArtifactRepository(repository, uniqueVersion);
deploy(embedder,repo,listener);
deploy(embedder,repository,listener);
embedder.stop();
record.result = Result.SUCCESS;
} finally {
if(record.result==null)
......
......@@ -26,20 +26,21 @@ package hudson.maven.reporters;
import hudson.maven.MavenAggregatedReport;
import hudson.maven.MavenBuild;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenModule;
import hudson.maven.MavenModuleSet;
import hudson.maven.MavenModuleSetBuild;
import hudson.model.Action;
import hudson.model.TaskListener;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.embedder.MavenEmbedderException;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
/**
* Redeploy action for the entire {@link MavenModuleSetBuild}.
*
......
......@@ -36,11 +36,14 @@ import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import com.google.common.collect.Maps;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import java.util.logging.Logger;
/**
......@@ -145,14 +148,14 @@ public final class MavenArtifact implements Serializable {
// in the repository during deployment. So simulate that behavior if that's necessary.
final String canonicalExtension = canonicalName.substring(canonicalName.lastIndexOf('.')+1);
ArtifactHandler ah = handlerManager.getArtifactHandler(type);
// Fix for HUDSON-3814 - changed from comparing against canonical extension to canonicalName.endsWith.
if(!canonicalName.endsWith(ah.getExtension())) {
handlerManager.addHandlers(Collections.singletonMap(type,
new DefaultArtifactHandler(type) {
Map<String,ArtifactHandler> handlers = Maps.newHashMap();
handlers.put( type, new DefaultArtifactHandler(type) {
public String getExtension() {
return canonicalExtension;
}
}));
} } );
// Fix for HUDSON-3814 - changed from comparing against canonical extension to canonicalName.endsWith.
if(!canonicalName.endsWith(ah.getExtension())) {
handlerManager.addHandlers(handlers);
}
Artifact a = factory.createArtifactWithClassifier(groupId, artifactId, version, type, classifier);
......
......@@ -27,10 +27,19 @@ import hudson.maven.AggregatableAction;
import hudson.maven.MavenAggregatedReport;
import hudson.maven.MavenBuild;
import hudson.maven.MavenEmbedder;
import hudson.maven.MavenEmbedderException;
import hudson.maven.MavenModule;
import hudson.maven.MavenModuleSetBuild;
import hudson.maven.MavenUtil;
import hudson.maven.RedeployPublisher.WrappedArtifactRepository;
import hudson.model.Action;
import hudson.model.TaskListener;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.deployer.ArtifactDeployer;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
......@@ -39,15 +48,9 @@ import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.installer.ArtifactInstallationException;
import org.apache.maven.artifact.installer.ArtifactInstaller;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.project.artifact.ProjectArtifactMetadata;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
import java.util.Map;
/**
* {@link Action} that remembers {@link MavenArtifact artifact}s that are built.
*
......@@ -105,33 +108,43 @@ public class MavenArtifactRecord extends MavenAbstractArtifactRecord<MavenBuild>
@Override
public void deploy(MavenEmbedder embedder, ArtifactRepository deploymentRepository, TaskListener listener) throws MavenEmbedderException, IOException, ComponentLookupException, ArtifactDeploymentException {
ArtifactHandlerManager handlerManager = (ArtifactHandlerManager) embedder.lookup(ArtifactHandlerManager.ROLE);
ArtifactDeployer deployer = (ArtifactDeployer) embedder.lookup(ArtifactDeployer.ROLE);
ArtifactFactory factory = (ArtifactFactory) embedder.lookup(ArtifactFactory.ROLE);
ArtifactHandlerManager handlerManager = embedder.lookup(ArtifactHandlerManager.class);
ArtifactFactory factory = embedder.lookup(ArtifactFactory.class);
PrintStream logger = listener.getLogger();
boolean maven3orLater = MavenUtil.maven3orLater( parent.getModuleSetBuild().getProject().getMavenVersionUsed());
if (!deploymentRepository.isUniqueVersion() && maven3orLater) {
logger.println("uniqueVersion == false is not anymore supported in maven 3");
((WrappedArtifactRepository) deploymentRepository).setUniqueVersion( true );
}
Artifact main = mainArtifact.toArtifact(handlerManager,factory,parent);
if(!isPOM())
main.addMetadata(new ProjectArtifactMetadata(main,pomArtifact.getFile(parent)));
// deploy the main artifact. This also deploys the POM
logger.println(Messages.MavenArtifact_DeployingMainArtifact(main.getFile().getName()));
deployer.deploy(main.getFile(),main,deploymentRepository,embedder.getLocalRepository());
deployMavenArtifact( main, deploymentRepository, embedder );
for (MavenArtifact aa : attachedArtifacts) {
Artifact a = aa.toArtifact(handlerManager,factory, parent);
logger.println(Messages.MavenArtifact_DeployingAttachedArtifact(a.getFile().getName()));
deployer.deploy(a.getFile(),a,deploymentRepository,embedder.getLocalRepository());
deployMavenArtifact( a, deploymentRepository, embedder );
}
}
protected void deployMavenArtifact(Artifact artifact, ArtifactRepository deploymentRepository, MavenEmbedder embedder)
throws ArtifactDeploymentException, ComponentLookupException {
ArtifactDeployer deployer = embedder.lookup(ArtifactDeployer.class,"maven2");
deployer.deploy(artifact.getFile(),artifact,deploymentRepository,embedder.getLocalRepository());
}
/**
* Installs the artifact to the local Maven repository.
*/
public void install(MavenEmbedder embedder) throws MavenEmbedderException, IOException, ComponentLookupException, ArtifactInstallationException {
ArtifactHandlerManager handlerManager = (ArtifactHandlerManager) embedder.lookup(ArtifactHandlerManager.ROLE);
ArtifactInstaller installer = (ArtifactInstaller) embedder.lookup(ArtifactInstaller.class.getName());
ArtifactFactory factory = (ArtifactFactory) embedder.lookup(ArtifactFactory.class.getName());
ArtifactHandlerManager handlerManager = embedder.lookup(ArtifactHandlerManager.class);
ArtifactInstaller installer = embedder.lookup(ArtifactInstaller.class);
ArtifactFactory factory = embedder.lookup(ArtifactFactory.class);
Artifact main = mainArtifact.toArtifact(handlerManager,factory,parent);
if(!isPOM())
......
......@@ -25,6 +25,7 @@ package hudson.maven.reporters;
import hudson.Util;
import hudson.Extension;
import hudson.maven.Maven3Builder;
import hudson.maven.MavenBuild;
import hudson.maven.MavenBuildProxy;
import hudson.maven.MavenBuildProxy.BuildCallable;
......@@ -126,6 +127,10 @@ public class SurefireArchiver extends MavenReporter {
if(failCount>0 && error instanceof MojoFailureException) {
MavenBuilder.markAsSuccess = true;
}
// TODO currenlty error is empty : will be here with maven 3.0.2+
if(failCount>0) {
Maven3Builder.markAsSuccess = true;
}
}
return true;
......
......@@ -26,7 +26,7 @@ Build=Byg
Maven\ Version=Maven version
Use\ private\ Maven\ repository=Benyt et privat Mavenarkiv
Incremental\ build\ -\ only\ build\ changed\ modules=Inkrementel byg - byg kun moduler med \u00e6ndringer
Maven\ Version.error.1=Hudson har brug for at vide hvor din Maven2 er installeret.
Maven\ Version.error.1=Hudson har brug for at vide hvor din Maven2/3 er installeret.
Goals\ and\ options=M\u00e5l og tilvalg
Build\ modules\ in\ parallel=Byg moduler i parallel
Build\ Settings=Byggeindstillinger
......
......@@ -31,5 +31,5 @@ Use\ private\ Maven\ repository=Verwende privates Maven-Repository
Alternate\ settings\ file=Alternative Settings-Datei
Build\ whenever\ a\ SNAPSHOT\ dependency\ is\ built=Baue dieses Projekt, wenn eine SNAPSHOT-Abhängigkeit gebaut wurde
Incremental\ build\ -\ only\ build\ changed\ modules=Inkrementelles Bauen - baut nur geänderte Module
Maven\ Version.error.1=Hudson muss Ihr Maven2-Installationsverzeichnis kennen.
Maven\ Version.error.1=Hudson muss Ihr Maven2/3-Installationsverzeichnis kennen.
Maven\ Version.error.2=Bitte geben Sie dieses in der <a href="{0}/configure" target="_new">Systemkonfiguration</a> an.
\ No newline at end of file
......@@ -20,7 +20,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
Maven\ Version.error.1=Hudson necesita saber donde está instalado Maven2.
Maven\ Version.error.1=Hudson necesita saber donde está instalado Maven2/3.
Maven\ Version.error.2=Configuraló en la pantalla de <a href="{0}/configure" target="_new">configuración del sistema</a>.
Root\ POM=Fichero POM raíz
Build=Proyecto
......
......@@ -31,6 +31,6 @@ Build\ Settings=Configuration du build
Use\ private\ Maven\ repository=Utilise un repository Maven priv\u00E9
Use\ private\ maven\ repository=Utiliser un repository Maven privé
Goals\ and\ options=Goals et options
Maven\ Version.error.1=Hudson a besoin de savoir où Maven2 est installé.
Maven\ Version.error.1=Hudson a besoin de savoir où Maven2/3 est installé.
Maven\ Version.error.2=Veuillez le faire dans <a href="{0}/configure" target="_new">la configuration système</a>.
Build\ whenever\ a\ SNAPSHOT\ dependency\ is\ built=Lance un build à chaque fois qu''une dépendance SNAPSHOT est construite
......@@ -22,7 +22,7 @@
Build=\u30D3\u30EB\u30C9
Maven\ Version=\u4F7F\u7528\u3059\u308BMaven
Maven\ Version.error.1=Maven2\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u5148\u3092\u8A2D\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
Maven\ Version.error.1=Maven2/3\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u5148\u3092\u8A2D\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
Maven\ Version.error.2=<a href="{0}/configure" target="_new">\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A</a>\u3067\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002
Root\ POM=\u30EB\u30FC\u30C8POM
Goals\ and\ options=\u30B4\u30FC\u30EB\u3068\u30AA\u30D7\u30B7\u30E7\u30F3
......
......@@ -20,5 +20,5 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
body=Byg et maven2 projekt. Hudson udnytter dine POM filer og reducerer herved \
body=Byg et maven2/3 projekt. Hudson udnytter dine POM filer og reducerer herved \
dramatisk behovet for konfiguration.
......@@ -21,5 +21,5 @@
# THE SOFTWARE.
body=\
Dieses Profil baut ein Maven 2 Projekt. Hudson wertet dabei Ihre POM Dateien aus und \
Dieses Profil baut ein Maven 2/3 Projekt. Hudson wertet dabei Ihre POM Dateien aus und \
reduziert damit den Konfigurationsaufwand ganz erheblich.
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
body=\u0394\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03B9\u03B1 maven2 project. O Hudson \u03B1\u03BE\u03B9\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF \u03C4\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 POM \u03BA\u03B1\u03B9 \u03BC\u03B5\u03B9\u03CE\u03BD\u03B5\u03B9 \u03B4\u03C1\u03B1\u03BC\u03B1\u03C4\u03B9\u03BA\u03AC \u03C4\u03B7\u03BD \u03C0\u03B1\u03C1\u03B1\u03BC\u03B5\u03C4\u03C1\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03B7 \u03C0\u03BF\u03C5 \u03C7\u03C1\u03B5\u03B9\u03AC\u03B6\u03B5\u03C4\u03B1\u03B9
body=\u0394\u03B7\u03BC\u03B9\u03BF\u03C5\u03C1\u03B3\u03B9\u03B1 maven2/3 project. O Hudson \u03B1\u03BE\u03B9\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF \u03C4\u03B1 \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 POM \u03BA\u03B1\u03B9 \u03BC\u03B5\u03B9\u03CE\u03BD\u03B5\u03B9 \u03B4\u03C1\u03B1\u03BC\u03B1\u03C4\u03B9\u03BA\u03AC \u03C4\u03B7\u03BD \u03C0\u03B1\u03C1\u03B1\u03BC\u03B5\u03C4\u03C1\u03BF\u03C0\u03BF\u03B9\u03AE\u03C3\u03B7 \u03C0\u03BF\u03C5 \u03C7\u03C1\u03B5\u03B9\u03AC\u03B6\u03B5\u03C4\u03B1\u03B9
......@@ -21,5 +21,5 @@
# THE SOFTWARE.
body=\
Ejecuta un proyecto maven2. Hudson es capaz de aprovechar la configuracion presente en los ficheros POM, reduciendo drásticamente la configuración.
Ejecuta un proyecto maven2/3. Hudson es capaz de aprovechar la configuracion presente en los ficheros POM, reduciendo drásticamente la configuración.
......@@ -22,6 +22,6 @@
# OUTDATED
body=\
Construit un projet avec maven2. Hudson utilise directement vos fichiers POM \
Construit un projet avec maven2/3. Hudson utilise directement vos fichiers POM \
et diminue radicalement l''effort de configuration. Cette fonctionnalit\u00e9 est encore en b\u00eata mais elle est \
disponible afin d''obtenir vos retours.
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
body=Effettua una build di un progetto maven2. Hudson sfrutta i file POM e riduce drasticamente la configurazione.
body=Effettua una build di un progetto maven2/3. Hudson sfrutta i file POM e riduce drasticamente la configurazione.
......@@ -21,4 +21,4 @@
# THE SOFTWARE.
body=\
Maven2\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u30d3\u30eb\u30c9\u3057\u307e\u3059\u3002Hudson\u306fPOM\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u5fc5\u8981\u306a\u60c5\u5831\u3092\u8aad\u307f\u53d6\u308b\u306e\u3067\u3001\u8a2d\u5b9a\u304c\u5fc5\u8981\u306a\u9805\u76ee\u306f\u3054\u304f\u308f\u305a\u304b\u3067\u3059\u3002
\ No newline at end of file
Maven2/3\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u30d3\u30eb\u30c9\u3057\u307e\u3059\u3002Hudson\u306fPOM\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u5fc5\u8981\u306a\u60c5\u5831\u3092\u8aad\u307f\u53d6\u308b\u306e\u3067\u3001\u8a2d\u5b9a\u304c\u5fc5\u8981\u306a\u9805\u76ee\u306f\u3054\u304f\u308f\u305a\u304b\u3067\u3059\u3002
\ No newline at end of file
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
body=Maven2 \uD504\uB85C\uC81D\uD2B8\uB97C \uBE4C\uB4DC\uD569\uB2C8\uB2E4. Hudson\uC740 POM \uD30C\uC77C\uC758 \uC774\uC810\uC744 \uAC00\uC9C0\uACE0 \uC788\uACE0 \uAE09\uACA9\uD788 \uC124\uC815\uC744 \uC904\uC785\uB2C8\uB2E4.
body=Maven2/3 \uD504\uB85C\uC81D\uD2B8\uB97C \uBE4C\uB4DC\uD569\uB2C8\uB2E4. Hudson\uC740 POM \uD30C\uC77C\uC758 \uC774\uC810\uC744 \uAC00\uC9C0\uACE0 \uC788\uACE0 \uAE09\uACA9\uD788 \uC124\uC815\uC744 \uC904\uC785\uB2C8\uB2E4.
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
body=Bygg et Maven 2 prosjekt. Hudson tar fordel av dine POM (Project Object Model - Prosjekt Objekt Modell) filer og drastisk reduserer behovet for konfigurasjon.
body=Bygg et Maven 2/3 prosjekt. Hudson tar fordel av dine POM (Project Object Model - Prosjekt Objekt Modell) filer og drastisk reduserer behovet for konfigurasjon.
......@@ -21,7 +21,7 @@
# THE SOFTWARE.
body=\
Bouw een maven2 project. Hudson maakt gebruikt van uw POM bestand wat \
Bouw een maven2/3 project. Hudson maakt gebruikt van uw POM bestand wat \
uw nood aan configuratie drastisch reduceert. Merk op dat deze functionaliteit \
nog steeds in ontwikkeling is, maar al reeds beschikbaar gesteld wordt om \
terugkoppeling te krijgen van gebruikers.
......@@ -22,6 +22,6 @@
# OUTDATED
body=\
Construir um projeto maven2. Hudson tira vantagem de seus arquivos POM e \
Construir um projeto maven2/3. Hudson tira vantagem de seus arquivos POM e \
reduz drasticamente a configura\u00e7\u00e3o. Ainda \u00e9 um trabalho em progresso, mas \
diposto a aceitar feedback.
......@@ -21,4 +21,4 @@
# THE SOFTWARE.
# OUTDATED
body=\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442 maven2. Hudson \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E \u0438\u0437 \u043F\u0440\u043E\u0435\u043A\u0442\u043D\u044B\u0445 \u0444\u0430\u0439\u043B\u043E\u0432 POM, \u0447\u0442\u043E \u0443\u043C\u0435\u043D\u0448\u0438\u0442 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E\u0441\u0442\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F.
body=\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442 maven2/3. Hudson \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044E \u0438\u0437 \u043F\u0440\u043E\u0435\u043A\u0442\u043D\u044B\u0445 \u0444\u0430\u0439\u043B\u043E\u0432 POM, \u0447\u0442\u043E \u0443\u043C\u0435\u043D\u0448\u0438\u0442 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E\u0441\u0442\u044C \u043A\u043E\u043D\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F.
......@@ -20,4 +20,4 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
body=Bygg ett maven2 projekt. Hudson utnyttjar dina POM filer och kommer drastiskt minska behovet av konfiguration.
body=Bygg ett maven2/3 projekt. Hudson utnyttjar dina POM filer och kommer drastiskt minska behovet av konfiguration.
......@@ -21,4 +21,4 @@
# THE SOFTWARE.
# OUTDATED
body=Maven2\ projesi\ yap\u0131land\u0131r.\ Hudson,\ POM\ dosyalar\u0131n\u0131z\u0131n\ avantajlar\u0131n\u0131\ kullan\u0131r\ ve\ konfig\u00fcrasyonu\ inan\u0131lmaz\ derecede\ azalt\u0131r.\ Hala\ \u00fczerinde\ \u00e7al\u0131\u015fma\ devam\ ediyor,\ dolay\u0131s\u0131yla geri\ bildirimler\ daima faydal\u0131 olacakt\u0131r.
body=Maven2/3\ projesi\ yap\u0131land\u0131r.\ Hudson,\ POM\ dosyalar\u0131n\u0131z\u0131n\ avantajlar\u0131n\u0131\ kullan\u0131r\ ve\ konfig\u00fcrasyonu\ inan\u0131lmaz\ derecede\ azalt\u0131r.\ Hala\ \u00fczerinde\ \u00e7al\u0131\u015fma\ devam\ ediyor,\ dolay\u0131s\u0131yla geri\ bildirimler\ daima faydal\u0131 olacakt\u0131r.
......@@ -21,4 +21,4 @@
# THE SOFTWARE.
body=\
\u6784\u5efa\u4e00\u4e2amaven2\u9879\u76ee.Hudson\u5229\u7528\u4f60\u7684POM\u6587\u4ef6,\u8fd9\u6837\u53ef\u4ee5\u5927\u5927\u51cf\u8f7b\u6784\u5efa\u914d\u7f6e.
\ No newline at end of file
\u6784\u5efa\u4e00\u4e2amaven2/3\u9879\u76ee.Hudson\u5229\u7528\u4f60\u7684POM\u6587\u4ef6,\u8fd9\u6837\u53ef\u4ee5\u5927\u5927\u51cf\u8f7b\u6784\u5efa\u914d\u7f6e.
\ No newline at end of file
......@@ -30,7 +30,7 @@ MavenBuilder.Waiting=Waiting for Hudson to finish collecting data
MavenModule.Pronoun=Module
MavenModuleSet.DiplayName=Build a maven2 project
MavenModuleSet.DiplayName=Build a maven2/3 project
MavenModuleSetBuild.DiscoveredModule=Discovered a new module {0} {1}
MavenModuleSetBuild.FailedToParsePom=Failed to parse POMs
......@@ -40,7 +40,7 @@ MavenModuleSetBuild.NoMavenInstall=A Maven installation needs to be available fo
MavenProbeAction.DisplayName=Monitor Maven Process
MavenProcessFactory.ClassWorldsNotFound=No classworlds*.jar found in {0} -- Is this a valid maven2 directory?
MavenProcessFactory.ClassWorldsNotFound=No classworlds*.jar found in {0} -- Is this a valid maven2/3 directory?
MavenRedeployer.DisplayName=Deploy to Maven repository
ProcessCache.Reusing=Reusing existing maven process
......
......@@ -29,7 +29,7 @@ MavenBuilder.Aborted=Afbrudt
MavenBuilder.Failed=Maven stoppede med en fejl.
MavenProbeAction.DisplayName=Overv\u00e5g Mavenproces
MavenProcessFactory.ClassWorldsNotFound=Ingen classworlds*.jar fundet i {0} -- Er dette et gyldigt maven2 direktorie?
MavenModuleSet.DiplayName=Byg et maven2 projekt
MavenModuleSet.DiplayName=Byg et maven2/3 projekt
MavenModule.Pronoun=Modul
MavenBuild.FailedEarlier=Bygget fejler f\u00f8r det n\u00e5r til dette modul
MavenModuleSetBuild.NoSuchPOMFile=Ingen fil kaldet {0}\nM\u00e5ske mangler du at specificere den korrekte POM fil placering i projekt konfigurationen?
......
......@@ -30,7 +30,7 @@ MavenBuilder.Waiting=Esperando a que Hudson finalize de recopilar datos
MavenModule.Pronoun=Modulo
MavenModuleSet.DiplayName=Crear un proyecto maven2
MavenModuleSet.DiplayName=Crear un proyecto maven2/3
MavenModuleSetBuild.DiscoveredModule=Se ha descubierto un nuevo mdulo {0} {1}
MavenModuleSetBuild.FailedToParsePom=Error al analizar el fichero POM
......
......@@ -29,7 +29,7 @@ MavenBuilder.Waiting=En attente qu''Hudson finisse de r
MavenModule.Pronoun=Module
MavenModuleSet.DiplayName=Construire un projet maven2
MavenModuleSet.DiplayName=Construire un projet maven2/3
MavenModuleSetBuild.DiscoveredModule=Un nouveau module {0} {1} a été trouvé
MavenModuleSetBuild.FailedToParsePom=Echec à la lecture des POMs
......@@ -37,7 +37,7 @@ MavenModuleSetBuild.NoSuchFile=Pas de fichier {0}\nAvez-vous sp
MavenProbeAction.DisplayName=Surveiller un process Maven
MavenProcessFactory.ClassWorldsNotFound=Pas de fichier classworlds*.jar trouvé dans {0} -- Est-ce un répertoire maven2 valide?
MavenProcessFactory.ClassWorldsNotFound=Pas de fichier classworlds*.jar trouvé dans {0} -- Est-ce un répertoire maven2/3 valide?
MavenRedeployer.DisplayName=Déployer vers un repository Maven
ProcessCache.Reusing=Réutilisation du process Maven existant
......
......@@ -30,7 +30,7 @@ MavenBuilder.Waiting=Hudson\u304c\u30c7\u30fc\u30bf\u53ce\u96c6\u3092\u5b8c\u4e8
MavenModule.Pronoun=\u30e2\u30b8\u30e5\u30fc\u30eb
MavenModuleSet.DiplayName=Maven2\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30d3\u30eb\u30c9
MavenModuleSet.DiplayName=Maven2/3\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30d3\u30eb\u30c9
MavenModuleSetBuild.DiscoveredModule=\u65b0\u898f\u30e2\u30b8\u30e5\u30fc\u30eb {0} {1} \u3092\u767a\u898b
MavenModuleSetBuild.FailedToParsePom=POM\u306e\u89e3\u6790\u306b\u5931\u6557
......
......@@ -30,7 +30,7 @@ MavenBuilder.Waiting=Wachtend to Hudson het verzamelen van gegevens be\u00EBindi
MavenModule.Pronoun=Module
MavenModuleSet.DiplayName=Bouw een maven2 project
MavenModuleSet.DiplayName=Bouw een maven2 p/3roject
MavenModuleSetBuild.DiscoveredModule= Een nieuwe module {0} {1} werd ontdekt.
MavenModuleSetBuild.FailedToParsePom=Het lezen van de POMs is gefaald.
......
......@@ -29,7 +29,7 @@ MavenBuilder.Waiting=Aguardando Hudson terminar de coletar dados
MavenModule.Pronoun=M\u00f3dulo
MavenModuleSet.DiplayName=Construir um projeto maven2
MavenModuleSet.DiplayName=Construir um projeto maven2/3
MavenModuleSetBuild.DiscoveredModule=Descoberto um novo m\u00f3dulo {0} {1}
MavenModuleSetBuild.FailedToParsePom=Falhou ao analisar POMs
......
......@@ -29,7 +29,7 @@ MavenBuilder.Waiting=\u041e\u0436\u0438\u0434\u0430\u044e \u043f\u043e\u043a\u04
MavenModule.Pronoun=\u041c\u043e\u0434\u0443\u043b\u044c
MavenModuleSet.DiplayName=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 maven2
MavenModuleSet.DiplayName=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 maven2/3
MavenModuleSetBuild.DiscoveredModule=\u041d\u0430\u0439\u0434\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c {0} {1}
MavenModuleSetBuild.FailedToParsePom=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c POM \u0444\u0430\u0439\u043b\u044b
......
......@@ -30,7 +30,7 @@ MavenBuilder.Waiting=Hudson''\u0131n bilgi toplamay\u0131 bitirmesi bekleniyor
MavenModule.Pronoun=Mod\u00fcl
MavenModuleSet.DiplayName=Maven2 projesi yap\u0131land\u0131r
MavenModuleSet.DiplayName=Maven2/3 projesi yap\u0131land\u0131r
MavenModuleSetBuild.DiscoveredModule={0} {1} olarak yeni bir mod\u00fcl bulundu
MavenModuleSetBuild.FailedToParsePom=POMlar\u0131 ayr\u0131\u015ft\u0131r\u0131rken hata ile kar\u015f\u0131la\u015f\u0131ld\u0131
......
......@@ -30,7 +30,7 @@ MavenBuilder.Waiting=Waiting for Hudson to finish collecting data
MavenModule.Pronoun=\u6a21\u5757
MavenModuleSet.DiplayName=\u6784\u5efa\u4e00\u4e2amaven2\u9879\u76ee
MavenModuleSet.DiplayName=\u6784\u5efa\u4e00\u4e2amaven2/3\u9879\u76ee
MavenModuleSetBuild.DiscoveredModule=Discovered a new module {0} {1}
MavenModuleSetBuild.FailedToParsePom=Failed to parse POMs
......
.settings
.project
target
.classpath
build
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>pom</artifactId>
<version>1.392-SNAPSHOT</version>
</parent>
<artifactId>maven3-agent</artifactId>
<name>Hudson Maven3 CLI Agent</name>
<dependencies>
<dependency>
<groupId>org.jvnet.hudson.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-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Olivier Lamy
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jvnet.hudson.maven3.agent;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.codehaus.plexus.classworlds.launcher.Launcher;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
/**
* Entry point for launching Maven 3 and Hudson remoting in the same VM, in the
* classloader layout that Maven expects.
*
* <p>
* The actual Maven execution will be started by the program sent through
* remoting.
* </p>
*
* @author Kohsuke Kawaguchi
* @author Olivier Lamy
*/
public class Maven3Main {
/**
* Used to pass the classworld instance to the code running inside the
* remoting system.
*/
private static Launcher launcher;
public static void main(String[] args) throws Exception {
main(new File(args[0]), new File(args[1]),new File(args[2]),
Integer.parseInt(args[3]));
}
/**
*
* @param m2Home
* Maven2 installation. This is where we find Maven jars that
* we'll run.
* @param remotingJar
* Hudson's remoting.jar that we'll load.
* @param 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(Maven3Main.class
.getResourceAsStream("classworlds.conf"));
// create a realm for loading remoting subsystem.
// this needs to be able to see maven.
ClassRealm remoting = launcher.getWorld().newRealm( "hudson-remoting", launcher.getSystemClassLoader() );
remoting.setParentRealm(launcher.getWorld().getRealm("plexus.core"));
remoting.addURL(remotingJar.toURI().toURL());
final Socket s = new Socket((String) null, tcpPort);
Class remotingLauncher = remoting.loadClass("hudson.remoting.Launcher");
remotingLauncher.getMethod("main",
new Class[] { InputStream.class, OutputStream.class }).invoke(
null,
new Object[] {
// do partial close, since socket.getInputStream and
// getOutputStream doesn't do it by
new BufferedInputStream(new FilterInputStream(s
.getInputStream()) {
public void close() throws IOException {
s.shutdownInput();
}
}),
new BufferedOutputStream(new RealFilterOutputStream(s
.getOutputStream()) {
public void close() throws IOException {
s.shutdownOutput();
}
}) });
System.exit(0);
}
/**
* Called by the code in remoting to launch.
*/
public static int launch(String[] args) throws Exception {
try {
launcher.launch(args);
} catch (Throwable e)
{
e.printStackTrace();
throw new Exception( e );
}
return launcher.getExitCode();
}
/**
* Makes sure that this is Java5 or later.
*/
private static void versionCheck() {
String v = System.getProperty("java.class.version");
if (v != null) {
try {
if (Float.parseFloat(v) < 49.0) {
System.err
.println("Native maven support requires Java 1.5 or later, but this Maven is using "
+ System.getProperty("java.home"));
System.err.println("Please use the freestyle project.");
System.exit(1);
}
} catch (NumberFormatException e) {
// couldn't check.
}
}
}
}
\ No newline at end of file
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package org.jvnet.hudson.maven3.agent;
import java.io.OutputStream;
import java.io.IOException;
import java.io.FilterOutputStream;
/**
* JDK's {@link FilterOutputStream} has some real issues.
*
* @author Kohsuke Kawaguchi
*/
class RealFilterOutputStream extends FilterOutputStream {
public RealFilterOutputStream(OutputStream core) {
super(core);
}
public void write(byte[] b) throws IOException {
out.write(b);
}
public void write(byte[] b, int off, int len) throws IOException {
out.write(b, off, len);
}
public void close() throws IOException {
out.close();
}
}
#
# mostly copied as-is from $MAVEN_HOME/bin/m2.conf
#
main is org.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 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jvnet.hudson.main</groupId>
<artifactId>pom</artifactId>
<version>1.392-SNAPSHOT</version>
</parent>
<artifactId>maven3-interceptor</artifactId>
<name>Hudson 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.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;
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异由.gitattributes 抑制。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册