PageRenderTime 18ms CodeModel.GetById 2ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/matrix/MatrixConfiguration.java

http://github.com/hudson/hudson
Java | 336 lines | 180 code | 44 blank | 112 comment | 7 complexity | 37cb1bfff84f99b380a21dc40c28a485 MD5 | raw file
  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 */
 24package hudson.matrix;
 25
 26import hudson.Util;
 27import hudson.security.ACL;
 28import hudson.util.DescribableList;
 29import hudson.model.AbstractBuild;
 30import hudson.model.Cause;
 31import hudson.model.CauseAction;
 32import hudson.model.DependencyGraph;
 33import hudson.model.Descriptor;
 34import hudson.model.Hudson;
 35import hudson.model.Item;
 36import hudson.model.ItemGroup;
 37import hudson.model.JDK;
 38import hudson.model.Label;
 39import hudson.model.ParametersAction;
 40import hudson.model.Project;
 41import hudson.model.SCMedItem;
 42import hudson.model.Queue.NonBlockingTask;
 43import hudson.model.Cause.LegacyCodeCause;
 44import hudson.scm.SCM;
 45import hudson.tasks.BuildWrapper;
 46import hudson.tasks.Builder;
 47import hudson.tasks.LogRotator;
 48import hudson.tasks.Publisher;
 49
 50import java.io.IOException;
 51import java.util.List;
 52import java.util.Map;
 53
 54/**
 55 * One configuration of {@link MatrixProject}.
 56 *
 57 * @author Kohsuke Kawaguchi
 58 */
 59public class MatrixConfiguration extends Project<MatrixConfiguration,MatrixRun> implements SCMedItem, NonBlockingTask {
 60    /**
 61     * The actual value combination.
 62     */
 63    private transient /*final*/ Combination combination;
 64
 65    /**
 66     * Hash value of {@link #combination}. Cached for efficiency.
 67     */
 68    private transient String digestName;
 69
 70    public MatrixConfiguration(MatrixProject parent, Combination c) {
 71        super(parent,c.toString());
 72        setCombination(c);
 73        updateTransientActions();
 74    }
 75
 76    @Override
 77    public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
 78        // directory name is not a name for us --- it's taken from the combination name
 79        super.onLoad(parent, combination.toString());
 80    }
 81
 82    /**
 83     * Used during loading to set the combination back.
 84     */
 85    /*package*/ void setCombination(Combination c) {
 86        this.combination = c;
 87        this.digestName = c.digest().substring(0,8);
 88    }
 89
 90    /**
 91     * Build numbers are always synchronized with the parent.
 92     *
 93     * <p>
 94     * Computing this is bit tricky. Several considerations:
 95     *
 96     * <ol>
 97     * <li>A new configuration build #N is started while the parent build #N is building,
 98     *     and when that happens we want to return N.
 99     * <li>But the configuration build #N is done before the parent build #N finishes,
100     *     and when that happens we want to return N+1 because that's going to be the next one.
101     * <li>Configuration builds might skip some numbers if the parent build is aborted
102     *     before this configuration is built.
103     * <li>If nothing is building right now and the last build of the parent is #N,
104     *     then we want to return N+1.
105     * </ol>
106     */
107    @Override
108    public int getNextBuildNumber() {
109        AbstractBuild lb = getParent().getLastBuild();
110        if(lb==null)    return 0;
111        
112
113        int n=lb.getNumber();
114        if(!lb.isBuilding())    n++;
115
116        lb = getLastBuild();
117        if(lb!=null)
118            n = Math.max(n,lb.getNumber()+1);
119
120        return n;
121    }
122
123    @Override
124    public int assignBuildNumber() throws IOException {
125        int nb = getNextBuildNumber();
126        MatrixRun r = getLastBuild();
127        if(r!=null && r.getNumber()>=nb) // make sure we don't schedule the same build twice
128            throw new IllegalStateException("Build #"+nb+" is already completed");
129        return nb;
130    }
131
132    @Override
133    public String getDisplayName() {
134        return combination.toCompactString(getParent().getAxes());
135    }
136
137    @Override
138    public MatrixProject getParent() {
139        return (MatrixProject)super.getParent();
140    }
141
142    /**
143     * Get the actual combination of the axes values for this {@link MatrixConfiguration}
144     */
145    public Combination getCombination() {
146        return combination;
147    }
148
149    /**
150     * Since {@link MatrixConfiguration} is always invoked from {@link MatrixRun}
151     * once and just once, there's no point in having a quiet period.
152     */
153    @Override
154    public int getQuietPeriod() {
155        return 0;
156    }
157
158    /**
159     * Inherit the value from the parent.
160     */
161    @Override
162    public int getScmCheckoutRetryCount() {
163        return getParent().getScmCheckoutRetryCount();
164    }
165
166    @Override
167    public boolean isConfigurable() {
168        return false;
169    }
170
171    @Override
172    protected Class<MatrixRun> getBuildClass() {
173        return MatrixRun.class;
174    }
175
176    @Override
177    protected MatrixRun newBuild() throws IOException {
178        // for every MatrixRun there should be a parent MatrixBuild
179        MatrixBuild lb = getParent().getLastBuild();
180        MatrixRun lastBuild = new MatrixRun(this, lb.getTimestamp());
181        lastBuild.number = lb.getNumber();
182
183        builds.put(lastBuild);
184        return lastBuild;
185    }
186
187    @Override
188    protected void buildDependencyGraph(DependencyGraph graph) {
189    }
190
191    @Override
192    public MatrixConfiguration asProject() {
193        return this;
194    }
195
196    @Override
197    public Label getAssignedLabel() {
198        // combine all the label axes by &&.
199        String expr = Util.join(combination.values(getParent().getAxes().subList(LabelAxis.class)), "&&");
200        return Hudson.getInstance().getLabel(Util.fixEmpty(expr));
201    }
202
203    @Override
204    public String getPronoun() {
205        return Messages.MatrixConfiguration_Pronoun();
206    }
207
208    @Override
209    public JDK getJDK() {
210        return Hudson.getInstance().getJDK(combination.get("jdk"));
211    }
212
213//
214// inherit build setting from the parent project
215//
216    @Override
217    public List<Builder> getBuilders() {
218        return getParent().getBuilders();
219    }
220
221    @Override
222    public Map<Descriptor<Publisher>, Publisher> getPublishers() {
223        return getParent().getPublishers();
224    }
225
226    @Override
227    public DescribableList<Builder, Descriptor<Builder>> getBuildersList() {
228        return getParent().getBuildersList();
229    }
230
231    @Override
232    public DescribableList<Publisher, Descriptor<Publisher>> getPublishersList() {
233        return getParent().getPublishersList();
234    }
235
236    @Override
237    public Map<Descriptor<BuildWrapper>, BuildWrapper> getBuildWrappers() {
238        return getParent().getBuildWrappers();
239    }
240
241    /**
242     * @since 2.1.0
243     */
244    @Override
245    public DescribableList<BuildWrapper, Descriptor<BuildWrapper>> getBuildWrappersList() {
246        return getParent().getBuildWrappersList();
247    }
248
249    @Override
250    public Publisher getPublisher(Descriptor<Publisher> descriptor) {
251        return getParent().getPublisher(descriptor);
252    }
253
254    @Override
255    public LogRotator getLogRotator() {
256        LogRotator lr = getParent().getLogRotator();
257        return new LinkedLogRotator(lr != null ? lr.getArtifactDaysToKeep() : -1,
258                                    lr != null ? lr.getArtifactNumToKeep() : -1);
259    }
260
261    @Override
262    public SCM getScm() {
263        return getParent().getScm();
264    }
265
266    /*package*/ String getDigestName() {
267        return digestName;
268    }
269
270    /**
271     * JDK cannot be set on {@link MatrixConfiguration} because
272     * it's controlled by {@link MatrixProject}.
273     * @deprecated
274     *      Not supported.
275     */
276    @Override
277    public void setJDK(JDK jdk) throws IOException {
278        throw new UnsupportedOperationException();
279    }
280
281    /**
282     * @deprecated
283     *      Value is controlled by {@link MatrixProject}.
284     */
285    @Override
286    public void setLogRotator(LogRotator logRotator) {
287        //TODO fins the reason
288        //throw new UnsupportedOperationException();
289    }
290
291    /**
292     * Returns true if this configuration is a configuration
293     * currently in use today (as opposed to the ones that are
294     * there only to keep the past record.) 
295     *
296     * @see MatrixProject#getActiveConfigurations()
297     */
298    public boolean isActiveConfiguration() {
299        return getParent().getActiveConfigurations().contains(this);
300    }
301
302    /**
303     * @since 2.1.0
304     */
305    @Override
306    public ACL getACL() {
307        return getParent().getACL();
308    }
309
310    /**
311     * On Cygwin, path names cannot be longer than 256 chars.
312     * See http://cygwin.com/ml/cygwin/2005-04/msg00395.html and
313     * http://www.nabble.com/Windows-Filename-too-long-errors-t3161089.html for
314     * the background of this issue. Setting this flag to true would
315     * cause Hudson to use cryptic but short path name, giving more room for
316     * jobs to use longer path names.
317     */
318    public static boolean useShortWorkspaceName = Boolean.getBoolean(MatrixConfiguration.class.getName()+".useShortWorkspaceName");
319
320	/**
321	 * @deprecated
322	 *    Use {@link #scheduleBuild(ParametersAction, Cause)}.  Since 1.283
323	 */
324    public boolean scheduleBuild(ParametersAction parameters) {
325    	return scheduleBuild(parameters, new LegacyCodeCause());
326    }
327
328    /**
329     *
330     * @param parameters
331     *      Can be null.
332     */
333    public boolean scheduleBuild(ParametersAction parameters, Cause c) {
334        return Hudson.getInstance().getQueue().schedule(this, getQuietPeriod(), parameters, new CauseAction(c))!=null;
335    }
336}