/*
* The MIT License
*
* Copyright 2014 Jesse Glick.
*
* 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 jenkins.triggers;
import hudson.model.Action;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.TaskListener;
import hudson.model.queue.QueueTaskFuture;
import hudson.scm.NullSCM;
import hudson.scm.PollingResult;
import hudson.scm.SCM;
import hudson.triggers.SCMTrigger;
import java.util.Collection;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import jenkins.model.ParameterizedJobMixIn;
import jenkins.scm.SCMDecisionHandler;
/**
* The item type accepted by {@link SCMTrigger}.
* @since 1.568
*/
public interface SCMTriggerItem {
/** Should be {@code this}. */
Item asItem();
/** @see Job#getNextBuildNumber */
int getNextBuildNumber();
/** @see jenkins.model.ParameterizedJobMixIn.ParameterizedJob#getQuietPeriod */
int getQuietPeriod();
/** @see ParameterizedJobMixIn#scheduleBuild2 */
@CheckForNull QueueTaskFuture<?> scheduleBuild2(int quietPeriod, Action... actions);
/**
* Checks if there is any update in SCM.
*
* <p>
* The implementation is responsible for ensuring mutual exclusion between polling and builds
* if necessary.
* <p>
* The implementation is responsible for checking the {@link SCMDecisionHandler} before proceeding
* with the actual polling.
*/
@Nonnull PollingResult poll(@Nonnull TaskListener listener);
@CheckForNull SCMTrigger getSCMTrigger();
/**
* Obtains all active SCMs.
* May be used for informational purposes, or to determine whether to initiate polling.
* @return a possibly empty collection
*/
@Nonnull Collection<? extends SCM> getSCMs();
/**
* Utilities.
*/
class SCMTriggerItems {
/**
* See whether an item can be coerced to {@link SCMTriggerItem}.
* @param item any item
* @return itself, if a {@link SCMTriggerItem}, or an adapter, if an {@link hudson.model.SCMedItem}, else null
*/
@SuppressWarnings("deprecation")
public static @CheckForNull SCMTriggerItem asSCMTriggerItem(Item item) {
if (item instanceof SCMTriggerItem) {
return (SCMTriggerItem) item;
} else if (item instanceof hudson.model.SCMedItem) {
return new Bridge((hudson.model.SCMedItem) item);
} else {
return null;
}
}
private static final class Bridge implements SCMTriggerItem {
private final hudson.model.SCMedItem delegate;
Bridge(hudson.model.SCMedItem delegate) {
this.delegate = delegate;
}
@Override public Item asItem() {
return delegate.asProject();
}
@Override public int getNextBuildNumber() {
return delegate.asProject().getNextBuildNumber();
}
@Override public int getQuietPeriod() {
return delegate.asProject().getQuietPeriod();
}
@Override public QueueTaskFuture<?> scheduleBuild2(int quietPeriod, Action... actions) {
return delegate.asProject().scheduleBuild2(quietPeriod, null, actions);
}
@Override public PollingResult poll(TaskListener listener) {
SCMDecisionHandler veto = SCMDecisionHandler.firstShouldPollVeto(asItem());
if (veto != null && !veto.shouldPoll(asItem())) {
listener.getLogger().println(Messages.SCMTriggerItem_PollingVetoed(veto));
return PollingResult.NO_CHANGES;
}
return delegate.poll(listener);
}
@Override public SCMTrigger getSCMTrigger() {
return delegate.asProject().getTrigger(SCMTrigger.class);
}
@Override public Collection<? extends SCM> getSCMs() {
return resolveMultiScmIfConfigured(delegate.asProject().getScm());
}
}
public static @Nonnull Collection<? extends SCM> resolveMultiScmIfConfigured(@CheckForNull SCM scm) {
if (scm == null || scm instanceof NullSCM) {
return Collections.emptySet();
} else if (scm.getClass().getName().equals("org.jenkinsci.plugins.multiplescms.MultiSCM")) {
try {
return (Collection<? extends SCM>) scm.getClass().getMethod("getConfiguredSCMs").invoke(scm);
} catch (Exception x) {
Logger.getLogger(SCMTriggerItem.class.getName()).log(Level.WARNING, null, x);
return Collections.singleton(scm);
}
} else {
return Collections.singleton(scm);
}
}
private SCMTriggerItems() {}
}
}