Project.java 9.5 KB
Newer Older
K
kohsuke 已提交
1 2 3
/*
 * The MIT License
 * 
4 5
 * Copyright (c) 2004-2011, Sun Microsystems, Inc., Kohsuke Kawaguchi,
 * Jorg Heymans, Stephen Connolly, Tom Huybrechts
K
kohsuke 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 
 * 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.
 */
K
kohsuke 已提交
25 26
package hudson.model;

27
import hudson.Util;
K
kohsuke 已提交
28
import hudson.model.Descriptor.FormException;
29
import hudson.model.queue.QueueTaskFuture;
30
import hudson.scm.SCM;
K
kohsuke 已提交
31
import hudson.tasks.BuildStep;
K
kohsuke 已提交
32 33
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrappers;
K
kohsuke 已提交
34 35 36
import hudson.tasks.Builder;
import hudson.tasks.Fingerprinter;
import hudson.tasks.Publisher;
37 38 39
import hudson.tasks.Maven;
import hudson.tasks.Maven.ProjectWithMaven;
import hudson.tasks.Maven.MavenInstallation;
40
import hudson.triggers.SCMTrigger;
K
kohsuke 已提交
41
import hudson.triggers.Trigger;
42 43
import hudson.util.DescribableList;
import net.sf.json.JSONObject;
K
kohsuke 已提交
44 45 46 47 48
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import javax.servlet.ServletException;
import java.io.IOException;
49
import java.util.Collection;
K
kohsuke 已提交
50 51 52 53
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
K
Kohsuke Kawaguchi 已提交
54
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
55 56 57
import java.util.logging.Level;
import java.util.logging.Logger;

58
import jenkins.triggers.SCMTriggerItem;
K
kohsuke 已提交
59 60 61 62 63 64

/**
 * Buildable software project.
 *
 * @author Kohsuke Kawaguchi
 */
65
public abstract class Project<P extends Project<P,B>,B extends Build<P,B>>
66
    extends AbstractProject<P,B> implements SCMTriggerItem, Saveable, ProjectWithMaven, BuildableItemWithBuildWrappers {
K
kohsuke 已提交
67 68 69 70

    /**
     * List of active {@link Builder}s configured for this project.
     */
K
Kohsuke Kawaguchi 已提交
71 72 73
    private volatile DescribableList<Builder,Descriptor<Builder>> builders;
    private static final AtomicReferenceFieldUpdater<Project,DescribableList> buildersSetter
            = AtomicReferenceFieldUpdater.newUpdater(Project.class,DescribableList.class,"builders");
K
kohsuke 已提交
74 75 76 77

    /**
     * List of active {@link Publisher}s configured for this project.
     */
K
Kohsuke Kawaguchi 已提交
78 79 80
    private volatile DescribableList<Publisher,Descriptor<Publisher>> publishers;
    private static final AtomicReferenceFieldUpdater<Project,DescribableList> publishersSetter
            = AtomicReferenceFieldUpdater.newUpdater(Project.class,DescribableList.class,"publishers");
K
kohsuke 已提交
81

82 83 84
    /**
     * List of active {@link BuildWrapper}s configured for this project.
     */
K
Kohsuke Kawaguchi 已提交
85 86 87
    private volatile DescribableList<BuildWrapper,Descriptor<BuildWrapper>> buildWrappers;
    private static final AtomicReferenceFieldUpdater<Project,DescribableList> buildWrappersSetter
            = AtomicReferenceFieldUpdater.newUpdater(Project.class,DescribableList.class,"buildWrappers");
88

K
kohsuke 已提交
89 90 91
    /**
     * Creates a new project.
     */
92
    public Project(ItemGroup parent,String name) {
K
kohsuke 已提交
93 94 95
        super(parent,name);
    }

96
    @Override
97 98
    public void onLoad(ItemGroup<? extends Item> parent, String name) throws IOException {
        super.onLoad(parent, name);
99 100 101
        getBuildersList().setOwner(this);
        getPublishersList().setOwner(this);
        getBuildWrappersList().setOwner(this);
K
kohsuke 已提交
102 103
    }

104 105 106 107
    public AbstractProject<?, ?> asProject() {
        return this;
    }

108 109 110 111 112 113 114 115
    @Override public Item asItem() {
        return this;
    }

    @Override public QueueTaskFuture<?> scheduleBuild2(int quietPeriod, Action... actions) {
        return scheduleBuild2(quietPeriod, null, actions);
    }

116 117 118 119 120 121
    @Override public SCMTrigger getSCMTrigger() {
        return getTrigger(SCMTrigger.class);
    }

    @Override public Collection<? extends SCM> getSCMs() {
        return SCMTriggerItem.SCMTriggerItems.resolveMultiScmIfConfigured(getScm());
122 123
    }

124
    public List<Builder> getBuilders() {
125
        return getBuildersList().toList();
126 127
    }

128 129 130 131 132
    /**
     * @deprecated as of 1.463
     *      We will be soon removing the restriction that only one instance of publisher is allowed per type.
     *      Use {@link #getPublishersList()} instead.
     */
133
    public Map<Descriptor<Publisher>,Publisher> getPublishers() {
134
        return getPublishersList().toMap();
135 136
    }

K
Kohsuke Kawaguchi 已提交
137
    public DescribableList<Builder,Descriptor<Builder>> getBuildersList() {
138
        if (builders == null) {
K
Kohsuke Kawaguchi 已提交
139
            buildersSetter.compareAndSet(this,null,new DescribableList<Builder,Descriptor<Builder>>(this));
140
        }
141 142 143
        return builders;
    }
    
K
Kohsuke Kawaguchi 已提交
144
    public DescribableList<Publisher,Descriptor<Publisher>> getPublishersList() {
145
        if (publishers == null) {
K
Kohsuke Kawaguchi 已提交
146
            publishersSetter.compareAndSet(this,null,new DescribableList<Publisher,Descriptor<Publisher>>(this));
147
        }
148
        return publishers;
K
kohsuke 已提交
149 150
    }

151
    public Map<Descriptor<BuildWrapper>,BuildWrapper> getBuildWrappers() {
152
        return getBuildWrappersList().toMap();
153 154
    }

K
Kohsuke Kawaguchi 已提交
155
    public DescribableList<BuildWrapper, Descriptor<BuildWrapper>> getBuildWrappersList() {
156
        if (buildWrappers == null) {
K
Kohsuke Kawaguchi 已提交
157
            buildWrappersSetter.compareAndSet(this,null,new DescribableList<BuildWrapper,Descriptor<BuildWrapper>>(this));
158
        }
159 160 161
        return buildWrappers;
    }

162 163 164
    @Override
    protected Set<ResourceActivity> getResourceActivities() {
        final Set<ResourceActivity> activities = new HashSet<ResourceActivity>();
K
kohsuke 已提交
165

166
        activities.addAll(super.getResourceActivities());
167 168 169
        activities.addAll(Util.filter(getBuildersList(),ResourceActivity.class));
        activities.addAll(Util.filter(getPublishersList(),ResourceActivity.class));
        activities.addAll(Util.filter(getBuildWrappersList(),ResourceActivity.class));
K
kohsuke 已提交
170

171 172 173
        return activities;
    }

174 175
    /**
     * Adds a new {@link BuildStep} to this {@link Project} and saves the configuration.
176 177 178
     *
     * @deprecated as of 1.290
     *      Use {@code getPublishersList().add(x)}
179
     */
180
    public void addPublisher(Publisher buildStep) throws IOException {
181
        getPublishersList().add(buildStep);
182 183 184 185
    }

    /**
     * Removes a publisher from this project, if it's active.
186 187 188
     *
     * @deprecated as of 1.290
     *      Use {@code getPublishersList().remove(x)}
189
     */
190
    public void removePublisher(Descriptor<Publisher> descriptor) throws IOException {
191
        getPublishersList().remove(descriptor);
192 193
    }

194
    public Publisher getPublisher(Descriptor<Publisher> descriptor) {
195
        for (Publisher p : getPublishersList()) {
196 197 198 199 200 201
            if(p.getDescriptor()==descriptor)
                return p;
        }
        return null;
    }

202 203
    @Override protected void buildDependencyGraph(DependencyGraph graph) {
        super.buildDependencyGraph(graph);
204 205 206
        getPublishersList().buildDependencyGraph(this,graph);
        getBuildersList().buildDependencyGraph(this,graph);
        getBuildWrappersList().buildDependencyGraph(this,graph);
K
kohsuke 已提交
207 208
    }

209
    @Override
K
kohsuke 已提交
210
    public boolean isFingerprintConfigured() {
K
kohsuke 已提交
211
        return getPublishersList().get(Fingerprinter.class)!=null;
K
kohsuke 已提交
212 213
    }

214
    public MavenInstallation inferMavenInstallation() {
K
kohsuke 已提交
215 216
        Maven m = getBuildersList().get(Maven.class);
        if (m!=null)    return m.getMaven();
217 218
        return null;
    }
K
kohsuke 已提交
219

K
kohsuke 已提交
220
//
K
kohsuke 已提交
221 222 223 224
//
// actions
//
//
225 226 227
    @Override
    protected void submit( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException {
        super.submit(req,rsp);
K
kohsuke 已提交
228

K
kohsuke 已提交
229
        JSONObject json = req.getSubmittedForm();
K
kohsuke 已提交
230

231 232 233
        getBuildWrappersList().rebuild(req,json, BuildWrappers.getFor(this));
        getBuildersList().rebuildHetero(req,json, Builder.all(), "builder");
        getPublishersList().rebuildHetero(req, json, Publisher.all(), "publisher");
234 235
    }

236
    @Override
237 238 239
    protected List<Action> createTransientActions() {
        List<Action> r = super.createTransientActions();

240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
        for (BuildStep step : getBuildersList()) {
            try {
                r.addAll(step.getProjectActions(this));
            } catch (Exception e) {
                LOGGER.log(Level.SEVERE, "Error loading build step.", e);
            }
        }
        for (BuildStep step : getPublishersList()) {
            try {
                r.addAll(step.getProjectActions(this));
            } catch (Exception e) {
                LOGGER.log(Level.SEVERE, "Error loading publisher.", e);
            }
        }
        for (BuildWrapper step : getBuildWrappers().values()) {
            try {
                r.addAll(step.getProjectActions(this));
            } catch (Exception e) {
                LOGGER.log(Level.SEVERE, "Error loading build wrapper.", e);
            }
        }
        for (Trigger trigger : triggers()) {
            try {
                r.addAll(trigger.getProjectActions());
            } catch (Exception e) {
                LOGGER.log(Level.SEVERE, "Error loading trigger.", e);
            }
        }
268 269

        return r;
K
kohsuke 已提交
270
    }
271 272

    private static final Logger LOGGER = Logger.getLogger(Project.class.getName());
273
}