提交 b63f162f 编写于 作者: K kohsuke

updated Publisher to support auto-discovery.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@15683 71c3de6d-444a-0410-be80-ed276b4c234a
上级 a8188ad4
......@@ -30,6 +30,8 @@ import hudson.model.ViewDescriptor;
import hudson.model.Descriptor.FormException;
import hudson.util.Memoizer;
import hudson.slaves.NodeDescriptor;
import hudson.tasks.Publisher;
import hudson.tasks.Publisher.DescriptorExtensionListImpl;
import java.util.List;
import java.util.ArrayList;
......@@ -58,13 +60,23 @@ import net.sf.json.JSONObject;
*
* @since 1.286
*/
public final class DescriptorExtensionList<T extends Describable<T>, D extends Descriptor<T>> extends ExtensionList<D> {
public class DescriptorExtensionList<T extends Describable<T>, D extends Descriptor<T>> extends ExtensionList<D> {
/**
* Creates a new instance.
*/
public static <T extends Describable<T>,D extends Descriptor<T>>
DescriptorExtensionList<T,D> create(Hudson hudson, Class<T> describableType) {
if(describableType==Publisher.class)
return (DescriptorExtensionList)new DescriptorExtensionListImpl(hudson);
return new DescriptorExtensionList<T,D>(hudson,describableType);
}
/**
* Type of the {@link Describable} that this extension list retains.
*/
private final Class<T> describableType;
public DescriptorExtensionList(Hudson hudson, Class<T> describableType) {
protected DescriptorExtensionList(Hudson hudson, Class<T> describableType) {
super(hudson, (Class)Descriptor.class, legacyDescriptors.get(describableType));
this.describableType = describableType;
}
......
......@@ -35,7 +35,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ConcurrentHashMap;
/**
* Retains the known extension instances for the given type 'T'.
......@@ -65,7 +64,8 @@ public class ExtensionList<T> extends AbstractList<T> {
/**
* Once discovered, extensions are retained here.
*/
private volatile CopyOnWriteArrayList<T> extensions;
@CopyOnWrite
private volatile List<T> extensions;
/**
* Place to store manually registered instances with the per-Hudson scope.
......@@ -119,11 +119,14 @@ public class ExtensionList<T> extends AbstractList<T> {
* Prefer automatic registration.
*/
@Override
public boolean add(T t) {
public synchronized boolean add(T t) {
legacyInstances.add(t);
// if we've already filled extensions, add it
if(extensions!=null)
extensions.add(t);
if(extensions!=null) {
List<T> r = new ArrayList<T>(extensions);
r.add(t);
extensions = sort(r);
}
return true;
}
......@@ -149,7 +152,7 @@ public class ExtensionList<T> extends AbstractList<T> {
if(extensions==null) {
List<T> r = load();
r.addAll(legacyInstances);
extensions = new CopyOnWriteArrayList<T>(r);
extensions = sort(r);
}
return extensions;
}
......@@ -165,6 +168,17 @@ public class ExtensionList<T> extends AbstractList<T> {
return r;
}
/**
* If the {@link ExtensionList} implementation requires sorting extensions,
* override this method to do so.
*
* <p>
* The implementation should copy a list, do a sort, and return the new instance.
*/
protected List<T> sort(List<T> r) {
return r;
}
public static <T> ExtensionList<T> create(Hudson hudson, Class<T> type) {
if(type==ExtensionFinder.class)
return new ExtensionList<T>(hudson,type) {
......
......@@ -606,7 +606,7 @@ public class Functions {
}
public static List<Descriptor<Publisher>> getPublisherDescriptors(AbstractProject<?,?> project) {
return BuildStepDescriptor.filter(BuildStep.PUBLISHERS, project.getClass());
return BuildStepDescriptor.filter(Publisher.all(), project.getClass());
}
public static List<Descriptor<ComputerLauncher>> getComputerLauncherDescriptors() {
......
......@@ -536,7 +536,7 @@ public class MatrixProject extends AbstractProject<MatrixProject,MatrixBuild> im
buildWrappers.rebuild(req, json, BuildWrappers.getFor(this));
builders.rebuildHetero(req, json, Builder.all(), "builder");
publishers.rebuild(req, json, BuildStepDescriptor.filter(BuildStep.PUBLISHERS,this.getClass()));
publishers.rebuild(req, json, BuildStepDescriptor.filter(Publisher.all(),this.getClass()));
updateTransientActions(); // to pick up transient actions from builder, publisher, etc.
rebuildConfigurations();
......
......@@ -604,7 +604,7 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
ignoreUpstremChanges = !json.has("triggerByDependency");
reporters.rebuild(req,json,MavenReporters.getConfigurableList());
publishers.rebuild(req,json,BuildStepDescriptor.filter(BuildStep.PUBLISHERS,this.getClass()));
publishers.rebuild(req,json,BuildStepDescriptor.filter(Publisher.all(),this.getClass()));
buildWrappers.rebuild(req,json,BuildWrappers.getFor(this));
updateTransientActions(); // to pick up transient actions from builder, publisher, etc.
......
......@@ -24,6 +24,7 @@
package hudson.maven;
import hudson.Launcher;
import hudson.Extension;
import hudson.maven.reporters.MavenAbstractArtifactRecord;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
......@@ -31,6 +32,7 @@ import hudson.model.BuildListener;
import hudson.model.Result;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import net.sf.json.JSONObject;
import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
import org.apache.maven.artifact.repository.ArtifactRepository;
......@@ -50,7 +52,7 @@ import java.io.IOException;
* @author Kohsuke Kawaguchi
* @since 1.191
*/
public class RedeployPublisher extends Publisher {
public class RedeployPublisher extends Recorder {
/**
* Repository ID. This is matched up with <tt>~/.m2/settings.xml</tt> for authentication related information.
*/
......@@ -115,16 +117,8 @@ public class RedeployPublisher extends Publisher {
return build.getAction(MavenAbstractArtifactRecord.class);
}
public BuildStepDescriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
private DescriptorImpl() {
}
protected DescriptorImpl(Class<? extends Publisher> clazz) {
super(clazz);
}
......
......@@ -286,7 +286,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*/
private transient final Memoizer<Class,DescriptorExtensionList> descriptorLists = new Memoizer<Class,DescriptorExtensionList>() {
public DescriptorExtensionList compute(Class key) {
return new DescriptorExtensionList(Hudson.this,key);
return DescriptorExtensionList.create(Hudson.this,key);
}
};
......@@ -654,7 +654,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* Gets the publisher descriptor by name. Primarily used for making them web-visible.
*/
public Descriptor<Publisher> getPublisher(String shortClassName) {
return findDescriptor(shortClassName, BuildStep.PUBLISHERS);
return findDescriptor(shortClassName, Publisher.all());
}
/**
......@@ -2027,7 +2027,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
for( Descriptor<Builder> d : Builder.all() )
result &= configureDescriptor(req,json,d);
for( Descriptor<Publisher> d : BuildStep.PUBLISHERS )
for( Descriptor<Publisher> d : Publisher.all() )
result &= configureDescriptor(req,json,d);
for( Descriptor<BuildWrapper> d : BuildWrapper.all() )
......
......@@ -187,7 +187,7 @@ public abstract class Project<P extends Project<P,B>,B extends Build<P,B>>
buildWrappers.rebuild(req,json, BuildWrappers.getFor(this));
builders.rebuildHetero(req,json, Builder.all(), "builder");
publishers.rebuild(req, json, BuildStepDescriptor.filter(BuildStep.PUBLISHERS, this.getClass()));
publishers.rebuild(req, json, BuildStepDescriptor.filter(Publisher.all(), this.getClass()));
updateTransientActions(); // to pick up transient actions from builder, publisher, etc.
}
......
......@@ -26,6 +26,7 @@ package hudson.tasks;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import hudson.maven.AbstractMavenProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
......@@ -48,7 +49,7 @@ import net.sf.json.JSONObject;
*
* @author Kohsuke Kawaguchi
*/
public class ArtifactArchiver extends Publisher {
public class ArtifactArchiver extends Recorder {
/**
* Comma- or space-separated list of patterns of files/directories to be archived.
......@@ -146,13 +147,7 @@ public class ArtifactArchiver extends Publisher {
return true;
}
public Descriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor<Publisher> DESCRIPTOR = new DescriptorImpl();
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public String getDisplayName() {
return Messages.ArtifactArchiver_DisplayName();
......
......@@ -25,6 +25,7 @@ package hudson.tasks;
import hudson.Launcher;
import hudson.Extension;
import hudson.ExtensionList;
import hudson.util.DescriptorList;
import hudson.maven.RedeployPublisher;
import hudson.model.AbstractBuild;
......@@ -34,6 +35,7 @@ import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Project;
import hudson.model.Hudson;
import hudson.tasks.junit.JUnitResultArchiver;
import hudson.tasks.test.AggregatedTestResultPublisher;
......@@ -41,6 +43,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.AbstractList;
import java.util.Iterator;
import java.util.WeakHashMap;
/**
* One step of the whole build process.
......@@ -140,25 +145,32 @@ public interface BuildStep {
* results, etc.
*
* @see PublisherList#addNotifier(Descriptor)
* @see PublisherList#addRecorder(Descriptor)
* @see PublisherList#addRecorder(Descriptor)
*
* @deprecated as of 1.286.
* Use {@link Publisher#all()} for read access, and use
* {@link Extension} for registration.
*/
public static final PublisherList PUBLISHERS = new PublisherList(Descriptor.toList(
ArtifactArchiver.DESCRIPTOR,
Fingerprinter.DESCRIPTOR,
JavadocArchiver.DESCRIPTOR,
JUnitResultArchiver.DescriptorImpl.DESCRIPTOR,
AggregatedTestResultPublisher.DescriptorImpl.INSTANCE,
BuildTrigger.DESCRIPTOR,
RedeployPublisher.DESCRIPTOR,
Mailer.DESCRIPTOR
));
public static final PublisherList PUBLISHERS = new PublisherList();
/**
* List of publisher descriptor.
*/
public static final class PublisherList extends ArrayList<Descriptor<Publisher>> {
public PublisherList(Collection<? extends Descriptor<Publisher>> c) {
super(c);
public static final class PublisherList extends AbstractList<Descriptor<Publisher>> {
/**
* {@link Descriptor}s are actually stored in here.
* Since {@link PublisherList} lives longer than {@link Hudson} we cannot directly use {@link ExtensionList}.
*/
private final DescriptorList<Publisher> core = new DescriptorList<Publisher>(Publisher.class);
/**
* For descriptors that are manually registered, remember what kind it was since
* older plugins don't extend from neither {@link Recorder} nor {@link Notifier}.
*/
/*package*/ static final WeakHashMap<Descriptor<Publisher>,Class<? extends Publisher>/*either Recorder.class or Notifier.class*/>
KIND = new WeakHashMap<Descriptor<Publisher>, Class<? extends Publisher>>();
private PublisherList() {
}
/**
......@@ -172,7 +184,8 @@ public interface BuildStep {
* @see #addRecorder(Descriptor)
*/
public void addNotifier( Descriptor<Publisher> d ) {
add(d);
KIND.put(d,Notifier.class);
core.add(d);
}
/**
......@@ -185,18 +198,31 @@ public interface BuildStep {
* @see #addNotifier(Descriptor)
*/
public void addRecorder( Descriptor<Publisher> d ) {
int idx = super.indexOf(Mailer.DESCRIPTOR);
add(idx,d);
KIND.put(d,Recorder.class);
core.add(d);
}
@Override
public boolean add(Descriptor<Publisher> d) {
return !contains(d) && super.add(d);
return !contains(d) && core.add(d);
}
@Override
public void add(int index, Descriptor<Publisher> d) {
if(!contains(d)) super.add(index, d);
if(!contains(d)) core.add(d);
}
public Descriptor<Publisher> get(int index) {
return core.get(index);
}
public int size() {
return core.size();
}
@Override
public Iterator<Descriptor<Publisher>> iterator() {
return core.iterator();
}
}
}
......@@ -24,6 +24,7 @@
package hudson.tasks;
import hudson.Launcher;
import hudson.Extension;
import hudson.security.AccessControlled;
import hudson.matrix.MatrixAggregatable;
import hudson.matrix.MatrixAggregator;
......@@ -33,7 +34,6 @@ import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.model.DependecyDeclarer;
import hudson.model.DependencyGraph;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.Items;
......@@ -74,7 +74,7 @@ import java.util.logging.Logger;
*
* @author Kohsuke Kawaguchi
*/
public class BuildTrigger extends Publisher implements DependecyDeclarer, MatrixAggregatable {
public class BuildTrigger extends Recorder implements DependecyDeclarer, MatrixAggregatable {
/**
* Comma-separated list of other projects to be scheduled.
......@@ -237,13 +237,7 @@ public class BuildTrigger extends Publisher implements DependecyDeclarer, Matrix
return this;
}
public Descriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor<Publisher> DESCRIPTOR = new DescriptorImpl();
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public DescriptorImpl() {
Hudson.getInstance().getJobListeners().add(new ItemListener() {
......@@ -251,8 +245,8 @@ public class BuildTrigger extends Publisher implements DependecyDeclarer, Matrix
public void onRenamed(Item item, String oldName, String newName) {
// update BuildTrigger of other projects that point to this object.
// can't we generalize this?
for( Project p : Hudson.getInstance().getProjects() ) {
BuildTrigger t = (BuildTrigger) p.getPublishers().get(BuildTrigger.DESCRIPTOR);
for( Project<?,?> p : Hudson.getInstance().getProjects() ) {
BuildTrigger t = p.getPublishersList().get(BuildTrigger.class);
if(t!=null) {
if(t.onJobRenamed(oldName,newName)) {
try {
......
......@@ -74,5 +74,4 @@ public abstract class Builder extends BuildStepCompatibilityLayer implements Bui
public static DescriptorExtensionList<Builder,Descriptor<Builder>> all() {
return Hudson.getInstance().getDescriptorList(Builder.class);
}
}
......@@ -27,13 +27,13 @@ import hudson.FilePath;
import hudson.FilePath.FileCallable;
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import hudson.maven.AbstractMavenProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Fingerprint;
import hudson.model.Fingerprint.BuildPtr;
import hudson.model.FingerprintMap;
......@@ -67,7 +67,7 @@ import java.util.logging.Logger;
*
* @author Kohsuke Kawaguchi
*/
public class Fingerprinter extends Publisher implements Serializable {
public class Fingerprinter extends Recorder implements Serializable {
/**
* Comma-separated list of files/directories to be fingerprinted.
......@@ -103,7 +103,7 @@ public class Fingerprinter extends Publisher implements Serializable {
record(build, listener, record, targets);
if(recordBuildArtifacts && build instanceof Build) {
ArtifactArchiver aa = (ArtifactArchiver) ((Build<?,?>)build).getProject().getPublishers().get(ArtifactArchiver.DESCRIPTOR);
ArtifactArchiver aa = ((Build<?,?>)build).getProject().getPublishersList().get(ArtifactArchiver.class);
if(aa==null) {
// configuration error
listener.error(Messages.Fingerprinter_NoArchiving());
......@@ -195,12 +195,7 @@ public class Fingerprinter extends Publisher implements Serializable {
}
}
public Descriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor<Publisher> DESCRIPTOR = new DescriptorImpl();
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public String getDisplayName() {
return Messages.Fingerprinter_DisplayName();
......
......@@ -26,6 +26,7 @@ package hudson.tasks;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import hudson.maven.AbstractMavenProject;
import hudson.model.*;
import hudson.util.FormFieldValidator;
......@@ -43,7 +44,7 @@ import java.io.IOException;
*
* @author Kohsuke Kawaguchi
*/
public class JavadocArchiver extends Publisher {
public class JavadocArchiver extends Recorder {
/**
* Path to the Javadoc directory in the workspace.
*/
......@@ -115,12 +116,6 @@ public class JavadocArchiver extends Publisher {
return new JavadocAction(project);
}
public Descriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
public static final Descriptor<Publisher> DESCRIPTOR = new DescriptorImpl();
protected static abstract class BaseJavadocAction implements Action {
public String getUrlName() {
return "javadoc";
......@@ -197,6 +192,7 @@ public class JavadocArchiver extends Publisher {
}
}
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public String getDisplayName() {
return Messages.JavadocArchiver_DisplayName();
......
......@@ -25,12 +25,11 @@ package hudson.tasks;
import hudson.Launcher;
import hudson.Functions;
import hudson.Extension;
import hudson.maven.AbstractMavenProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Build;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.User;
import hudson.model.UserPropertyDescriptor;
import hudson.util.FormFieldValidator;
......@@ -66,7 +65,7 @@ import net.sf.json.JSONObject;
*
* @author Kohsuke Kawaguchi
*/
public class Mailer extends Publisher {
public class Mailer extends Notifier {
protected static final Logger LOGGER = Logger.getLogger(Mailer.class.getName());
/**
......@@ -97,7 +96,7 @@ public class Mailer extends Publisher {
/** Check whether a path (/-separated) will be archived. */
@Override
public boolean artifactMatches(String path, AbstractBuild<?,?> build) {
ArtifactArchiver aa = (ArtifactArchiver) build.getProject().getPublishersList().toMap().get(ArtifactArchiver.DESCRIPTOR);
ArtifactArchiver aa = build.getProject().getPublishersList().get(ArtifactArchiver.class);
if (aa == null) {
LOGGER.finer("No ArtifactArchiver found");
return false;
......@@ -119,12 +118,7 @@ public class Mailer extends Publisher {
}.execute(build,listener);
}
public Descriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
/**
* The default e-mail address suffix appended to the user name found from changelog,
......
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, 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 hudson.tasks;
import hudson.Extension;
import hudson.ExtensionPoint;
/**
* {@link BuildStep}s that run after the build is completed.
*
* <p>
* {@link Notifier} is a kind of {@link Publisher} that sends out the outcome of the builds to
* other systems and humans. This marking ensures that notifiers are run after the build result
* is set to its final values by other {@link Recorder}s.
*
* <p>
* To register a custom {@link Publisher} from a plugin,
* put {@link Extension} on your descriptor.
*
*
* @author Kohsuke Kawaguchi
* @since 1.286
* @see Recorder
*/
public abstract class Notifier extends Publisher implements ExtensionPoint {
public BuildStepDescriptor getDescriptor() {
return (BuildStepDescriptor)super.getDescriptor();
}
}
......@@ -25,6 +25,8 @@ package hudson.tasks;
import hudson.ExtensionPoint;
import hudson.Launcher;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.maven.MavenReporter;
import hudson.model.Action;
import hudson.model.Build;
......@@ -32,13 +34,20 @@ import hudson.model.BuildListener;
import hudson.model.Describable;
import hudson.model.Project;
import hudson.model.AbstractBuild;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* {@link BuildStep}s that run after the build is completed.
*
* <p>
* To register a custom {@link Publisher} from a plugin,
* add it to {@link BuildStep#PUBLISHERS}.
* put {@link Extension} on your descriptor implementation.
*
* <p>
* Starting 1.178, publishers are exposed to all kinds of different
......@@ -55,7 +64,15 @@ import hudson.model.AbstractBuild;
* @author Kohsuke Kawaguchi
*/
public abstract class Publisher extends BuildStepCompatibilityLayer implements BuildStep, Describable<Publisher>, ExtensionPoint {
//
/**
* @deprecated
* Don't extend from {@link Publisher} directly. Instead, choose {@link Recorder} or {@link Notifier}
* as your base class.
*/
protected Publisher() {
}
//
// these two methods need to remain to keep binary compatibility with plugins built with Hudson < 1.150
//
/**
......@@ -99,4 +116,55 @@ public abstract class Publisher extends BuildStepCompatibilityLayer implements B
public boolean needsToRunAfterFinalized() {
return false;
}
public Descriptor<Publisher> getDescriptor() {
return Hudson.getInstance().getDescriptor(getClass());
}
/**
* {@link Publisher} has a special sort semantics that requires a subtype.
*
* @see DescriptorExtensionList#create(Hudson, Class)
*/
public static final class DescriptorExtensionListImpl extends DescriptorExtensionList<Publisher,Descriptor<Publisher>>
implements Comparator<Descriptor<Publisher>> {
public DescriptorExtensionListImpl(Hudson hudson) {
super(hudson,Publisher.class);
}
@Override
protected List<Descriptor<Publisher>> sort(List<Descriptor<Publisher>> r) {
List<Descriptor<Publisher>> copy = new ArrayList<Descriptor<Publisher>>(r);
Collections.sort(copy,this);
return copy;
}
public int compare(Descriptor<Publisher> lhs, Descriptor<Publisher> rhs) {
return classify(lhs)-classify(rhs);
}
/**
* If recorder, return 0, if unknown return 1, if notifier returns 2.
* This is used as a sort key.
*/
private int classify(Descriptor<Publisher> d) {
if(Recorder.class.isAssignableFrom(d.clazz)) return 0;
if(Notifier.class.isAssignableFrom(d.clazz)) return 2;
// for compatibility, if the descriptor is manually registered in a specific way, detect that.
Class<? extends Publisher> kind = PublisherList.KIND.get(d);
if(kind==Recorder.class) return 0;
if(kind==Notifier.class) return 2;
return 1;
}
}
/**
* Returns all the registered {@link Publisher} descriptors.
*/
// for backward compatibility, the signature is not BuildStepDescriptor
public static DescriptorExtensionList<Publisher,Descriptor<Publisher>> all() {
return Hudson.getInstance().getDescriptorList(Publisher.class);
}
}
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, 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 hudson.tasks;
import hudson.Extension;
import hudson.ExtensionPoint;
/**
* {@link BuildStep}s that run after the build is completed.
*
* <p>
* {@link Recorder} is a kind of {@link Publisher} that collects statistics from the build,
* and can mark builds as untable/failure. This marking ensures that builds are marked accordingly
* before notifications are sent via {@link Notifier}s. Otherwise, if the build is marked failed
* after some notifications are sent, inconsistency ensues.
*
* <p>
* To register a custom {@link Publisher} from a plugin,
* put {@link Extension} on your descriptor.
*
*
* @author Kohsuke Kawaguchi
* @since 1.286
* @see Notifier
*/
public abstract class Recorder extends Publisher implements ExtensionPoint {
public BuildStepDescriptor getDescriptor() {
return (BuildStepDescriptor)super.getDescriptor();
}
}
......@@ -26,6 +26,7 @@ package hudson.tasks.junit;
import hudson.FilePath.FileCallable;
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import hudson.maven.AbstractMavenProject;
import hudson.matrix.MatrixAggregatable;
import hudson.matrix.MatrixAggregator;
......@@ -34,6 +35,7 @@ import hudson.model.*;
import hudson.remoting.VirtualChannel;
import hudson.tasks.Publisher;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Recorder;
import hudson.tasks.test.TestResultAggregator;
import hudson.tasks.test.TestResultProjectAction;
import hudson.util.FormFieldValidator;
......@@ -53,7 +55,7 @@ import java.io.Serializable;
*
* @author Kohsuke Kawaguchi
*/
public class JUnitResultArchiver extends Publisher implements Serializable, MatrixAggregatable {
public class JUnitResultArchiver extends Recorder implements Serializable, MatrixAggregatable {
/**
* {@link FileSet} "includes" string, like "foo/bar/*.xml"
......@@ -130,15 +132,10 @@ public class JUnitResultArchiver extends Publisher implements Serializable, Matr
return new TestResultAggregator(build,launcher,listener);
}
public Descriptor<Publisher> getDescriptor() {
return DescriptorImpl.DESCRIPTOR;
}
private static final long serialVersionUID = 1L;
@Extension
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public static final Descriptor<Publisher> DESCRIPTOR = new DescriptorImpl();
public String getDisplayName() {
return Messages.JUnitResultArchiver_DisplayName();
}
......
......@@ -25,6 +25,7 @@ package hudson.tasks.test;
import hudson.Launcher;
import hudson.Util;
import hudson.Extension;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
......@@ -37,6 +38,7 @@ import hudson.model.TaskListener;
import hudson.model.listeners.RunListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import hudson.util.FormFieldValidator;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.QueryParameter;
......@@ -57,7 +59,7 @@ import java.util.List;
*
* @author Kohsuke Kawaguchi
*/
public class AggregatedTestResultPublisher extends Publisher {
public class AggregatedTestResultPublisher extends Recorder {
/**
* Jobs to aggregate. Camma separated.
* Null if triggering downstreams.
......@@ -74,10 +76,6 @@ public class AggregatedTestResultPublisher extends Publisher {
return true;
}
public DescriptorImpl getDescriptor() {
return DescriptorImpl.INSTANCE;
}
/**
* Action that serves the aggregated record.
*
......@@ -232,6 +230,7 @@ public class AggregatedTestResultPublisher extends Publisher {
}
}
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true; // for all types
......@@ -268,8 +267,6 @@ public class AggregatedTestResultPublisher extends Publisher {
else
return new AggregatedTestResultPublisher(s.getString("jobs"));
}
public static final DescriptorImpl INSTANCE = new DescriptorImpl();
}
}
......@@ -49,6 +49,7 @@ import hudson.slaves.RetentionStrategy;
import hudson.tasks.BuildStep;
import hudson.tasks.Mailer;
import hudson.tasks.Maven;
import hudson.tasks.Publisher;
import hudson.tasks.Maven.MavenInstallation;
import hudson.util.ProcessTreeKiller;
import hudson.util.StreamTaskListener;
......@@ -201,11 +202,6 @@ public abstract class HudsonTestCase extends TestCase {
for (LenientRunnable r : tearDowns)
r.run();
// TODO: avoid relying on singletons and switch to some DI container.
// In the mean time, discard descriptors created during this exercise.
// without this, plugins loaded in the tests will be left and interferes with the later tests.
cleanUpDescriptors(BuildStep.PUBLISHERS);
hudson.cleanUp();
env.dispose();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册