提交 f98070d3 编写于 作者: K Kohsuke Kawaguchi

maven plugin is moved off to a separate repository.

See https://github.com/jenkinsci/maven-plugin
上级 7ca07b5d
......@@ -42,7 +42,6 @@
<module name="jenkins-core" />
<module name="jenkins-test-harness" />
<module name="jenkins-war" />
<module name="maven-plugin" />
<module name="ui-samples-plugin" />
</profile>
</annotationProcessing>
......
<!--
The MIT License
Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi,
Daniel Dyer, Erik Ramfelt, Stephen Connolly, Tom Huybrechts, 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.535-SNAPSHOT</version>
</parent>
<artifactId>maven-plugin</artifactId>
<packaging>hpi</packaging>
<name>Maven Integration plugin</name>
<description>This plug-in provides deep integration of Jenkins and Maven. This functionality used to be part of the Jenkins core.
Now it is a plug-in that is installed by default, but can be disabled.</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/Maven+Project+Plugin</url>
<properties>
<mavenInterceptorsVersion>1.4</mavenInterceptorsVersion>
<mavenVersion>3.1.0</mavenVersion>
<maven.version>${mavenVersion}</maven.version>
<aetherVersion>0.9.0.M3</aetherVersion>
<sisuInjectVersion>0.0.0.M5</sisuInjectVersion>
<wagonVersion>2.4</wagonVersion>
</properties>
<issueManagement>
<system>jira</system>
<url>https://issues.jenkins-ci.org/browse/JENKINS/component/15487</url>
</issueManagement>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>jenkins-core</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>javadoc</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>mailer</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven-agent</artifactId>
<version>${mavenInterceptorsVersion}</version>
<exclusions>
<exclusion>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven-interceptor</artifactId>
<version>${mavenInterceptorsVersion}</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.jenkins-ci.main.maven</groupId>
<artifactId>maven3-agent</artifactId>
<version>${mavenInterceptorsVersion}</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
</exclusion>
<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-bean</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven31-agent</artifactId>
<version>${mavenInterceptorsVersion}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven3-interceptor</artifactId>
<version>${mavenInterceptorsVersion}</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
</exclusion>
<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-bean</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven31-interceptor</artifactId>
<version>${mavenInterceptorsVersion}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main.maven</groupId>
<artifactId>maven3-interceptor-commons</artifactId>
<version>${mavenInterceptorsVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-embedder</artifactId>
<version>${mavenVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-api</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-impl</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-spi</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-util</artifactId>
<version>${aetherVersion}</version>
</dependency>
<dependency>
<groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-wagon</artifactId>
<version>${aetherVersion}</version>
<exclusions>
<exclusion>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-container-default</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.plexus</artifactId>
<version>${sisuInjectVersion}</version>
<exclusions>
<exclusion>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-guice</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-plexus</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-inject-bean</artifactId>
<version>2.4.1</version>
</dependency>
-->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.0-beta</version>
<classifier>no_aop</classifier>
</dependency>
<!-- JENKINS-10819 : This wagon is safer and more configurable to provide http(s) support -->
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.2.4</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-file</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-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>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-provider-api</artifactId>
<version>${wagonVersion}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.reporting</groupId>
<artifactId>maven-reporting-api</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.lib</groupId>
<artifactId>lib-jenkins-maven-artifact-manager</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>org.jenkins-ci.lib</groupId>
<artifactId>lib-jenkins-maven-embedder</artifactId>
<version>3.11</version>
<exclusions>
<exclusion><!-- we'll add our own patched version. see https://issues.jenkins-ci.org/browse/JENKINS-1680 -->
<groupId>jtidy</groupId>
<artifactId>jtidy</artifactId>
</exclusion>
<exclusion>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
</exclusion>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<!-- we bundle our own version below -->
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
</dependency>
<!-- JENKINS-10076 : This wagon is better to provide webdav support -->
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav-jackrabbit</artifactId>
<version>${wagonVersion}</version>
<exclusions>
<exclusion><!-- jcl-over-slf4j version needs to match with slf4j-api version, which makes this fragile. let's not try to intercept jcl calls -->
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</exclusion>
<!-- SECURITY-61: unused -->
<exclusion>
<groupId>nekohtml</groupId>
<artifactId>nekohtml</artifactId>
</exclusion>
<exclusion>
<groupId>nekohtml</groupId>
<artifactId>xercesMinimal</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>token-macro</artifactId>
<version>1.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>findbugs</groupId>
<artifactId>annotations</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<scope>test</scope>
</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>
<plugins>
<plugin>
<groupId>org.jenkins-ci.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
<!-- version specified in grandparent pom -->
<extensions>true</extensions>
<configuration>
<showDeprecation>true</showDeprecation>
<disabledTestInjection>true</disabledTestInjection>
</configuration>
</plugin>
<plugin>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>maven-stapler-plugin</artifactId>
<!-- version specified in grandparent pom -->
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.jvnet.localizer</groupId>
<artifactId>maven-localizer-plugin</artifactId>
<!-- version specified in grandparent pom -->
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<fileMask>Messages.properties</fileMask>
<outputDirectory>target/generated-sources/localizer</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin><!-- generate licenses.xml -->
<groupId>com.cloudbees</groupId>
<artifactId>maven-license-plugin</artifactId>
<!-- version specified in grandparent pom -->
<configuration>
<generateLicenseXml>target/${project.artifactId}/WEB-INF/licenses.xml</generateLicenseXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>resgen</id>
<phase>generate-resources</phase>
<goals>
<!-- we use copy as this is a dependency from outside the reactor -->
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<!-- classworld 1.1 for maven 2 builds -->
<artifactItem>
<groupId>classworlds</groupId>
<artifactId>classworlds</artifactId>
<version>1.1</version>
<type>jar</type>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<destFileName>classworlds.jar</destFileName>
</artifactItem>
</artifactItems>
</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 specified in grandparent pom -->
<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., Kohsuke Kawaguchi, Red Hat, Inc., Victor Glushenkov
*
* 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.EnvVars;
import hudson.model.AbstractBuild;
import hudson.model.TaskListener;
import hudson.util.ReflectionUtils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class AbstractMavenBuild<P extends AbstractMavenProject<P,B>,B extends AbstractMavenBuild<P,B>> extends AbstractBuild<P, B> {
/**
* Extra verbose debug switch.
*/
public static boolean debug = false;
protected AbstractMavenBuild(P job) throws IOException {
super(job);
}
public AbstractMavenBuild(P job, Calendar timestamp) {
super(job, timestamp);
}
public AbstractMavenBuild(P project, File buildDir) throws IOException {
super(project, buildDir);
}
@Override
public EnvVars getEnvironment(TaskListener log) throws IOException, InterruptedException {
EnvVars envs = super.getEnvironment(log);
String opts = getMavenOpts(log,envs);
if(opts!=null)
envs.put("MAVEN_OPTS", opts);
return envs;
}
/**
* Obtains the fully resolved MAVEN_OPTS with all the tokens and variables expanded.
*
* @see MavenModuleSet#getMavenOpts()
* @param envVars
* Caller must pass in the environment variables obtained from {@link #getEnvironment(TaskListener)}
* This method takes this as a parameter as opposed to recomputing it since the caller always have this handy.
*/
public abstract String getMavenOpts(TaskListener listener, EnvVars envVars);
/**
* Expand tokens with token macro.
*/
protected final String expandTokens(TaskListener listener, String str) {
if (str==null) return null;
try {
Class<?> clazz = Class.forName( "org.jenkinsci.plugins.tokenmacro.TokenMacro" );
Method expandMethod =
ReflectionUtils.findMethod(clazz, "expand", new Class[]{AbstractBuild.class, TaskListener.class, String.class});
return (String) expandMethod.invoke( null, this, listener, str );
//opts = TokenMacro.expand(this, listener, opts);
}
catch(Exception tokenException) {
//Token plugin not present. Ignore, this is OK.
LOGGER.log(Level.FINE, "Ignore problem in expanding tokens", tokenException);
}
catch(LinkageError linkageError) {
// Token plugin not present. Ignore, this is OK.
LOGGER.log(Level.FINE, "Ignore problem in expanding tokens", linkageError);
}
return str;
}
private static final Logger LOGGER = Logger.getLogger(AbstractMavenBuild.class.getName());
}
/*
* 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.Launcher;
import hudson.maven.MavenBuild.ProxyImpl2;
import hudson.model.BuildListener;
import hudson.model.Executor;
import hudson.model.Result;
import hudson.remoting.Channel;
import hudson.remoting.DelegatingCallable;
import hudson.remoting.Future;
import java.io.IOException;
import java.io.Serializable;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutionException;
import jenkins.model.Jenkins;
/**
* @author Olivier Lamy
* @author Christoph Kutzinski
*
*/
public abstract class AbstractMavenBuilder implements DelegatingCallable<Result,IOException> {
private static final long serialVersionUID = -2687215937784908860L;
/**
* 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 Map<ModuleName,FilterImpl> proxies;
/**
* Kept so that we can finalize them in the end method.
*/
protected final transient Map<ModuleName,ProxyImpl2> sourceProxies = new HashMap<ModuleName, MavenBuild.ProxyImpl2>();
protected final Map<ModuleName,List<MavenReporter>> reporters = new HashMap<ModuleName,List<MavenReporter>>();
/**
* Record all asynchronous executions as they are scheduled,
* to make sure they are all completed before we finish.
*/
protected transient /*final*/ List<Future<?>> futures;
protected AbstractMavenBuilder(BuildListener listener, Collection<MavenModule> modules, List<String> goals, Map<String, String> systemProps) {
this.listener = listener;
this.goals = goals;
this.systemProps = systemProps;
for (MavenModule m : modules) {
reporters.put(m.getModuleName(),m.createReporters());
}
}
/**
* Invoked after the maven has finished running, and in the master, not in the maven process.
*/
void end(Launcher launcher) throws IOException, InterruptedException {
for (Map.Entry<ModuleName,ProxyImpl2> e : sourceProxies.entrySet()) {
ProxyImpl2 p = e.getValue();
for (MavenReporter r : reporters.get(e.getKey())) {
// we'd love to do this when the module build ends, but doing so requires
// we know how many task segments are in the current build.
r.end(p.owner(),launcher,listener);
p.appendLastLog();
}
p.close();
}
}
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();
}
/**
* Add all the {@link #systemProps jenkins environment variables} into the {@link System#getProperties() system properties}
* Ignores {@link #systemProps jenkins environment variables} with empty keys.
* @throws IllegalArgumentException if a {@link #systemProps jenkins environment variable} has null value
* as it blows up Maven.
* @see http://jenkins.361315.n4.nabble.com/Upgrade-to-1-424-broke-our-Maven-builds-due-to-empty-system-property-key-td3726460.html
*/
protected void registerSystemProperties() {
for (Map.Entry<String,String> e : systemProps.entrySet()) {
if ("".equals(e.getKey()))
continue;
if (e.getValue()==null)
throw new IllegalArgumentException("Global Environment Variable "+e.getKey()+" has a null value");
System.getProperties().put(e.getKey(), e.getValue());
}
}
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 Jenkins.getInstance().getPluginManager().uberClassLoader;
}
/**
* Initialize the collection of the asynchronous executions.
* The method must be called in the Maven jail process i.e. inside the call method!
*/
protected void initializeAsynchronousExecutions() {
futures = new CopyOnWriteArrayList<Future<?>>();
if (this.proxies != null) {
for(FilterImpl proxy : this.proxies.values()) {
proxy.setFutures(futures);
}
}
}
/**
* Records a new asynchronous exection.
*/
protected void recordAsynchronousExecution(Future<?> future) {
futures.add(future);
}
/**
* Waits until all asynchronous executions are finished.
*
* @return null in success case; returns an ABORT result if we were interrupted while waiting
*/
protected Result waitForAsynchronousExecutions() {
try {
boolean messageReported = false;
for (Future<?> f : futures) {
try {
if(!messageReported && !f.isDone()) {
messageReported = true;
listener.getLogger().println(Messages.MavenBuilder_Waiting());
}
f.get();
} catch (InterruptedException e) {
// attempt to cancel all asynchronous tasks
for (Future<?> g : futures)
g.cancel(true);
listener.getLogger().println(Messages.MavenBuilder_Aborted());
return Executor.currentExecutor().abortResult();
} catch (ExecutionException e) {
e.printStackTrace(listener.error(Messages.MavenBuilder_AsyncFailed()));
}
}
return null;
} finally {
futures.clear();
}
}
protected boolean isDebug() {
for(String goal : goals) {
if (goal.equals("-X") || goal.equals("--debug")) return true;
}
return false;
}
protected boolean isQuiet() {
for(String goal : goals) {
if (goal.equals("-q") || goal.equals("--quiet")) return true;
}
return false;
}
protected static class FilterImpl extends MavenBuildProxy2.Filter<MavenBuildProxy2> implements Serializable {
private MavenBuildInformation mavenBuildInformation;
/**
* Maven can internally use multiple threads to call {@link #executeAsync(BuildCallable)},
* making it impossible to rely on {@code Channel#current()} at the point of call, so
* instead we capture it when we get deserialized into Maven JVM.
* In other cases, we create FilterImpl inside Maven JVM, so we take it as a constructor.
* See JENKINS-11458
*/
private transient Channel channel;
private transient List<Future<?>> futures;
public FilterImpl(MavenBuildProxy2 core, MavenBuildInformation mavenBuildInformation) {
super(core);
this.mavenBuildInformation = mavenBuildInformation;
}
public FilterImpl(MavenBuildProxy2 core, MavenBuildInformation mavenBuildInformation, Channel channel) {
super(core);
this.mavenBuildInformation = mavenBuildInformation;
if (channel == null) {
throw new NullPointerException("channel must not be null!");
}
this.channel = channel;
}
@Override
public void executeAsync(final BuildCallable<?,?> program) throws IOException {
futures.add(
channel.callAsync(
new AsyncInvoker(core,program)));
}
public MavenBuildInformation getMavenBuildInformation() {
return mavenBuildInformation;
}
public void setFutures(List<Future<?>> futures) {
this.futures = futures;
}
public Object readResolve() {
channel = Channel.current();
return this;
}
private static final long serialVersionUID = 1L;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.DependencyGraph;
import jenkins.model.Jenkins;
import hudson.model.ItemGroup;
import hudson.model.Result;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.model.DependencyGraph.Dependency;
import hudson.tasks.Maven.ProjectWithMaven;
import hudson.triggers.Trigger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Common part between {@link MavenModule} and {@link MavenModuleSet}.
*
* @author Kohsuke Kawaguchi
*/
public abstract class AbstractMavenProject<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends AbstractProject<P,R>
implements ProjectWithMaven {
protected static class MavenModuleDependency extends Dependency {
public MavenModuleDependency(AbstractMavenProject<?,?> upstream,
AbstractProject<?,?> downstream) {
super(upstream, downstream);
}
@Override
public boolean shouldTriggerBuild(AbstractBuild build,
TaskListener listener, List<Action> actions) {
/**
* Schedules all the downstream builds.
* Returns immediately if build result doesn't meet the required level
* (as specified by {@link BuildTrigger}, or {@link Result#SUCCESS} if none).
*
* @param listener
* Where the progress reports go.
*/
if (build.getResult().isWorseThan(Result.SUCCESS)) return false;
// trigger dependency builds
AbstractProject<?,?> downstreamProject = getDownstreamProject();
if(AbstractMavenBuild.debug)
listener.getLogger().println("Considering whether to trigger "+downstreamProject+" or not");
// if the downstream module depends on multiple modules,
// only trigger them when all the upstream dependencies are updated.
boolean trigger = true;
// Check to see if any of its upstream dependencies are already building or in queue.
AbstractMavenProject<?,?> parent = (AbstractMavenProject<?,?>) getUpstreamProject();
if (areUpstreamsBuilding(downstreamProject, parent)) {
if(AbstractMavenBuild.debug)
listener.getLogger().println(" -> No, because downstream has dependencies already building or in queue");
trigger = false;
}
// Check to see if any of its upstream dependencies are in this list of downstream projects.
else if (inDownstreamProjects(downstreamProject)) {
if(AbstractMavenBuild.debug)
listener.getLogger().println(" -> No, because downstream has dependencies in the downstream projects list");
trigger = false;
}
else {
AbstractBuild<?,?> dlb = downstreamProject.getLastBuild(); // can be null.
for (AbstractMavenProject up : Util.filter(downstreamProject.getUpstreamProjects(),AbstractMavenProject.class)) {
Run ulb;
if(up==parent) {
// the current build itself is not registered as lastSuccessfulBuild
// at this point, so we have to take that into account. ugly.
if(build.getResult()==null || !build.getResult().isWorseThan(Result.UNSTABLE))
ulb = build;
else
ulb = up.getLastSuccessfulBuild();
} else
ulb = up.getLastSuccessfulBuild();
if(ulb==null) {
// if no usable build is available from the upstream,
// then we have to wait at least until this build is ready
if(AbstractMavenBuild.debug)
listener.getLogger().println(" -> No, because another upstream "+up+" for "+downstreamProject+" has no successful build");
trigger = false;
break;
}
// if no record of the relationship in the last build
// is available, we'll just have to assume that the condition
// for the new build is met, or else no build will be fired forever.
if(dlb==null) continue;
int n = dlb.getUpstreamRelationship(up);
if(n==-1) continue;
assert ulb.getNumber()>=n;
}
}
return trigger;
}
/**
* Determines whether any of the upstream project are either
* building or in the queue.
*
* This means eventually there will be an automatic triggering of
* the given project (provided that all builds went smoothly.)
*
* @param downstreamProject
* The AbstractProject we want to build.
* @param excludeProject
* An AbstractProject to exclude - if we see this in the transitive
* dependencies, we're not going to bother checking to see if it's
* building. For example, pass the current parent project to be sure
* that it will be ignored when looking for building dependencies.
* @return
* True if any upstream projects are building or in queue, false otherwise.
*/
@SuppressWarnings("rawtypes")
private boolean areUpstreamsBuilding(AbstractProject<?,?> downstreamProject,
AbstractProject<?,?> excludeProject) {
DependencyGraph graph = Jenkins.getInstance().getDependencyGraph();
Set<AbstractProject> tups = graph.getTransitiveUpstream(downstreamProject);
for (AbstractProject tup : tups) {
if(tup!=excludeProject && (tup.isBuilding() || tup.isInQueue()))
return true;
}
return false;
}
private boolean inDownstreamProjects(AbstractProject<?,?> downstreamProject) {
DependencyGraph graph = Jenkins.getInstance().getDependencyGraph();
Set<AbstractProject> tups = graph.getTransitiveUpstream(downstreamProject);
for (AbstractProject tup : tups) {
List<AbstractProject<?,?>> downstreamProjects = getUpstreamProject().getDownstreamProjects();
for (AbstractProject<?,?> dp : downstreamProjects) {
if(dp!=getUpstreamProject() && dp!=downstreamProject && dp==tup)
return true;
}
}
return false;
}
}
protected AbstractMavenProject(ItemGroup parent, String name) {
super(parent, name);
}
protected List<Action> createTransientActions() {
List<Action> r = super.createTransientActions();
// if we just pick up the project actions from the last build,
// and if the last build failed very early, then the reports that
// kick in later (like test results) won't be displayed.
// so pick up last successful build, too.
Set<Class> added = new HashSet<Class>();
addTransientActionsFromBuild(getLastBuild(),r,added);
addTransientActionsFromBuild(getLastSuccessfulBuild(),r,added);
for (Trigger<?> trigger : triggers())
r.addAll(trigger.getProjectActions());
return r;
}
/**
* @param collection
* Add the transient actions to this collection.
*/
protected abstract void addTransientActionsFromBuild(R lastBuild, List<Action> collection, Set<Class> added);
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.model.Action;
import java.util.List;
import java.util.Map;
/**
* Indicates that this {@link Action} for {@link MavenBuild} contributes
* an "aggregated" action to {@link MavenBuild#getModuleSetBuild()
* its governing MavenModuleSetBuild}.
*
* @author Kohsuke Kawaguchi
* @since 1.99
* @see MavenReporter
*/
public interface AggregatableAction extends Action {
/**
* Creates {@link Action} to be contributed to {@link MavenModuleSetBuild}.
*
* @param build
* {@link MavenModuleSetBuild} for which the aggregated report is
* created.
* @param moduleBuilds
* The result of {@link MavenModuleSetBuild#getModuleBuilds()} provided
* for convenience and efficiency.
* @return
* null if the reporter provides no such action.
*/
MavenAggregatedReport createAggregatedAction(
MavenModuleSetBuild build, Map<MavenModule,List<MavenBuild>> moduleBuilds);
}
package hudson.maven;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
/**
* ClassLoader that delegates to multiple side classloaders, in addition to the parent.
*
* The side classloaders generally need to be carefully crafted
* to avoid classloader constraint violations.
*
* @author Kohsuke Kawaguchi
*/
class AggregatingClassLoader extends ClassLoader {
private final List<ClassLoader> sides;
public AggregatingClassLoader(ClassLoader parent, List<ClassLoader> sides) {
super(parent);
this.sides = new ArrayList<ClassLoader>(sides);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for (ClassLoader cl : sides) {
try {
return cl.loadClass(name);
} catch (ClassNotFoundException e) {
//not found. try next
}
}
// not found in any of the classloader. delegate.
throw new ClassNotFoundException(name);
}
@Override
protected URL findResource(String name) {
for (ClassLoader cl : sides) {
URL url = cl.getResource(name);
if (url!=null)
return url;
}
return null;
}
@Override
protected Enumeration<URL> findResources(String name) throws IOException {
List<URL> resources = new ArrayList<URL>();
for (ClassLoader cl : sides) {
resources.addAll(Collections.list(cl.getResources(name)));
}
return Collections.enumeration(resources);
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import static hudson.Util.intern;
import hudson.Util;
import jenkins.model.Jenkins;
import hudson.remoting.Which;
import hudson.util.ReflectionUtils;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.kohsuke.stapler.Stapler;
/**
* Persisted record of mojo execution.
*
* <p>
* This information is first recorded in the maven process, then sent over
* the remoting layer to the master, then persisted via XStream.
*
* @author Kohsuke Kawaguchi
*/
public final class ExecutedMojo implements Serializable {
private static final long serialVersionUID = -3048316415397586490L;
/**
* Plugin group ID.
*/
public final String groupId;
/**
* Plugin artifact ID.
*/
public final String artifactId;
/**
* Plugin version.
*/
public final String version;
/**
* Mojo name.
*/
public final String goal;
/**
* Optional execution ID, when the same mojo gets executed multiple times.
*/
public final String executionId;
/**
* How long did it take to execute this goal? in milli-seconds.
* (precision might not be 1ms)
*/
public final long duration;
/**
* MD5 hash of the plugin jar.
*/
public final String digest;
public ExecutedMojo(MojoInfo mojo, long duration) {
this.groupId = mojo.pluginName.groupId;
this.artifactId = mojo.pluginName.artifactId;
this.version = mojo.pluginName.version;
this.goal = mojo.getGoal();
this.executionId = mojo.mojoExecution.getExecutionId();
this.duration = duration;
String digest = null;
MojoDescriptor md = mojo.mojoExecution.getMojoDescriptor();
PluginDescriptor pd = md.getPluginDescriptor();
try {
Class<?> clazz = getMojoClass( md, pd );
if (clazz!=null) {
File jarFile = Which.jarFile(clazz);
if (jarFile.isFile()) {
digest = Util.getDigestOf(jarFile);
} else {
// Maybe mojo was loaded from a classes dir instead of from a jar (JENKINS-5044)
LOGGER.log(Level.WARNING, "Cannot calculate digest of mojo class, because mojo wasn't loaded from a jar, but from: "
+ jarFile);
}
} else {
LOGGER.log(Level.WARNING, "Failed to getClass for "+md.getImplementation());
}
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING, "Failed to locate jar for "+md.getImplementation(),e);
} catch (ClassNotFoundException e) {
// perhaps the plugin has failed to load.
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Failed to calculate digest for "+md.getImplementation(),e);
}
this.digest = digest;
}
private Class<?> getMojoClass(MojoDescriptor md, PluginDescriptor pd) throws ClassNotFoundException {
try {
ClassRealm classRealm = pd.getClassRealm();
return classRealm == null ? null : classRealm.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 );
if (cl==null)
{
return null;
}
Class<?> clazz = cl.loadClass( md.getImplementation() );
return clazz;
}
/**
* Copy constructor used for interning.
*/
private ExecutedMojo(String groupId, String artifactId, String version, String goal, String executionId, long duration, String digest) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.goal = goal;
this.executionId = executionId;
this.duration = duration;
this.digest = digest;
}
/**
* Lots of {@link ExecutedMojo}s tend to have the same groupId, artifactId, etc., so interning them help
* with memory consumption.
*
* TODO: better if XStream has a declarative way of marking fields as "target for intern".
*/
protected Object readResolve() {
return new ExecutedMojo(intern(groupId),intern(artifactId),intern(version),intern(goal),intern(executionId),duration,intern(digest));
}
/**
* Returns duration in a human readable text.
*/
public String getDurationString() {
return Util.getTimeSpanString(duration);
}
public String getReadableExecutionId() {
if(executionId==null) return "-";
else return executionId;
}
/**
* Returns a hyperlink for the plugin name if there's one.
* Otherwise null.
*/
public String getPluginLink(Cache c) {
MavenModule m = c.get(this);
if(m!=null)
return Stapler.getCurrentRequest().getContextPath()+m.getUrl();
if(groupId.equals("org.apache.maven.plugins"))
return "http://maven.apache.org/plugins/"+artifactId+'/';
if (groupId.equals("org.codehaus.mojo"))
return "http://mojo.codehaus.org/"+artifactId+'/';
return null;
}
public String getGoalLink(Cache c) {
if(groupId.equals("org.apache.maven.plugins"))
return "http://maven.apache.org/plugins/"+artifactId+'/'+goal+"-mojo.html";
if (groupId.equals("org.codehaus.mojo"))
return "http://mojo.codehaus.org/"+artifactId+'/'+goal+"-mojo.html";
return null;
}
/**
* Used during the HTML rendering to cache the index.
*/
public static final class Cache {
/**
* All maven modules in this Hudson by their names.
*/
public final Map<ModuleName,MavenModule> modules = new HashMap<ModuleName,MavenModule>();
public Cache() {
for( MavenModule m : Jenkins.getInstance().getAllItems(MavenModule.class))
modules.put(m.getModuleName(),m);
}
public MavenModule get(ExecutedMojo mojo) {
return modules.get(new ModuleName(mojo.groupId,mojo.artifactId));
}
}
private static final Logger LOGGER = Logger.getLogger(ExecutedMojo.class.getName());
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.scm.ChangeLogSet;
import hudson.scm.ChangeLogSet.Entry;
import java.util.Iterator;
import java.util.List;
import java.util.Collections;
/**
* {@link ChangeLogSet} implementation used for {@link MavenBuild}.
*
* @author Kohsuke Kawaguchi
*/
public class FilteredChangeLogSet extends ChangeLogSet<Entry> {
private final List<Entry> master;
public final ChangeLogSet<? extends Entry> core;
/*package*/ FilteredChangeLogSet(MavenBuild build) {
super(build);
MavenModuleSetBuild parentBuild = build.getParentBuild();
if(parentBuild==null) {
core = ChangeLogSet.createEmpty(build);
master = Collections.emptyList();
} else {
core = parentBuild.getChangeSet();
master = parentBuild.getChangeSetFor(build.getParent());
}
}
public Iterator<Entry> iterator() {
return master.iterator();
}
public boolean isEmptySet() {
return master.isEmpty();
}
public List<Entry> getLogs() {
return master;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi,
* Red Hat, Inc., Victor Glushenkov, Alan Harder, Olivier Lamy, Christoph Kutzinski
*
* 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.maven.MavenBuild.ProxyImpl2;
import hudson.maven.reporters.TestFailureDetector;
import hudson.model.BuildListener;
import hudson.model.Result;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
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.monitor.event.EventDispatcher;
import org.apache.maven.project.MavenProject;
/**
* Runs Maven and builds the project.
*
* This is only used for
* {@link MavenModuleSet#isAggregatorStyleBuild() the aggregator style build}.
*/
@SuppressWarnings("deprecation") // as we're restricted to Maven 2.x API here, but compile against Maven 3.x, we cannot avoid deprecations
final class Maven2Builder extends MavenBuilder {
private final Map<ModuleName,List<ExecutedMojo>> executedMojos = new HashMap<ModuleName,List<ExecutedMojo>>();
private long mojoStartTime;
private MavenBuildProxy2 lastProxy;
private final AtomicBoolean hasTestFailures = new AtomicBoolean();
public Maven2Builder(BuildListener listener,Map<ModuleName,ProxyImpl2> proxies, Collection<MavenModule> modules, List<String> goals, Map<String,String> systemProps, MavenBuildInformation mavenBuildInformation) {
super(listener,modules,goals,systemProps);
this.sourceProxies.putAll(proxies);
this.proxies = new HashMap<ModuleName, FilterImpl>();
for (Entry<ModuleName,ProxyImpl2> e : this.sourceProxies.entrySet()) {
this.proxies.put(e.getKey(), new FilterImpl(e.getValue(), mavenBuildInformation));
}
}
@Override
public Result call() throws IOException {
try {
if (MavenModuleSetBuild.debug) {
listener.getLogger().println("Builder extends MavenBuilder in call " + Thread.currentThread().getContextClassLoader());
}
return super.call();
} finally {
if(lastProxy!=null)
lastProxy.appendLastLog();
}
}
@Override
void preBuild(MavenSession session, ReactorManager rm, EventDispatcher dispatcher) throws BuildFailureException, LifecycleExecutionException, IOException, InterruptedException {
// set all modules which are not actually being build (in incremental builds) to NOT_BUILD
List<MavenProject> projects = rm.getSortedProjects();
Set<ModuleName> buildingProjects = new HashSet<ModuleName>();
for (MavenProject p : projects) {
buildingProjects.add(new ModuleName(p));
}
for (Entry<ModuleName,FilterImpl> e : this.proxies.entrySet()) {
if (! buildingProjects.contains(e.getKey())) {
MavenBuildProxy2 proxy = e.getValue();
proxy.start();
proxy.setResult(Result.NOT_BUILT);
proxy.end();
}
}
}
void postBuild(MavenSession session, ReactorManager rm, EventDispatcher dispatcher) throws BuildFailureException, LifecycleExecutionException, IOException, InterruptedException {
// TODO
}
void preModule(MavenProject project) throws InterruptedException, IOException, hudson.maven.agent.AbortException {
ModuleName name = new ModuleName(project);
MavenBuildProxy2 proxy = proxies.get(name);
listener.getLogger().flush(); // make sure the data until here are all written
proxy.start();
for (MavenReporter r : reporters.get(name))
if(!r.preBuild(proxy,project,listener))
throw new hudson.maven.agent.AbortException(r+" failed");
}
void postModule(MavenProject project) throws InterruptedException, IOException, hudson.maven.agent.AbortException {
ModuleName name = new ModuleName(project);
MavenBuildProxy2 proxy = proxies.get(name);
List<MavenReporter> rs = reporters.get(name);
if(rs==null) { // probe for issue #906
throw new AssertionError("reporters.get("+name+")==null. reporters="+reporters+" proxies="+proxies);
}
for (MavenReporter r : rs)
if(!r.postBuild(proxy,project,listener))
throw new hudson.maven.agent.AbortException(r+" failed");
proxy.setExecutedMojos(executedMojos.get(name));
listener.getLogger().flush(); // make sure the data until here are all written
proxy.end();
lastProxy = proxy;
}
void preExecute(MavenProject project, MojoInfo mojoInfo) throws IOException, InterruptedException, hudson.maven.agent.AbortException {
ModuleName name = new ModuleName(project);
MavenBuildProxy proxy = proxies.get(name);
for (MavenReporter r : reporters.get(name))
if(!r.preExecute(proxy,project,mojoInfo,listener))
throw new hudson.maven.agent.AbortException(r+" failed");
mojoStartTime = System.currentTimeMillis();
}
void postExecute(MavenProject project, MojoInfo mojoInfo, Exception exception) throws IOException, InterruptedException, hudson.maven.agent.AbortException {
ModuleName name = new ModuleName(project);
List<ExecutedMojo> mojoList = executedMojos.get(name);
if(mojoList==null)
executedMojos.put(name,mojoList=new ArrayList<ExecutedMojo>());
mojoList.add(new ExecutedMojo(mojoInfo,System.currentTimeMillis()-mojoStartTime));
MavenBuildProxy2 proxy = proxies.get(name);
for (MavenReporter r : reporters.get(name)){
if(!r.postExecute(proxy,project,mojoInfo,listener,exception)) {
throw new hudson.maven.agent.AbortException(r+" failed");
} else if (r instanceof TestFailureDetector) {
if(((TestFailureDetector) r).hasTestFailures()) {
hasTestFailures.compareAndSet(false, true);
}
}
}
if(exception!=null)
proxy.setResult(Result.FAILURE);
}
void onReportGenerated(MavenProject project, MavenReportInfo report) throws IOException, InterruptedException, hudson.maven.agent.AbortException {
ModuleName name = new ModuleName(project);
MavenBuildProxy proxy = proxies.get(name);
for (MavenReporter r : reporters.get(name))
if(!r.reportGenerated(proxy,project,report,listener))
throw new hudson.maven.agent.AbortException(r+" failed");
}
@Override
public boolean hasBuildFailures() {
return hasTestFailures.get();
}
private static final long serialVersionUID = 1L;
}
\ No newline at end of file
/*
* 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 hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.BuildListener;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.tasks.Maven.MavenInstallation;
import jenkins.maven3.agent.Maven31Main;
import org.jvnet.hudson.maven3.launcher.Maven31Interceptor;
import org.jvnet.hudson.maven3.listeners.HudsonMavenExecutionResult;
import java.io.IOException;
import java.net.URL;
/**
* {@link hudson.maven.AbstractMavenProcessFactory} for Maven 3.
*
* @author Olivier Lamy
*/
public class Maven31ProcessFactory extends Maven3ProcessFactory
{
Maven31ProcessFactory( MavenModuleSet mms, AbstractMavenBuild<?, ?> build, Launcher launcher, EnvVars envVars,
String mavenOpts, FilePath workDir ) {
super( mms, build, launcher, envVars, mavenOpts, workDir );
}
@Override
protected String getMainClassName()
{
return Maven31Main.class.getName();
}
@Override
protected String getMavenAgentClassPath(MavenInstallation mvn, FilePath slaveRoot, BuildListener listener) throws IOException, InterruptedException {
String classWorldsJar = getLauncher().getChannel().call(new Maven3ProcessFactory.GetClassWorldsJar(mvn.getHome(),listener));
String path = classPathEntry(slaveRoot, Maven31Main.class, "maven31-agent", listener) +
(getLauncher().isUnix()?":":";")+classWorldsJar;
// TODO this configurable??
path += (getLauncher().isUnix()?":":";")+mvn.getHomeDir().getPath()+"/conf/logging";
return path;
}
@Override
protected void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask(context));
}
private static final class InstallPlexusModulesTask implements Callable<Void,IOException>
{
PlexusModuleContributor c;
public InstallPlexusModulesTask(AbstractMavenBuild<?, ?> context) throws IOException, InterruptedException {
c = PlexusModuleContributorFactory.aggregate(context);
}
public Void call() throws IOException {
Maven31Main.addPlexusComponents( c.getPlexusComponentJars().toArray( new URL[0] ) );
return null;
}
private static final long serialVersionUID = 1L;
}
@Override
protected String getMavenInterceptorClassPath(MavenInstallation mvn, FilePath slaveRoot, BuildListener listener) throws IOException, InterruptedException {
return classPathEntry(slaveRoot, Maven31Interceptor.class, "maven31-interceptor", listener);
}
protected String getMavenInterceptorCommonClassPath(MavenInstallation mvn, FilePath slaveRoot, BuildListener listener) throws IOException, InterruptedException {
return classPathEntry(slaveRoot, HudsonMavenExecutionResult.class, "maven3-interceptor-commons", listener);
}
}
/*
* 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 hudson.EnvVars;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.BuildListener;
import hudson.model.Run.RunnerAbortedException;
import hudson.model.TaskListener;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.tasks.Maven.MavenInstallation;
import org.jvnet.hudson.maven3.agent.Maven3Main;
import org.jvnet.hudson.maven3.launcher.Maven3Launcher;
import org.jvnet.hudson.maven3.listeners.HudsonMavenExecutionResult;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URL;
/**
* {@link AbstractMavenProcessFactory} for Maven 3.
*
* @author Olivier Lamy
*/
public class Maven3ProcessFactory extends AbstractMavenProcessFactory implements ProcessCache.Factory
{
Maven3ProcessFactory(MavenModuleSet mms, AbstractMavenBuild<?,?> build, Launcher launcher, EnvVars envVars, String mavenOpts, FilePath workDir) {
super( mms, build, launcher, envVars, mavenOpts, workDir );
}
@Override
protected String getMavenAgentClassPath(MavenInstallation mvn, FilePath slaveRoot, BuildListener listener) throws IOException, InterruptedException {
String classWorldsJar = getLauncher().getChannel().call(new GetClassWorldsJar(mvn.getHome(),listener));
return classPathEntry(slaveRoot, Maven3Main.class, "maven3-agent", listener) +
(getLauncher().isUnix()?":":";")+classWorldsJar;
}
@Override
protected String getMainClassName() {
return Maven3Main.class.getName();
}
@Override
protected String getMavenInterceptorClassPath(MavenInstallation mvn, FilePath slaveRoot, BuildListener listener) throws IOException, InterruptedException {
return classPathEntry(slaveRoot, Maven3Launcher.class, "maven3-interceptor", listener);
}
protected String getMavenInterceptorCommonClassPath(MavenInstallation mvn, FilePath slaveRoot, BuildListener listener) throws IOException, InterruptedException {
return classPathEntry(slaveRoot, HudsonMavenExecutionResult.class, "maven3-interceptor-commons", listener);
}
@Override
protected String getMavenInterceptorOverride(MavenInstallation mvn,
FilePath slaveRoot, BuildListener listener) throws IOException,
InterruptedException {
return null;
}
@Override
protected void applyPlexusModuleContributor(Channel channel, AbstractMavenBuild<?, ?> context) throws InterruptedException, IOException {
channel.call(new InstallPlexusModulesTask(context));
}
private static final class InstallPlexusModulesTask implements Callable<Void,IOException> {
PlexusModuleContributor c;
public InstallPlexusModulesTask(AbstractMavenBuild<?, ?> context) throws IOException, InterruptedException {
c = PlexusModuleContributorFactory.aggregate(context);
}
public Void call() throws IOException {
Maven3Main.addPlexusComponents(c.getPlexusComponentJars().toArray(new URL[0]));
return null;
}
private static final long serialVersionUID = 1L;
}
/**
* Finds classworlds.jar
*/
protected static final class GetClassWorldsJar implements Callable<String,IOException> {
private static final long serialVersionUID = -2599434124883557137L;
private final String mvnHome;
private final TaskListener listener;
protected 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) {
listener.error(Messages.MavenProcessFactory_ClassWorldsNotFound(home));
throw new RunnerAbortedException();
}
return classworlds[0].getAbsolutePath();
}
}
/**
* 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");
}
};
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.model.Action;
import hudson.tasks.BuildStep;
import java.util.List;
import java.util.Map;
/**
* {@link Action} to be associated with {@link MavenModuleSetBuild},
* which usually displays some aspect of the aggregated results
* of the module builds (such as aggregated test result, aggregated
* coverage report, etc.)
*
* <p>
* When a module build is completed, {@link MavenBuild#getModuleSetBuild()
* its governing MavenModuleSetBuild} tries to create an instane of
* {@link MavenAggregatedReport} from each kind of {@link MavenReporterDescriptor}
* whose {@link MavenReporter}s are used on module builds.
*
* <p>
* The obtained instance is then persisted with {@link MavenModuleSetBuild}.
*
* @author Kohsuke Kawaguchi
* @since 1.99
* @see AggregatableAction
*/
public interface MavenAggregatedReport extends Action {
/**
* Called whenever a new module build is completed, to update the
* aggregated report. When multiple builds complete simultaneously,
* Hudson serializes the execution of this method, so this method
* needs not be concurrency-safe.
*
* @param moduleBuilds
* Same as <tt>MavenModuleSet.getModuleBuilds()</tt> but provided for convenience and efficiency.
* @param newBuild
* Newly completed build.
*/
void update(Map<MavenModule,List<MavenBuild>> moduleBuilds, MavenBuild newBuild);
/**
* Returns the implementation class of {@link AggregatableAction} that
* produces this {@link MavenAggregatedReport}. Hudson uses this method
* to determine which {@link AggregatableAction} is aggregated to
* which {@link MavenAggregatedReport}.
*/
Class<? extends AggregatableAction> getIndividualActionType();
/**
* Equivalent of {@link BuildStep#getProjectAction(AbstractProject)}
* for {@link MavenAggregatedReport}.
*/
Action getProjectAction(MavenModuleSet moduleSet);
}
/*
* The MIT License
*
* Copyright (c) 2011, Dominik Bartholdi
*
* 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.Action;
import hudson.util.ArgumentListBuilder;
/**
* Provides a hook to change the arguments passed to the maven execution. This
* enables plugins to transiently change the arguments of a maven build (e.g.
* change the arguments for a release build).
*
* @author Dominik Bartholdi (imod)
*
*/
public interface MavenArgumentInterceptorAction extends Action {
/**
* Provides maven goals and options to start the build with. This is the
* preferred way to provide other goals then the default ones to a build.
* The goals and options returned by this method will not be persist and do
* not affect the default configuration.
* <p>
* This method will be called on one and only one action during a build. If
* there are two actions present in the build, the second will be ignored.
*
* @param build
* reference to the current build, might be used for some
* calculations for the correct arguments
* @return the maven goals and options to start maven with. Result is
* ignored if <code>null</code> or empty. Variables will be expanded
* by the caller.
*/
public String getGoalsAndOptions(MavenModuleSetBuild build);
/**
* Change/add arguments to any needs, but special care has to be taken, as
* the list contains every argument needed for the default execution (e.g.
* <code>-f /path/to/pom.xml</code> or <code>-B</code>). <br />
* An easy example would be to add "<code>-DskipTests</code>" to skip the
* test execution on request.
*
* <p>
* This method is called on all present MavenArgumentInterceptorAction
* during a build (kind of chaining, each action can add the arguments it
* thinks are missing).
*
* @param mavenargs
* the calculated default maven arguments (never
* <code>null</code>).
* @param build
* reference to the current build, might be used for some
* calculations for the correct arguments
* @return the new arguments to be used.
*/
public ArgumentListBuilder intercept(ArgumentListBuilder mavenargs, MavenModuleSetBuild build);
}
package hudson.maven;
/*
* 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.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.apache.maven.model.Model;
import org.apache.maven.project.MavenProject;
/**
* @author Olivier Lamy
* @since 1.392
*/
public class MavenBuildInformation implements Serializable {
private static final long serialVersionUID = -3719709179508200057L;
private String mavenVersion;
/**
* Map of model IDs to IDs of the model parents (if defined).
* @see MavenProject#getId
* @see Model#getId
* @see MavenProject#getParent
* @see Model#getParent
* @since 1.515
*/
public final Map<String,String> modelParents = new HashMap<String,String>();
public MavenBuildInformation(String mavenVersion) {
this.mavenVersion = mavenVersion;
}
public String getMavenVersion()
{
return mavenVersion;
}
/**
* @since 1.441
*/
public boolean isMaven3OrLater() {
return MavenUtil.maven3orLater(mavenVersion);
}
/**
* Returns if this maven version is at least 'version'.
* @param version the version to compare against
*
* @since 1.441
*/
public boolean isAtLeastMavenVersion(String version) {
if (StringUtils.isBlank(mavenVersion)) {
return false;
}
return new ComparableVersion(mavenVersion).compareTo(new ComparableVersion(version)) >= 0;
}
@Override
public String toString() {
return mavenVersion;
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.FilePath;
import hudson.model.Result;
import hudson.remoting.Callable;
import hudson.remoting.DelegatingCallable;
import java.io.IOException;
import java.io.Serializable;
import java.util.Calendar;
import java.util.List;
import jenkins.model.ArtifactManager;
/**
* Remoting proxy interface for {@link MavenReporter}s to talk to {@link MavenBuild}
* during the build.
*
* That is, this represents {@link MavenBuild} objects in the master's JVM to code
* running inside Maven JVM.
*
* @author Kohsuke Kawaguchi
*/
public interface MavenBuildProxy {
/**
* Executes the given {@link BuildCallable} on the master, where one
* has access to {@link MavenBuild} and all the other Hudson objects.
*
* <p>
* The parameter, return value, and exception are all transfered by using
* Java serialization.
*
* @return
* the value that {@link BuildCallable} returned.
* @throws T
* if {@link BuildCallable} throws this exception.
* @throws IOException
* if the remoting failed.
* @throws InterruptedException
* if the remote execution is aborted.
* @see #executeAsync(BuildCallable)
*/
<V,T extends Throwable> V execute( BuildCallable<V,T> program ) throws T, IOException, InterruptedException;
/**
* Executes the given {@link BuildCallable} asynchronously on the master.
* <p>
* This method works like {@link #execute(BuildCallable)} except that
* the method returns immediately and doesn't wait for the completion of the program.
* <p>
* The completions of asynchronous executions are accounted for before
* the build completes. If they throw exceptions, they'll be reported
* and the build will be marked as a failure.
*/
void executeAsync( BuildCallable<?,?> program ) throws IOException;
/**
* Root directory of the build.
*
* @see MavenBuild#getRootDir()
*/
FilePath getRootDir();
/**
* Root directory of the parent of this build.
*/
FilePath getProjectRootDir();
/**
* Root directory of the owner {@link MavenModuleSet}
*/
FilePath getModuleSetRootDir();
/**
* @deprecated Does not work with {@link ArtifactManager}.
*/
@Deprecated
FilePath getArtifactsDir();
/**
* @param artifactPath a relative {@code /}-separated path
* @param artifact absolute path name on the slave in the workspace
* @see ArtifactManager#archive
* @since 1.532
*/
void queueArchiving(String artifactPath, String artifact);
/**
* @see MavenBuild#setResult(Result)
*/
void setResult(Result result);
/**
* @see MavenBuild#getTimestamp()
*/
Calendar getTimestamp();
/**
* # of milliseconds elapsed since {@link #getTimestamp()}.
*
* Where the clock skew is involved between the master and the Maven JVM, comparing
* current time on Maven JVM with {@link #getTimestamp()} could be problematic,
* but this value is more robust.
*/
long getMilliSecsSinceBuildStart();
/**
* If true, artifacts will not actually be archived to master. Calls {@link MavenModuleSet#isArchivingDisabled()}.
*/
boolean isArchivingDisabled();
/**
* Nominates that the reporter will contribute a project action
* for this build by using {@link MavenReporter#getProjectActions(MavenModule)}.
*
* <p>
* The specified {@link MavenReporter} object will be transfered to the master
* and will become a persisted part of the {@link MavenBuild}.
*/
void registerAsProjectAction(MavenReporter reporter);
/**
* Nominates that the reporter will contribute a project action
* for this build by using {@link MavenReporter#getProjectActions(MavenModule)}.
*
* <p>
* The specified {@link MavenReporter} object will be transferred to the master
* and will become a persisted part of the {@link MavenBuild}.
*
* @since 1.372
*/
void registerAsProjectAction(MavenProjectActionBuilder builder);
/**
* Nominates that the reporter will contribute a project action
* for this build by using {@link MavenReporter#getAggregatedProjectAction(MavenModuleSet)}.
*
* <p>
* The specified {@link MavenReporter} object will be transfered to the master
* and will become a persisted part of the {@link MavenModuleSetBuild}.
*/
void registerAsAggregatedProjectAction(MavenReporter reporter);
/**
* Called at the end of the build to record what mojos are executed.
*/
void setExecutedMojos(List<ExecutedMojo> executedMojos);
interface BuildCallable<V,T extends Throwable> extends Serializable {
/**
* Performs computation and returns the result,
* or throws some exception.
*
* @throws InterruptedException
* if the processing is interrupted in the middle. Exception will be
* propagated to the caller.
* @throws IOException
* if the program simply wishes to propage the exception, it may throw
* {@link IOException}.
*/
V call(MavenBuild build) throws T, IOException, InterruptedException;
}
MavenBuildInformation getMavenBuildInformation();
/**
* Filter for {@link MavenBuildProxy}.
*
* Meant to be useful as the base class for other filters.
*/
/*package*/ abstract class Filter<CORE extends MavenBuildProxy> implements MavenBuildProxy, Serializable {
protected final CORE core;
protected Filter(CORE core) {
this.core = core;
}
public <V, T extends Throwable> V execute(BuildCallable<V, T> program) throws T, IOException, InterruptedException {
return core.execute(program);
}
public void executeAsync(BuildCallable<?, ?> program) throws IOException {
core.executeAsync(program);
}
public FilePath getRootDir() {
return core.getRootDir();
}
public FilePath getProjectRootDir() {
return core.getProjectRootDir();
}
public FilePath getModuleSetRootDir() {
return core.getModuleSetRootDir();
}
public FilePath getArtifactsDir() {
return core.getArtifactsDir();
}
@Override public void queueArchiving(String artifactPath, String artifact) {
core.queueArchiving(artifactPath, artifact);
}
public void setResult(Result result) {
core.setResult(result);
}
public Calendar getTimestamp() {
return core.getTimestamp();
}
public long getMilliSecsSinceBuildStart() {
return core.getMilliSecsSinceBuildStart();
}
public boolean isArchivingDisabled() {
return core.isArchivingDisabled();
}
public void registerAsProjectAction(MavenReporter reporter) {
core.registerAsProjectAction(reporter);
}
public void registerAsProjectAction(MavenProjectActionBuilder builder) {
core.registerAsProjectAction(builder);
}
public void registerAsAggregatedProjectAction(MavenReporter reporter) {
core.registerAsAggregatedProjectAction(reporter);
}
public void setExecutedMojos(List<ExecutedMojo> executedMojos) {
core.setExecutedMojos(executedMojos);
}
public MavenBuildInformation getMavenBuildInformation() {
return core.getMavenBuildInformation();
}
private static final long serialVersionUID = 1L;
/**
* {@link Callable} for invoking {@link BuildCallable} asynchronously.
*/
protected static final class AsyncInvoker implements DelegatingCallable<Object,Throwable> {
private final MavenBuildProxy proxy;
private final BuildCallable<?,?> program;
public AsyncInvoker(MavenBuildProxy proxy, BuildCallable<?,?> program) {
this.proxy = proxy;
this.program = program;
}
public ClassLoader getClassLoader() {
return program.getClass().getClassLoader();
}
public Object call() throws Throwable {
// by the time this method is invoked on the master, proxy points to a real object
proxy.execute(program);
return null; // ignore the result, as there's no point in sending it back
}
private static final long serialVersionUID = 1L;
}
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
/**
* A part of {@link MavenBuildProxy} that's used internally
* for aggregated build. Fired and consumed internally and
* not exposed to plugins.
*
* @author Kohsuke Kawaguchi
*/
public interface MavenBuildProxy2 extends MavenBuildProxy {
/**
* Notifies that the build has entered a module.
*
* Jenkins has a somewhat simplified view of the sequence of events in a Maven build.
* Namely, a Maven build can be building a particular Maven module, and start and end marks that boundary.
* Note that Maven can be in a state that it's not building any module, for example when executing an aggregator mojo,
* and start/end cannot be nested (which right now means a forked lifecycle doesn't result in the event firing.)
*/
void start();
/**
* Notifies that the build has left a module.
*/
void end();
/**
* Maven produces additional error message after the module build is done.
* So to catch those messages, invoke this method on the last module that was built
* after all the Maven processing is done, to append last messages to the console
* output of the module.
*/
void appendLastLog();
/**
* Filter for {@link MavenBuildProxy2}.
*
* Meant to be useful as the base class for other filters.
*/
/*package*/ abstract class Filter<CORE extends MavenBuildProxy2> extends MavenBuildProxy.Filter<CORE> implements MavenBuildProxy2 {
private static final long serialVersionUID = -1208416744028858844L;
protected Filter(CORE core) {
super(core);
}
public void start() {
core.start();
}
public void end() {
core.end();
}
public void appendLastLog() {
core.appendLastLog();
}
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.EnvVars;
import hudson.model.AbstractProject;
import hudson.model.Action;
import jenkins.model.Jenkins;
import hudson.remoting.Channel;
import hudson.util.RemotingDiagnostics;
import hudson.util.RemotingDiagnostics.HeapDump;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Map;
/**
* UI for probing Maven process.
*
* <p>
* This action is added to a build when it's started, and removed
* when it's completed.
*
* @author Kohsuke Kawaguchi
* @since 1.175
*/
public final class MavenProbeAction implements Action {
private final transient Channel channel;
public final AbstractProject<?,?> owner;
MavenProbeAction(AbstractProject<?,?> owner, Channel channel) {
this.channel = channel;
this.owner = owner;
}
public String getIconFileName() {
if(channel==null) return null;
return "computer.png";
}
public String getDisplayName() {
return Messages.MavenProbeAction_DisplayName();
}
public String getUrlName() {
if(channel==null) return null;
return "probe";
}
/**
* Gets the system properties of the JVM on this computer.
* If this is the master, it returns the system property of the master computer.
*/
public Map<Object,Object> getSystemProperties() throws IOException, InterruptedException {
return RemotingDiagnostics.getSystemProperties(channel);
}
/**
* Gets the environment variables of the JVM on this computer.
* If this is the master, it returns the system property of the master computer.
*/
public Map<String,String> getEnvVars() throws IOException, InterruptedException {
return EnvVars.getRemote(channel);
}
/**
* Gets the thread dump of the slave JVM.
* @return
* key is the thread name, and the value is the pre-formatted dump.
*/
public Map<String,String> getThreadDump() throws IOException, InterruptedException {
return RemotingDiagnostics.getThreadDump(channel);
}
public void doScript( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException {
Jenkins._doScript(req, rsp, req.getView(this, "_script.jelly"), channel, owner.getACL());
}
/**
* Obtains the heap dump.
*/
public HeapDump getHeapDump() throws IOException {
return new HeapDump(owner,channel);
}
}
/*
* The MIT License
*
* Copyright (c) 2010, InfraDNA, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import hudson.model.Action;
import hudson.tasks.BuildStep;
import java.util.Collection;
/**
* Can contribute to project actions.
*
*
* @author Kohsuke Kawaguchi
* @see MavenBuildProxy#registerAsProjectAction(MavenProjectActionBuilder)
*/
public interface MavenProjectActionBuilder {
/**
* Equivalent of {@link BuildStep#getProjectActions(AbstractProject)}.
*
* <p>
* Registers a transient action to {@link MavenModule} when it's rendered.
* This is useful if you'd like to display an action at the module level.
*
* <p>
* Since this contributes a transient action, the returned {@link Action}
* will not be serialized.
*
* <p>
* For this method to be invoked, call
* {@link MavenBuildProxy#registerAsProjectAction(MavenProjectActionBuilder)} during the build.
*
* @return
* can be empty but never null.
* @since 1.341
*/
Collection<? extends Action> getProjectActions(MavenModule module);
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package hudson.maven;
import org.apache.maven.reporting.MavenReport;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.Mojo;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
/**
* Information about {@link MavenReport} that was executed.
*
* <p>
* Since {@link MavenReport} is always a {@link Mojo} (even though the interface
* inheritance is not explicitly defined), this class extends from {@link MojoInfo}.
*
* <p>
* This object provides additional convenience methods that only make sense for {@link MavenReport}.
*
* @author Kohsuke Kawaguchi
* @see MojoInfo
*/
public final class MavenReportInfo extends MojoInfo {
/**
* The fully-populated {@link MavenReport} object. The same object as
* {@link #mojo} but in the right type. Never null.
*/
public final MavenReport report;
public MavenReportInfo(MojoExecution mojoExecution, MavenReport mojo, PlexusConfiguration configuration, ExpressionEvaluator expressionEvaluator,
long mojoStartTime) {
super(mojoExecution, (Mojo)mojo, configuration, expressionEvaluator,mojoStartTime);
this.report = mojo;
}
}
package hudson.maven.local_repo;
import hudson.model.Descriptor;
/**
* @author Kohsuke Kawaguchi
* @since 1.448
* @see LocalRepositoryLocator
*/
public abstract class LocalRepositoryLocatorDescriptor extends Descriptor<LocalRepositoryLocator> {
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册