Package hudson.maven

Source Code of hudson.maven.AbstractMavenProject$MavenModuleDependency

/*
* 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);
   
}
TOP

Related Classes of hudson.maven.AbstractMavenProject$MavenModuleDependency

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.