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

1 /*
2 * The MIT License
3 *
4 * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Tom Huybrechts
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.matrix;
25
26 import hudson.EnvVars;
27 import hudson.Util;
28 import hudson.model.Action;
29 import hudson.model.Executor;
30 import hudson.model.InvisibleAction;
31 import hudson.model.Node;
32 import hudson.model.Queue.QueueAction;
33 import hudson.model.TaskListener;
34 import hudson.util.AlternativeUiTextProvider;
35 import hudson.util.DescribableList;
36 import hudson.model.AbstractBuild;
37 import hudson.model.Cause;
38 import hudson.model.CauseAction;
39 import hudson.model.DependencyGraph;
40 import hudson.model.Descriptor;
41 import jenkins.model.BuildDiscarder;
42 import jenkins.model.Jenkins;
43 import hudson.model.Item;
44 import hudson.model.ItemGroup;
45 import hudson.model.JDK;
46 import hudson.model.Label;
47 import hudson.model.ParametersAction;
48 import hudson.model.Project;
49 import hudson.model.SCMedItem;
50 import hudson.model.Queue.NonBlockingTask;
51 import hudson.model.Cause.LegacyCodeCause;
52 import hudson.scm.SCM;
53 import jenkins.scm.SCMCheckoutStrategy;
54 import hudson.tasks.BuildWrapper;
55 import hudson.tasks.Builder;
56 import hudson.tasks.LogRotator;
57 import hudson.tasks.Publisher;
58
59 import java.io.IOException;
60 import java.util.Collections;
61 import java.util.ArrayList;
62 import java.util.List;
63 import java.util.Map;
64
65 /**
66 * One configuration of {@link MatrixProject}.
67 *
68 * @author Kohsuke Kawaguchi
69 */
70 public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun> implements SCMedItem, NonBlockingTask {
71 /**
72 * The actual value combination.
73 */
74 private transient /*final*/ Combination combination;
75
76 /**
77 * Hash value of {@link #combination}. Cached for efficiency.
78 */
79 private transient String digestName;
80
81 public MatrixConfiguration(MatrixProject parent, Combination c) {
82 super(parent,c.toString());
83 setCombination(c);
84 }
85
86 @Override
87 public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
88 // directory name is not a name for us --- it's taken from the combination name
89 super.onLoad(parent, combination.toString());
90 }
91
92 @Override
93 public EnvVars getEnvironment(Node node, TaskListener listener) throws IOException, InterruptedException {
94 EnvVars env = super.getEnvironment(node, listener);
95
96 AxisList axes = getParent().getAxes();
97 for (Map.Entry<String,String> e : getCombination().entrySet()) {
98 Axis a = axes.find(e.getKey());
99 if (a!=null)
100 a.addBuildVariable(e.getValue(),env); // TODO: hijacking addBuildVariable but perhaps we need addEnvVar?
101 else
102 env.put(e.getKey(), e.getValue());
103 }
104
105 return env;
106 }
107
108 @Override
109 protected void updateTransientActions(){
110 // This method is exactly the same as in {@link #AbstractProject}.
111 // Enabling to call this method from MatrixProject is the only reason for overriding.
112 super.updateTransientActions();
113 }
114
115 @Override
116 public boolean isConcurrentBuild() {
117 return getParent().isConcurrentBuild();
118 }
119
120 @Override
121 public void setConcurrentBuild(boolean b) throws IOException {
122 throw new UnsupportedOperationException("The setting can be only changed at MatrixProject");
123 }
124
125 /**
126 * Used during loading to set the combination back.
127 */
128 /*package*/ void setCombination(Combination c) {
129 this.combination = c;
130 this.digestName = c.digest().substring(0,8);
131 }
132
133 /**
134 * Build numbers are always synchronized with the parent.
135 *
136 * <p>
137 * Computing this is bit tricky. Several considerations:
138 *
139 * <ol>
140 * <li>A new configuration build #N is started while the parent build #N is building,
141 * and when that happens we want to return N.
142 * <li>But the configuration build #N is done before the parent build #N finishes,
143 * and when that happens we want to return N+1 because that's going to be the next one.
144 * <li>Configuration builds might skip some numbers if the parent build is aborted
145 * before this configuration is built.
146 * <li>If nothing is building right now and the last build of the parent is #N,
147 * then we want to return N+1.
148 * </ol>
149 */
150 @Override
151 public int getNextBuildNumber() {
152 AbstractBuild<?,?> lb = getParent().getLastBuild();
153
154 while (lb!=null && lb.isBuilding()) {
155 lb = lb.getPreviousBuild();
156 }
157 if(lb==null) return 0;
158
159 int n=lb.getNumber()+1;
160
161 lb = getLastBuild();
162 if(lb!=null)
163 n = Math.max(n,lb.getNumber()+1);
164
165 return n;
166 }
167
168 @Override
169 public int assignBuildNumber() throws IOException {
170 int nb = getNextBuildNumber();
171 MatrixRun r = getLastBuild();
172 if(r!=null && r.getNumber()>=nb) // make sure we don't schedule the same build twice
173 throw new IllegalStateException("Build #"+nb+" is already completed");
174 return nb;
175 }
176
177 @Override
178 public String getDisplayName() {
179 return combination.toCompactString(getParent().getAxes());
180 }
181
182 @Override
183 public MatrixProject getParent() {
184 return (MatrixProject)super.getParent();
185 }
186
187 /**
188 * Get the actual combination of the axes values for this {@link MatrixConfiguration}
189 */
190 public Combination getCombination() {
191 return combination;
192 }
193
194 /**
195 * Since {@link MatrixConfiguration} is always invoked from {@link MatrixRun}
196 * once and just once, there's no point in having a quiet period.
197 */
198 @Override
199 public int getQuietPeriod() {
200 return 0;
201 }
202
203 /**
204 * Inherit the value from the parent.
205 */
206 @Override
207 public int getScmCheckoutRetryCount() {
208 return getParent().getScmCheckoutRetryCount();
209 }
210
211 /**
212 * Inherit the value from the parent.
213 */
214 @Override
215 public SCMCheckoutStrategy getScmCheckoutStrategy() {
216 return getParent().getScmCheckoutStrategy();
217 }
218
219 @Override
220 public boolean isConfigurable() {
221 return false;
222 }
223
224 @Override
225 protected Class<MatrixRun> getBuildClass() {
226 return MatrixRun.class;
227 }
228
229 @Override
230 protected MatrixRun newBuild() throws IOException {
231 List<Action> actions = Executor.currentExecutor().getCurrentWorkUnit().context.actions;
232 MatrixBuild lb = getParent().getLastBuild();
233 for (Action a : actions) {
234 if (a instanceof ParentBuildAction) {
235 lb = ((ParentBuildAction) a).parent;
236 }
237 }
238
239 // for every MatrixRun there should be a parent MatrixBuild
240 MatrixRun lastBuild = new MatrixRun(this, lb.getTimestamp());
241
242 lastBuild.number = lb.getNumber();
243
244 builds.put(lastBuild);
245 return lastBuild;
246 }
247
248 @Override
249 protected void buildDependencyGraph(DependencyGraph graph) {
250 }
251
252 @Override
253 public MatrixConfiguration asProject() {
254 return this;
255 }
256
257 @Override
258 public Label getAssignedLabel() {
259 // combine all the label axes by &&.
260 String expr;
261 String exprSlave = Util.join(combination.values(getParent().getAxes().subList(LabelAxis.class)), "&&");
262 String exprLabel = Util.join(combination.values(getParent().getAxes().subList(LabelExpAxis.class)), "&&");
263 if(!exprSlave.equals("") && !exprLabel.equals("")){
264 expr = exprSlave + "&&" + exprLabel;
265 } else{
266 expr = (exprSlave.equals("")) ? exprLabel : exprSlave;
267 }
268 return Jenkins.getInstance().getLabel(Util.fixEmpty(expr));
269 }
270
271 @Override
272 public String getPronoun() {
273 return AlternativeUiTextProvider.get(PRONOUN, this, Messages.MatrixConfiguration_Pronoun());
274 }
275
276 @Override
277 public JDK getJDK() {
278 return Jenkins.getInstance().getJDK(combination.get("jdk"));
279 }
280
281 //
282 // inherit build setting from the parent project
283 //
284 @Override
285 public List<Builder> getBuilders() {
286 return getParent().getBuilders();
287 }
288
289 @Override
290 public Map<Descriptor<Publisher>, Publisher> getPublishers() {
291 return getParent().getPublishers();
292 }
293
294 @Override
295 public DescribableList<Builder, Descriptor<Builder>> getBuildersList() {
296 return getParent().getBuildersList();
297 }
298
299 @Override
300 public DescribableList<Publisher, Descriptor<Publisher>> getPublishersList() {
301 return getParent().getPublishersList();
302 }
303
304 @Override
305 public Map<Descriptor<BuildWrapper>, BuildWrapper> getBuildWrappers() {
306 return getParent().getBuildWrappers();
307 }
308
309 @Override
310 public DescribableList<BuildWrapper, Descriptor<BuildWrapper>> getBuildWrappersList() {
311 return getParent().getBuildWrappersList();
312 }
313
314 @Override
315 public Publisher getPublisher(Descriptor<Publisher> descriptor) {
316 return getParent().getPublisher(descriptor);
317 }
318
319 @Override
320 public BuildDiscarder getBuildDiscarder() {
321 // TODO: LinkedLogRotator doesn't work very well in the face of pluggable BuildDiscarder but I don't know what to do
322 BuildDiscarder bd = getParent().getBuildDiscarder();
323 if (bd instanceof LogRotator) {
324 LogRotator lr = (LogRotator) bd;
325 return new LinkedLogRotator(lr.getArtifactDaysToKeep(),lr.getArtifactNumToKeep());
326 }
327 return new LinkedLogRotator();
328 }
329
330 @Override
331 public SCM getScm() {
332 return getParent().getScm();
333 }
334
335 /*package*/ String getDigestName() {
336 return digestName;
337 }
338
339 /**
340 * JDK cannot be set on {@link MatrixConfiguration} because
341 * it's controlled by {@link MatrixProject}.
342 * @deprecated
343 * Not supported.
344 */
345 @Override
346 public void setJDK(JDK jdk) throws IOException {
347 throw new UnsupportedOperationException();
348 }
349
350 /**
351 * @deprecated
352 * Value is controlled by {@link MatrixProject}.
353 */
354 @Override
355 public void setBuildDiscarder(BuildDiscarder logRotator) {
356 throw new UnsupportedOperationException();
357 }
358
359 /**
360 * Returns true if this configuration is a configuration
361 * currently in use today (as opposed to the ones that are
362 * there only to keep the past record.)
363 *
364 * @see MatrixProject#getActiveConfigurations()
365 */
366 public boolean isActiveConfiguration() {
367 return getParent().getActiveConfigurations().contains(this);
368 }
369
370 /**
371 * On Cygwin, path names cannot be longer than 256 chars.
372 * See http://cygwin.com/ml/cygwin/2005-04/msg00395.html and
373 * http://www.nabble.com/Windows-Filename-too-long-errors-t3161089.html for
374 * the background of this issue. Setting this flag to true would
375 * cause Jenkins to use cryptic but short path name, giving more room for
376 * jobs to use longer path names.
377 */
378 public static boolean useShortWorkspaceName = Boolean.getBoolean(MatrixConfiguration.class.getName()+".useShortWorkspaceName");
379
380 /**
381 * @deprecated
382 * Use {@link #scheduleBuild(ParametersAction, Cause)}. Since 1.283
383 */
384 public boolean scheduleBuild(ParametersAction parameters) {
385 return scheduleBuild(parameters, new LegacyCodeCause());
386 }
387
388 /** Starts the build with the ParametersAction that are passed in.
389 *
390 * @param parameters
391 * Can be null.
392 * @deprecated
393 * Use {@link #scheduleBuild(List<? extends Action>, Cause)}. Since 1.480
394 */
395 public boolean scheduleBuild(ParametersAction parameters, Cause c) {
396
397 return scheduleBuild(Collections.singletonList(parameters), c);
398 }
399 /**
400 * Starts the build with the actions that are passed in.
401 *
402 * @param actions Can be null.
403 * @param cause Reason for starting the build
404 */
405 public boolean scheduleBuild(List<? extends Action> actions, Cause c) {
406 List<Action> allActions = new ArrayList<Action>();
407
408 if(actions != null)
409 allActions.addAll(actions);
410
411 allActions.add(new ParentBuildAction());
412 allActions.add(new CauseAction(c));
413
414 return Jenkins.getInstance().getQueue().schedule(this, getQuietPeriod(), allActions )!=null;
415 }
416
417 /**
418 *
419 */
420 public static class ParentBuildAction extends InvisibleAction implements QueueAction {
421 public transient MatrixBuild parent = (MatrixBuild)Executor.currentExecutor().getCurrentExecutable();
422 public boolean shouldSchedule(List<Action> actions) {
423 return true;
424 }
425 }
426 }
427