
hudson.maven.AbstractMavenProject Maven / Gradle / Ivy
Show all versions of legacy-maven-plugin Show documentation
/*******************************************************************************
*
* Copyright (c) 2004-2009 Oracle Corporation.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*
* Kohsuke Kawaguchi
*
*******************************************************************************/
package hudson.maven;
import hudson.maven.AbstractMavenBuild;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.DependencyGraph;
import hudson.model.Hudson;
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,R extends AbstractBuild
> extends AbstractProject
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 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.
*/
private boolean areUpstreamsBuilding(AbstractProject,?> downstreamProject,
AbstractProject,?> excludeProject) {
DependencyGraph graph = Hudson.getInstance().getDependencyGraph();
Set 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 = Hudson.getInstance().getDependencyGraph();
Set tups = graph.getTransitiveUpstream(downstreamProject);
for (AbstractProject tup : tups) {
List> 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 createTransientActions() {
List 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 added = new HashSet();
addTransientActionsFromBuild(getLastBuild(),r,added);
addTransientActionsFromBuild(getLastSuccessfulBuild(),r,added);
for (Trigger> trigger : getTriggersList())
r.addAll(trigger.getProjectActions());
return r;
}
/**
* @param collection
* Add the transient actions to this collection.
*/
protected abstract void addTransientActionsFromBuild(R lastBuild, List collection, Set added);
}