Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[JENKINS-43507] Refactoring to enable traits
  • Loading branch information
stephenc committed May 4, 2017
1 parent 5fe2558 commit 37da6da
Show file tree
Hide file tree
Showing 7 changed files with 493 additions and 0 deletions.
56 changes: 56 additions & 0 deletions src/main/java/jenkins/scm/api/SCMBuilder.java
@@ -0,0 +1,56 @@
package jenkins.scm.api;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.TaskListener;
import hudson.scm.SCM;
import hudson.scm.SCMDescriptor;
import java.util.Arrays;
import java.util.Collection;
import jenkins.model.Jenkins;
import jenkins.scm.api.trait.SCMSourceTrait;

public abstract class SCMBuilder<B extends SCMBuilder<B,S>,S extends SCM> {

private final Class<S> clazz;
private final SCMHead head;
private final SCMRevision revision;

public SCMBuilder(Class<S> clazz, @NonNull SCMHead head, @CheckForNull SCMRevision revision) {
this.clazz = clazz;
this.head = head;
this.revision = revision;
}

public SCMHead getHead() {
return head;
}

public SCMRevision getRevision() {
return revision;
}

public abstract S build();

@SuppressWarnings("unchecked")
public B withTrait(@NonNull SCMSourceTrait trait) {
trait.applyToSCM((B)this);
return (B) this;
}

public B withTraits(@NonNull SCMSourceTrait... traits) {
return withTraits(Arrays.asList(traits));
}

@SuppressWarnings("unchecked")
public B withTraits(@NonNull Collection<SCMSourceTrait> traits) {
for (SCMSourceTrait trait : traits) {
withTrait(trait);
}
return (B) this;
}

public SCMDescriptor<S> getSCMDescriptor() {
return (SCMDescriptor<S>)Jenkins.getActiveInstance().getDescriptorOrDie(clazz);
}
}
10 changes: 10 additions & 0 deletions src/main/java/jenkins/scm/api/trait/SCMHeadFilter.java
@@ -0,0 +1,10 @@
package jenkins.scm.api.trait;

import edu.umd.cs.findbugs.annotations.NonNull;
import jenkins.scm.api.SCMHead;

public abstract class SCMHeadFilter {

public abstract boolean isExcluded(@NonNull SCMSourceRequest request, @NonNull SCMHead head);

}
126 changes: 126 additions & 0 deletions src/main/java/jenkins/scm/api/trait/SCMSourceRequest.java
@@ -0,0 +1,126 @@
/*
* The MIT License
*
* Copyright (c) 2017 CloudBees, Inc.
*
* 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.scm.api.trait;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.TaskListener;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import jenkins.scm.api.SCMHead;
import jenkins.scm.api.SCMHeadEvent;
import jenkins.scm.api.SCMHeadObserver;
import jenkins.scm.api.SCMRevision;
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.SCMSourceCriteria;
import jenkins.scm.api.mixin.SCMHeadMixin;

/**
* Represents the context of an individual request for a call to
* {@link SCMSource#retrieve(SCMSourceCriteria, SCMHeadObserver, SCMHeadEvent, TaskListener)} or an equivalent method.
*
* @since 2.2.0
*/
public abstract class SCMSourceRequest implements Closeable {

private static final Set<Class<? extends SCMHeadMixin>> STANDARD_MIXINS =
Collections.<Class<? extends SCMHeadMixin>>singleton(SCMHeadMixin.class);
private final List<SCMHeadFilter> filters;

private final List<SCMSourceCriteria> criteria;

private final TaskListener listener;

private final SCMHeadObserver observer;

private final Set<SCMHead> observerIncludes;

protected SCMSourceRequest(SCMSourceRequestBuilder<?,?> builder) {
this.filters = builder.filters();
this.criteria = builder.criteria().isEmpty()
? Collections.<SCMSourceCriteria>emptyList()
: Collections.unmodifiableList(new ArrayList<SCMSourceCriteria>(builder.criteria()));
this.observer = builder.observer();
this.observerIncludes = observer.getIncludes();
this.listener = builder.listener();
}

public boolean isExcluded(SCMHead head) {
if (observerIncludes != null && !observerIncludes.contains(head)) {
return true;
}
if (filters.isEmpty()) {
return false;
}
for (SCMHeadFilter filter : filters) {
if (filter.isExcluded(this, head)) {
return true;
}
}
return false;
}

@NonNull
public List<SCMSourceCriteria> getCriteria() {
return criteria;
}

public boolean hasNoCriteria() {
return criteria.isEmpty();
}

public boolean meetsCriteria(SCMSourceCriteria.Probe probe) throws IOException {
for (SCMSourceCriteria c : criteria) {
if (!c.isHead(probe, listener)) {
return false;
}
}
return true;
}

public void criteriaMet(SCMHead head, SCMRevision revision) throws IOException, InterruptedException {
observer.observe(head, revision);
}

public boolean isComplete() {
return !observer.isObserving();
}

public TaskListener listener() {
return listener;
}

/**
* {@inheritDoc}
*/
@Override
public void close() throws IOException {
// default to no-op but allow subclasses to store persistent connections in the request and clean up after
}
}
112 changes: 112 additions & 0 deletions src/main/java/jenkins/scm/api/trait/SCMSourceRequestBuilder.java
@@ -0,0 +1,112 @@
/*
* The MIT License
*
* Copyright (c) 2017 CloudBees, Inc.
*
* 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.scm.api.trait;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.model.TaskListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import jenkins.scm.api.SCMHeadObserver;
import jenkins.scm.api.SCMSource;
import jenkins.scm.api.SCMSourceCriteria;

public abstract class SCMSourceRequestBuilder<B extends SCMSourceRequestBuilder<B,R>,R extends SCMSourceRequest> {
@NonNull
private final List<SCMSourceCriteria> criteria = new ArrayList<SCMSourceCriteria>();
@NonNull
private final List<SCMHeadFilter> filters = new ArrayList<SCMHeadFilter>();
@NonNull
private final TaskListener listener;
@NonNull
private SCMHeadObserver observer;

public SCMSourceRequestBuilder(@CheckForNull SCMSourceCriteria criteria, @NonNull SCMHeadObserver observer, @NonNull TaskListener listener) {
withCriteria(criteria);
this.listener = listener;
this.observer = observer;
}

@SuppressWarnings("unchecked")
public B withCriteria(@CheckForNull SCMSourceCriteria criteria) {
if (criteria != null) {
this.criteria.add(criteria);
}
return (B)this;
}

@SuppressWarnings("unchecked")
public B withFilter(@CheckForNull SCMHeadFilter filter) {
if (filter != null) {
this.filters.add(filter);
}
return (B)this;
}

@SuppressWarnings("unchecked")
public B withTrait(@NonNull SCMSourceTrait trait) {
observer = trait.applyToObserver(observer);
trait.applyToRequest((B) this);
return (B)this;
}

public B withTraits(@NonNull SCMSourceTrait... traits) {
return withTraits(Arrays.asList(traits));
}

@SuppressWarnings("unchecked")
public B withTraits(@NonNull Collection<SCMSourceTrait> traits) {
for (SCMSourceTrait trait: traits) {
withTrait(trait);
}
return (B) this;
}

@NonNull
public TaskListener listener() {
return listener;
}

@NonNull
public List<SCMSourceCriteria> criteria() {
return Collections.unmodifiableList(criteria);
}

@NonNull
public List<SCMHeadFilter> filters() {
return Collections.unmodifiableList(filters);
}

@NonNull
public SCMHeadObserver observer() {
return observer;
}

public abstract R build();
}

0 comments on commit 37da6da

Please sign in to comment.