File D:\maven-qcr-plugin-testsunitaires\qcr4java\jenkins-master\target\site\qc\maven-plugin\src\main\java\hudson\maven\AbstractMavenProject.java.html

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 package hudson.maven;
25
26 import hudson.Util;
27 import hudson.model.AbstractBuild;
28 import hudson.model.AbstractProject;
29 import hudson.model.Action;
30 import hudson.model.DependencyGraph;
31 import jenkins.model.Jenkins;
32 import hudson.model.ItemGroup;
33 import hudson.model.Result;
34 import hudson.model.Run;
35 import hudson.model.TaskListener;
36 import hudson.model.DependencyGraph.Dependency;
37 import hudson.tasks.Maven.ProjectWithMaven;
38 import hudson.triggers.Trigger;
39
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Set;
43
44 /**
45 * Common part between {@link MavenModule} and {@link MavenModuleSet}.
46 *
47 * @author Kohsuke Kawaguchi
48 */
49 public abstract class AbstractMavenProject<P extends AbstractProject<P,R>,R extends AbstractBuild<P,R>> extends AbstractProject<P,R>
50 implements ProjectWithMaven {
51
52 protected static class MavenModuleDependency extends Dependency {
53
54 public MavenModuleDependency(AbstractMavenProject<?,?> upstream,
55 AbstractProject<?,?> downstream) {
56 super(upstream, downstream);
57 }
58
59 @Override
60 public boolean shouldTriggerBuild(AbstractBuild build,
61 TaskListener listener, List<Action> actions) {
62 /**
63 * Schedules all the downstream builds.
64 * Returns immediately if build result doesn't meet the required level
65 * (as specified by {@link BuildTrigger}, or {@link Result#SUCCESS} if none).
66 *
67 * @param listener
68 * Where the progress reports go.
69 */
70 if (build.getResult().isWorseThan(Result.SUCCESS)) return false;
71 // trigger dependency builds
72 AbstractProject<?,?> downstreamProject = getDownstreamProject();
73 if(AbstractMavenBuild.debug)
74 listener.getLogger().println("Considering whether to trigger "+downstreamProject+" or not");
75
76 // if the downstream module depends on multiple modules,
77 // only trigger them when all the upstream dependencies are updated.
78 boolean trigger = true;
79
80 // Check to see if any of its upstream dependencies are already building or in queue.
81 AbstractMavenProject<?,?> parent = (AbstractMavenProject<?,?>) getUpstreamProject();
82 if (areUpstreamsBuilding(downstreamProject, parent)) {
83 if(AbstractMavenBuild.debug)
84 listener.getLogger().println(" -> No, because downstream has dependencies already building or in queue");
85 trigger = false;
86 }
87 // Check to see if any of its upstream dependencies are in this list of downstream projects.
88 else if (inDownstreamProjects(downstreamProject)) {
89 if(AbstractMavenBuild.debug)
90 listener.getLogger().println(" -> No, because downstream has dependencies in the downstream projects list");
91 trigger = false;
92 }
93 else {
94 AbstractBuild<?,?> dlb = downstreamProject.getLastBuild(); // can be null.
95 for (AbstractMavenProject up : Util.filter(downstreamProject.getUpstreamProjects(),AbstractMavenProject.class)) {
96 Run ulb;
97 if(up==parent) {
98 // the current build itself is not registered as lastSuccessfulBuild
99 // at this point, so we have to take that into account. ugly.
100 if(build.getResult()==null || !build.getResult().isWorseThan(Result.UNSTABLE))
101 ulb = build;
102 else
103 ulb = up.getLastSuccessfulBuild();
104 } else
105 ulb = up.getLastSuccessfulBuild();
106 if(ulb==null) {
107 // if no usable build is available from the upstream,
108 // then we have to wait at least until this build is ready
109 if(AbstractMavenBuild.debug)
110 listener.getLogger().println(" -> No, because another upstream "+up+" for "+downstreamProject+" has no successful build");
111 trigger = false;
112 break;
113 }
114
115 // if no record of the relationship in the last build
116 // is available, we'll just have to assume that the condition
117 // for the new build is met, or else no build will be fired forever.
118 if(dlb==null) continue;
119 int n = dlb.getUpstreamRelationship(up);
120 if(n==-1) continue;
121
122 assert ulb.getNumber()>=n;
123 }
124 }
125 return trigger;
126 }
127
128 /**
129 * Determines whether any of the upstream project are either
130 * building or in the queue.
131 *
132 * This means eventually there will be an automatic triggering of
133 * the given project (provided that all builds went smoothly.)
134 *
135 * @param downstreamProject
136 * The AbstractProject we want to build.
137 * @param excludeProject
138 * An AbstractProject to exclude - if we see this in the transitive
139 * dependencies, we're not going to bother checking to see if it's
140 * building. For example, pass the current parent project to be sure
141 * that it will be ignored when looking for building dependencies.
142 * @return
143 * True if any upstream projects are building or in queue, false otherwise.
144 */
145 @SuppressWarnings("rawtypes")
146 private boolean areUpstreamsBuilding(AbstractProject<?,?> downstreamProject,
147 AbstractProject<?,?> excludeProject) {
148 DependencyGraph graph = Jenkins.getInstance().getDependencyGraph();
149 Set<AbstractProject> tups = graph.getTransitiveUpstream(downstreamProject);
150 for (AbstractProject tup : tups) {
151 if(tup!=excludeProject && (tup.isBuilding() || tup.isInQueue()))
152 return true;
153 }
154 return false;
155 }
156
157 private boolean inDownstreamProjects(AbstractProject<?,?> downstreamProject) {
158 DependencyGraph graph = Jenkins.getInstance().getDependencyGraph();
159 Set<AbstractProject> tups = graph.getTransitiveUpstream(downstreamProject);
160
161 for (AbstractProject tup : tups) {
162 List<AbstractProject<?,?>> downstreamProjects = getUpstreamProject().getDownstreamProjects();
163 for (AbstractProject<?,?> dp : downstreamProjects) {
164 if(dp!=getUpstreamProject() && dp!=downstreamProject && dp==tup)
165 return true;
166 }
167 }
168 return false;
169 }
170 }
171
172 protected AbstractMavenProject(ItemGroup parent, String name) {
173 super(parent, name);
174 }
175
176 protected List<Action> createTransientActions() {
177 List<Action> r = super.createTransientActions();
178
179 // if we just pick up the project actions from the last build,
180 // and if the last build failed very early, then the reports that
181 // kick in later (like test results) won't be displayed.
182 // so pick up last successful build, too.
183 Set<Class> added = new HashSet<Class>();
184 addTransientActionsFromBuild(getLastBuild(),r,added);
185 addTransientActionsFromBuild(getLastSuccessfulBuild(),r,added);
186
187 for (Trigger<?> trigger : triggers)
188 r.addAll(trigger.getProjectActions());
189
190 return r;
191 }
192
193 /**
194 * @param collection
195 * Add the transient actions to this collection.
196 */
197 protected abstract void addTransientActionsFromBuild(R lastBuild, List<Action> collection, Set<Class> added);
198
199 }
200