提交 d02065c0 编写于 作者: K kohsuke

improved parameterization of DescriptorExtensionList to better support custom Descriptor type.

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@15667 71c3de6d-444a-0410-be80-ed276b4c234a
上级 4e1f48ac
......@@ -26,8 +26,10 @@ package hudson;
import hudson.model.Descriptor;
import hudson.model.Describable;
import hudson.model.Hudson;
import hudson.model.ViewDescriptor;
import hudson.model.Descriptor.FormException;
import hudson.util.Memoizer;
import hudson.slaves.NodeDescriptor;
import java.util.List;
import java.util.ArrayList;
......@@ -46,9 +48,17 @@ import net.sf.json.JSONObject;
*
* Use {@link Hudson#getDescriptorList(Class)} to obtain instances.
*
* @param <D>
* Represents the descriptor type. This is {@code Descriptor<T>} normally but often there are subtypes
* of descriptors, like {@link ViewDescriptor}, {@link NodeDescriptor}, etc, and this parameter points
* to those for better type safety of users.
*
* The actual value of 'D' is not necessary for the operation of this code, so it's purely for convenience
* of the users of this class.
*
* @since 1.286
*/
public final class DescriptorExtensionList<T extends Describable<T>> extends ExtensionList<Descriptor<T>> {
public final class DescriptorExtensionList<T extends Describable<T>, D extends Descriptor<T>> extends ExtensionList<D> {
/**
* Type of the {@link Describable} that this extension list retains.
*/
......@@ -65,7 +75,7 @@ public final class DescriptorExtensionList<T extends Describable<T>> extends Ext
* @param fqcn
* Fully qualified name of the descriptor, not the describable.
*/
public Descriptor<T> find(String fqcn) {
public D find(String fqcn) {
return Descriptor.find(this,fqcn);
}
......@@ -89,7 +99,7 @@ public final class DescriptorExtensionList<T extends Describable<T>> extends Ext
* Loading the descriptors in this case means filtering the descriptor from the master {@link ExtensionList}.
*/
@Override
protected List<Descriptor<T>> load() {
protected List<D> load() {
List r = new ArrayList();
for( Descriptor d : hudson.getExtensionList(Descriptor.class) ) {
Type subTyping = Types.getBaseClass(d.getClass(), Descriptor.class);
......
......@@ -182,7 +182,7 @@ public abstract class FileSystemProvisioner implements ExtensionPoint, Describab
/**
* Returns all the registered {@link FileSystemProvisioner} descriptors.
*/
public static DescriptorExtensionList<FileSystemProvisioner> all() {
public static DescriptorExtensionList<FileSystemProvisioner,FileSystemProvisionerDescriptor> all() {
return Hudson.getInstance().getDescriptorList(FileSystemProvisioner.class);
}
......
......@@ -41,6 +41,7 @@ import hudson.model.Project;
import hudson.model.Run;
import hudson.model.TopLevelItem;
import hudson.model.View;
import hudson.model.ParameterDefinition.ParameterDescriptor;
import hudson.search.SearchableModelObject;
import hudson.security.AccessControlled;
import hudson.security.AuthorizationStrategy;
......@@ -616,7 +617,7 @@ public class Functions {
return RetentionStrategy.all();
}
public static List<Descriptor<ParameterDefinition>> getParameterDescriptors() {
public static List<ParameterDescriptor> getParameterDescriptors() {
return ParameterDefinition.all();
}
......
......@@ -1165,7 +1165,7 @@ public abstract class AbstractProject<P extends AbstractProject<P,R>,R extends A
for (Trigger t : triggers)
t.stop();
triggers = buildDescribable(req, Triggers.getApplicableTriggers(this));
triggers = buildDescribable(req, Trigger.for_(this));
for (Trigger t : triggers)
t.start(this,true);
......
......@@ -74,7 +74,7 @@ public abstract class Build <P extends Project<P,B>,B extends Build<P,B>>
@Override
protected void onStartBuilding() {
super.onStartBuilding();
SCMTrigger t = (SCMTrigger)project.getTriggers().get(SCMTrigger.DESCRIPTOR);
SCMTrigger t = (SCMTrigger)project.getTriggers().get(Hudson.getInstance().getDescriptorByType(SCMTrigger.DescriptorImpl.class));
if(t!=null) {
// acquire the lock
buildLock = t.getLock();
......
......@@ -668,7 +668,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* Gets the trigger descriptor by name. Primarily used for making them web-visible.
*/
public TriggerDescriptor getTrigger(String shortClassName) {
return (TriggerDescriptor) findDescriptor(shortClassName, Triggers.TRIGGERS);
return (TriggerDescriptor) findDescriptor(shortClassName, Trigger.all());
}
/**
......@@ -1504,7 +1504,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* Can be an empty list but never null.
*/
@SuppressWarnings({"unchecked"})
public <T extends Describable<T>> DescriptorExtensionList<T> getDescriptorList(Class<T> type) {
public <T extends Describable<T>,D extends Descriptor<T>> DescriptorExtensionList<T,D> getDescriptorList(Class<T> type) {
return descriptorLists.get(type);
}
......@@ -2043,7 +2043,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
for( SCMDescriptor scmd : SCMS.SCMS )
result &= configureDescriptor(req,json,scmd);
for( TriggerDescriptor d : Triggers.TRIGGERS )
for( TriggerDescriptor d : Trigger.all() )
result &= configureDescriptor(req,json,d);
for( JobPropertyDescriptor d : JobPropertyDescriptor.all() )
......
......@@ -137,7 +137,7 @@ public abstract class ParameterDefinition implements
/**
* Returns all the registered {@link ParameterDefinition} descriptors.
*/
public static DescriptorExtensionList<ParameterDefinition> all() {
public static DescriptorExtensionList<ParameterDefinition,ParameterDescriptor> all() {
return Hudson.getInstance().getDescriptorList(ParameterDefinition.class);
}
......
......@@ -101,7 +101,7 @@ public abstract class RepositoryBrowser<E extends ChangeLogSet.Entry> implements
/**
* Returns all the registered {@link RepositoryBrowser} descriptors.
*/
public static DescriptorExtensionList<RepositoryBrowser<?>> all() {
public static DescriptorExtensionList<RepositoryBrowser<?>,Descriptor<RepositoryBrowser<?>>> all() {
return (DescriptorExtensionList)Hudson.getInstance().getDescriptorList(RepositoryBrowser.class);
}
......
......@@ -44,6 +44,7 @@ import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
import hudson.triggers.SCMTrigger;
import hudson.triggers.SCMTrigger.DescriptorImpl;
import hudson.util.EditDistance;
import hudson.util.FormFieldValidator;
import hudson.util.IOException2;
......@@ -516,7 +517,7 @@ public class SubversionSCM extends SCM implements Serializable {
e.printStackTrace(listener.error("Failed to update "+l.remote));
// trouble-shooting probe for #591
if(e.getErrorMessage().getErrorCode()== SVNErrorCode.WC_NOT_LOCKED) {
listener.getLogger().println("Polled jobs are "+ SCMTrigger.DESCRIPTOR.getItemsBeingPolled());
listener.getLogger().println("Polled jobs are "+ Hudson.getInstance().getDescriptorByType(SCMTrigger.DescriptorImpl.class).getItemsBeingPolled());
}
return null;
}
......
......@@ -182,7 +182,7 @@ public abstract class AuthorizationStrategy implements Describable<Authorization
/**
* Returns all the registered {@link AuthorizationStrategy} descriptors.
*/
public static DescriptorExtensionList<AuthorizationStrategy> all() {
public static DescriptorExtensionList<AuthorizationStrategy,Descriptor<AuthorizationStrategy>> all() {
return Hudson.getInstance().getDescriptorList(AuthorizationStrategy.class);
}
......
......@@ -63,7 +63,7 @@ public abstract class NodeDescriptor extends Descriptor<Node> {
/**
* Returns all the registered {@link NodeDescriptor} descriptors.
*/
public static DescriptorExtensionList<Node> all() {
public static DescriptorExtensionList<Node,NodeDescriptor> all() {
return Hudson.getInstance().getDescriptorList(Node.class);
}
......
......@@ -90,7 +90,7 @@ public abstract class RetentionStrategy<T extends Computer> implements Describab
/**
* Returns all the registered {@link RetentionStrategy} descriptors.
*/
public static DescriptorExtensionList<RetentionStrategy<?>> all() {
public static DescriptorExtensionList<RetentionStrategy<?>,Descriptor<RetentionStrategy<?>>> all() {
return (DescriptorExtensionList)Hudson.getInstance().getDescriptorList(RetentionStrategy.class);
}
......
......@@ -34,6 +34,7 @@ import hudson.model.Project;
import hudson.model.Action;
import hudson.model.AbstractProject;
import hudson.model.Hudson;
import hudson.model.Descriptor;
import hudson.model.Run.RunnerAbortedException;
import java.io.IOException;
......@@ -187,7 +188,8 @@ public abstract class BuildWrapper implements ExtensionPoint, Describable<BuildW
/**
* Returns all the registered {@link BuildWrapper} descriptors.
*/
public static DescriptorExtensionList<BuildWrapper> all() {
// for compatibility we can't use BuildWrapperDescriptor
public static DescriptorExtensionList<BuildWrapper,Descriptor<BuildWrapper>> all() {
// use getDescriptorList and not getExtensionList to pick up legacy instances
return Hudson.getInstance().getDescriptorList(BuildWrapper.class);
}
......
......@@ -70,7 +70,8 @@ public abstract class Builder extends BuildStepCompatibilityLayer implements Bui
/**
* Returns all the registered {@link Builder} descriptors.
*/
public static DescriptorExtensionList<Builder> all() {
// for backward compatibility, the signature is not BuildStepDescriptor
public static DescriptorExtensionList<Builder,Descriptor<Builder>> all() {
return Hudson.getInstance().getDescriptorList(Builder.class);
}
......
......@@ -101,7 +101,9 @@ public class SCMTrigger extends Trigger<SCMedItem> {
pollingScheduled = true;
LOGGER.fine("Scheduling a polling for "+job);
if (DESCRIPTOR.synchronousPolling) {
DescriptorImpl d = getDescriptor();
if (d.synchronousPolling) {
LOGGER.fine("Running the trigger directly without threading, " +
"as it's already taken care of by Trigger.Cron");
new Runner().run();
......@@ -110,11 +112,15 @@ public class SCMTrigger extends Trigger<SCMedItem> {
// even if we end up submitting this too many times, that's OK.
// the real exclusion control happens inside Runner.
LOGGER.fine("scheduling the trigger to (asynchronously) run");
DESCRIPTOR.getExecutor().submit(new Runner());
DESCRIPTOR.clogCheck();
d.getExecutor().submit(new Runner());
d.clogCheck();
}
}
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
public Action getProjectAction() {
return new SCMAction();
}
......@@ -126,12 +132,7 @@ public class SCMTrigger extends Trigger<SCMedItem> {
return new File(job.getRootDir(),"scm-polling.log");
}
public DescriptorImpl getDescriptor() {
return DESCRIPTOR;
}
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
@Extension
public static final class DescriptorImpl extends TriggerDescriptor {
/**
* Used to control the execution of the polling tasks.
......@@ -155,7 +156,7 @@ public class SCMTrigger extends Trigger<SCMedItem> {
*/
private int maximumThreads;
DescriptorImpl() {
public DescriptorImpl() {
load();
/*
* Need to resize the thread pool here in case there is no existing configuration file for SCMTrigger as
......
......@@ -29,6 +29,7 @@ import hudson.model.Cause;
import hudson.model.Item;
import hudson.scheduler.CronTabList;
import hudson.util.FormFieldValidator;
import hudson.Extension;
import java.io.IOException;
......@@ -56,12 +57,7 @@ public class TimerTrigger extends Trigger<BuildableItem> {
job.scheduleBuild(0, new TimerTriggerCause());
}
public TriggerDescriptor getDescriptor() {
return DESCRIPTOR;
}
public static final TriggerDescriptor DESCRIPTOR = new DescriptorImpl();
@Extension
public static class DescriptorImpl extends TriggerDescriptor {
public boolean isApplicable(Item item) {
return item instanceof BuildableItem;
......
......@@ -27,6 +27,7 @@ import antlr.ANTLRException;
import hudson.DependencyRunner;
import hudson.DependencyRunner.ProjectRunnable;
import hudson.ExtensionPoint;
import hudson.DescriptorExtensionList;
import hudson.slaves.ComputerRetentionWork;
import hudson.model.AbstractProject;
import hudson.model.Action;
......@@ -50,6 +51,8 @@ import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
......@@ -59,7 +62,7 @@ import java.util.logging.Logger;
*
* <p>
* To register a custom {@link Trigger} from a plugin,
* add it to {@link Triggers#TRIGGERS}.
* put {@link Extension} on your {@link TriggerDescriptor} class.
*
* @author Kohsuke Kawaguchi
*/
......@@ -105,7 +108,9 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
return null;
}
public abstract TriggerDescriptor getDescriptor();
public TriggerDescriptor getDescriptor() {
return (TriggerDescriptor)Hudson.getInstance().getDescriptor(getClass());
}
......@@ -181,7 +186,8 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
Hudson inst = Hudson.getInstance();
// Are we using synchronous polling?
if (SCMTrigger.DESCRIPTOR.synchronousPolling) {
SCMTrigger.DescriptorImpl scmd = inst.getDescriptorByType(SCMTrigger.DescriptorImpl.class);
if (scmd.synchronousPolling) {
LOGGER.fine("using synchronous polling");
// Check that previous synchronous polling job is done to prevent piling up too many jobs
......@@ -190,7 +196,7 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
// ignored, only the global setting is honored. The polling job is submitted only if the previous job has
// terminated.
// FIXME allow to set a global crontab spec
previousSynchronousPolling = SCMTrigger.DESCRIPTOR.getExecutor().submit(new DependencyRunner(new ProjectRunnable() {
previousSynchronousPolling = scmd.getExecutor().submit(new DependencyRunner(new ProjectRunnable() {
public void run(AbstractProject p) {
for (Trigger t : (Collection<Trigger>) p.getTriggers().values()) {
if (t instanceof SCMTrigger) {
......@@ -208,7 +214,7 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
// Process all triggers, except SCMTriggers when synchronousPolling is set
for (AbstractProject<?,?> p : inst.getAllItems(AbstractProject.class)) {
for (Trigger t : p.getTriggers().values()) {
if (! (t instanceof SCMTrigger && SCMTrigger.DESCRIPTOR.synchronousPolling)) {
if (! (t instanceof SCMTrigger && scmd.synchronousPolling)) {
LOGGER.fine("cron checking "+p.getName());
if (t.tabs.check(cal)) {
......@@ -251,4 +257,23 @@ public abstract class Trigger<J extends Item> implements Describable<Trigger<?>>
}
}, 1000*10);
}
/**
* Returns all the registered {@link Trigger} descriptors.
*/
public static DescriptorExtensionList<Trigger<?>,TriggerDescriptor> all() {
return (DescriptorExtensionList)Hudson.getInstance().getDescriptorList(Trigger.class);
}
/**
* Returns a subset of {@link TriggerDescriptor}s that applys to the given item.
*/
public static List<TriggerDescriptor> for_(Item i) {
List<TriggerDescriptor> r = new ArrayList<TriggerDescriptor>();
for (TriggerDescriptor t : all()) {
if(t.isApplicable(i))
r.add(t);
}
return r;
}
}
......@@ -25,6 +25,8 @@ package hudson.triggers;
import hudson.model.Descriptor;
import hudson.model.Item;
import hudson.util.DescriptorList;
import hudson.Extension;
import java.util.List;
import java.util.ArrayList;
......@@ -33,22 +35,28 @@ import java.util.ArrayList;
* List of all installed {@link Trigger}s.
*
* @author Kohsuke Kawaguchi
* @deprecated as of 1.286
* See each member for how to migrate your code.
*/
public class Triggers {
public static final List<TriggerDescriptor> TRIGGERS = Descriptor.toList(
SCMTrigger.DESCRIPTOR,
TimerTrigger.DESCRIPTOR
);
/**
* All registered {@link TriggerDescriptor} implementations.
* @deprecated as of 1.286
* Use {@link Trigger#all()} for read access, and {@link Extension} for registration.
*/
public static final List<TriggerDescriptor> TRIGGERS = (List)new DescriptorList<Trigger<?>>((Class)Trigger.class);
// Descriptor.toList(
// SCMTrigger.DESCRIPTOR,
// TimerTrigger.DESCRIPTOR
// );
/**
* Returns a subset of {@link TriggerDescriptor}s that applys to the given item.
*
* @deprecated as of 1.286
* Use {@link Trigger#for_(Item)}.
*/
public static List<TriggerDescriptor> getApplicableTriggers(Item i) {
List<TriggerDescriptor> r = new ArrayList<TriggerDescriptor>();
for (TriggerDescriptor t : TRIGGERS) {
if(t.isApplicable(i))
r.add(t);
}
return r;
return Trigger.for_(i);
}
}
......@@ -33,6 +33,7 @@ import hudson.model.Describable;
import hudson.model.ListView;
import hudson.model.Item;
import hudson.model.Hudson;
import hudson.model.Descriptor;
import hudson.util.DescriptorList;
import org.kohsuke.stapler.export.Exported;
......@@ -69,7 +70,7 @@ public abstract class ListViewColumn implements ExtensionPoint, Describable<List
/**
* Returns all the registered {@link ListViewColumn} descriptors.
*/
public static DescriptorExtensionList<ListViewColumn> all() {
public static DescriptorExtensionList<ListViewColumn, Descriptor<ListViewColumn>> all() {
return Hudson.getInstance().getDescriptorList(ListViewColumn.class);
}
......
......@@ -27,7 +27,7 @@ THE SOFTWARE.
-->
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<!-- build triggers config pane -->
<j:invokeStatic var="triggers" className="hudson.triggers.Triggers" method="getApplicableTriggers">
<j:invokeStatic var="triggers" className="hudson.triggers.Trigger" method="for_">
<j:arg value="${it}" type="hudson.model.Item" />
</j:invokeStatic>
<f:descriptorList title="${%Build Triggers}"
......
......@@ -100,7 +100,7 @@ public class ExtensionListTest extends HudsonTestCase {
public void testDescriptorLookup() throws Exception {
Descriptor<Fish> d = new Sishamo().getDescriptor();
DescriptorExtensionList<Fish> list = hudson.getDescriptorList(Fish.class);
DescriptorExtensionList<Fish,Descriptor<Fish>> list = hudson.getDescriptorList(Fish.class);
assertSame(d,list.get(Sishamo.DescriptorImpl.class));
assertSame(d,hudson.getDescriptor(Sishamo.class));
......@@ -110,7 +110,7 @@ public class ExtensionListTest extends HudsonTestCase {
// imagine that this is a static instance, like it is in many LIST static field in Hudson.
DescriptorList<Fish> LIST = new DescriptorList<Fish>(Fish.class);
DescriptorExtensionList<Fish> list = hudson.getDescriptorList(Fish.class);
DescriptorExtensionList<Fish,Descriptor<Fish>> list = hudson.getDescriptorList(Fish.class);
assertEquals(2,list.size());
assertNotNull(list.get(Tai.DescriptorImpl.class));
assertNotNull(list.get(Saba.DescriptorImpl.class));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册