From 215f34b4949e9de5514cc7c7c9947e1d4c78e8f4 Mon Sep 17 00:00:00 2001 From: kohsuke Date: Sun, 7 Jan 2007 19:55:52 +0000 Subject: [PATCH] added JobProperty as the extensible property on Job. git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@1683 71c3de6d-444a-0410-be80-ed276b4c234a --- core/src/main/java/hudson/Functions.java | 1 - .../main/java/hudson/model/Descriptor.java | 2 +- core/src/main/java/hudson/model/Hudson.java | 5 +- core/src/main/java/hudson/model/Job.java | 29 ++++++++++ .../main/java/hudson/model/JobDescriptor.java | 14 +++++ .../main/java/hudson/model/JobProperty.java | 40 ++++++++++++++ .../hudson/model/JobPropertyDescriptor.java | 29 ++++++++++ core/src/main/java/hudson/model/Jobs.java | 12 +++++ .../java/hudson/util/CopyOnWriteList.java | 53 ++++++++++++++++++- core/src/main/java/hudson/util/XStream2.java | 2 + .../hudson/model/Hudson/configure.jelly | 53 +++++++------------ .../hudson/model/Job/configure.jelly | 10 ++++ 12 files changed, 210 insertions(+), 40 deletions(-) create mode 100644 core/src/main/java/hudson/model/JobProperty.java create mode 100644 core/src/main/java/hudson/model/JobPropertyDescriptor.java diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 91bd485381..a0ce3a6536 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -270,5 +270,4 @@ public class Functions { } return false; } - } diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index eeb4895033..3eb353eb88 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -199,7 +199,7 @@ public abstract class Descriptor> { } public static > - Map,T> toMap(List describables) { + Map,T> toMap(Iterable describables) { Map,T> m = new LinkedHashMap,T>(); for (T d : describables) { m.put(d.getDescriptor(),d); diff --git a/core/src/main/java/hudson/model/Hudson.java b/core/src/main/java/hudson/model/Hudson.java index e42cc56633..10125c995a 100644 --- a/core/src/main/java/hudson/model/Hudson.java +++ b/core/src/main/java/hudson/model/Hudson.java @@ -116,7 +116,7 @@ public final class Hudson extends JobCollection implements Node { private transient boolean isQuietingDown; private transient boolean terminating; - private List jdks; + private List jdks = new ArrayList(); /** * Set of installed cluster nodes. @@ -818,6 +818,9 @@ public final class Hudson extends JobCollection implements Node { for( Descriptor d : Triggers.TRIGGERS ) result &= d.configure(req); + for( JobPropertyDescriptor d : Jobs.PROPERTIES ) + result &= d.configure(req); + save(); if(result) rsp.sendRedirect("."); // go to the top page diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index a7bbff8318..73e67029ca 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -8,6 +8,7 @@ import hudson.tasks.BuildTrigger; import hudson.tasks.LogRotator; import hudson.util.ChartUtil; import hudson.util.ColorPalette; +import hudson.util.CopyOnWriteList; import hudson.util.DataSetBuilder; import hudson.util.IOException2; import hudson.util.RunList; @@ -39,6 +40,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.SortedMap; +import java.util.Map; /** * A job is an runnable entity under the monitoring of Hudson. @@ -85,6 +87,11 @@ public abstract class Job, RunT extends Run> properties = new CopyOnWriteList>(); + protected Job(Hudson parent,String name) { this.parent = parent; doSetName(name); @@ -113,6 +120,9 @@ public abstract class Job, RunT extends Run>(); } /** @@ -196,6 +206,25 @@ public abstract class Job, RunT extends Run> getProperties() { + return Descriptor.toMap((Iterable)properties); + } + + /** + * Gets the specific property, or null if the propert is not configured for this job. + */ + public T getProperty(Class clazz) { + for (JobProperty p : properties) { + if(clazz.isInstance(p)) + return clazz.cast(p); + } + return null; + } + /** * Renames a job. */ diff --git a/core/src/main/java/hudson/model/JobDescriptor.java b/core/src/main/java/hudson/model/JobDescriptor.java index ddb71a84ca..afa7d7b1a3 100644 --- a/core/src/main/java/hudson/model/JobDescriptor.java +++ b/core/src/main/java/hudson/model/JobDescriptor.java @@ -2,6 +2,9 @@ package hudson.model; import org.kohsuke.stapler.StaplerRequest; +import java.util.List; +import java.util.ArrayList; + /** * {@link Descriptor} for {@link Job}s. * @@ -25,4 +28,15 @@ public abstract class JobDescriptor,R extends Run> exten * Creates a new {@link Job}. */ public abstract Job newInstance(String name); + + /** + * Gets the {@link JobPropertyDescriptor}s applicable for this job type. + */ + public List getPropertyDescriptors() { + List r = new ArrayList(); + for (JobPropertyDescriptor p : Jobs.PROPERTIES) + if(p.isApplicable(clazz)) + r.add(p); + return r; + } } diff --git a/core/src/main/java/hudson/model/JobProperty.java b/core/src/main/java/hudson/model/JobProperty.java new file mode 100644 index 0000000000..07e09503a2 --- /dev/null +++ b/core/src/main/java/hudson/model/JobProperty.java @@ -0,0 +1,40 @@ +package hudson.model; + +import hudson.ExtensionPoint; +import hudson.Plugin; + +/** + * Extensible property of {@link Job}. + * + *

+ * {@link Plugin}s can extend this to define custom properties + * for {@link Job}s. {@link JobProperty}s show up in the user + * configuration screen, and they are persisted with the job object. + * + *

+ * Configuration screen should be defined in config.jelly. + * Within this page, the {@link JobProperty} instance is available + * as instance variable (while it refers to {@link Job}. + * + * + * @author Kohsuke Kawaguchi + * @see JobPropertyDescriptor + * @since 1.72 + */ +public abstract class JobProperty> implements Describable>, ExtensionPoint { + /** + * The {@link Job} object that owns this property. + * This value will be set by the Hudson code. + * Derived classes can expect this value to be always set. + */ + protected transient J owner; + + /*package*/ final void setOwner(J owner) { + this.owner = owner; + } + + /** + * {@inheritDoc} + */ + public abstract JobPropertyDescriptor getDescriptor(); +} diff --git a/core/src/main/java/hudson/model/JobPropertyDescriptor.java b/core/src/main/java/hudson/model/JobPropertyDescriptor.java new file mode 100644 index 0000000000..4b5cb0c2fe --- /dev/null +++ b/core/src/main/java/hudson/model/JobPropertyDescriptor.java @@ -0,0 +1,29 @@ +package hudson.model; + +/** + * {@link Descriptor} for {@link JobProperty}. + * + * @author Kohsuke Kawaguchi + * @see Jobs#PROPERTIES + * @since 1.72 + */ +public abstract class JobPropertyDescriptor extends Descriptor> { + protected JobPropertyDescriptor(Class> clazz) { + super(clazz); + } + + /** + * Returns true if this {@link JobProperty} type is applicable to the + * given job type. + * + *

+ * Normally, this method is implemented like + * {@code return AbstractProject.class.isAssignableFrom(jobType)} + * where "AbstractProject" is the J of {@link JobProperty}<J>. + * + * @return + * true to indicate applicable, in which case the property will be + * displayed in the configuration screen of this job. + */ + public abstract boolean isApplicable(Class jobType); +} diff --git a/core/src/main/java/hudson/model/Jobs.java b/core/src/main/java/hudson/model/Jobs.java index f16495d26d..cdcdabc3f3 100644 --- a/core/src/main/java/hudson/model/Jobs.java +++ b/core/src/main/java/hudson/model/Jobs.java @@ -3,6 +3,7 @@ package hudson.model; import hudson.maven.MavenJob; import java.util.List; +import java.util.ArrayList; /** * List of all installed {@link Job} types. @@ -27,6 +28,17 @@ public class Jobs { return null; } + /** + * List of all installed {@link JobPropertyDescriptor} types. + * + *

+ * Plugins can add their {@link JobPropertyDescriptor}s to this list. + * + * @see JobDescriptor#getPropertyDescriptors() + */ + public static final List PROPERTIES = Descriptor.toList( + ); + static { if(Boolean.getBoolean("hudson.maven")) JOBS.add(MavenJob.DESCRIPTOR); diff --git a/core/src/main/java/hudson/util/CopyOnWriteList.java b/core/src/main/java/hudson/util/CopyOnWriteList.java index b9c6785907..b78a905b7e 100644 --- a/core/src/main/java/hudson/util/CopyOnWriteList.java +++ b/core/src/main/java/hudson/util/CopyOnWriteList.java @@ -1,9 +1,18 @@ package hudson.util; -import java.util.List; +import com.thoughtworks.xstream.alias.CannotResolveClassException; +import com.thoughtworks.xstream.converters.Converter; +import com.thoughtworks.xstream.converters.MarshallingContext; +import com.thoughtworks.xstream.converters.UnmarshallingContext; +import com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.mapper.Mapper; + import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; +import java.util.List; /** * {@link List}-like implementation that has copy-on-write semantics. @@ -17,7 +26,11 @@ public class CopyOnWriteList implements Iterable { private volatile List core; public CopyOnWriteList(List core) { - this.core = new ArrayList(core); + this(core,false); + } + + private CopyOnWriteList(List core, boolean noCopy) { + this.core = noCopy ? core : new ArrayList(core); } public CopyOnWriteList() { @@ -65,4 +78,40 @@ public class CopyOnWriteList implements Iterable { } }; } + + /** + * {@link Converter} implementation for XStream. + */ + public static final class ConverterImpl extends AbstractCollectionConverter { + public ConverterImpl(Mapper mapper) { + super(mapper); + } + + public boolean canConvert(Class type) { + return type==CopyOnWriteList.class; + } + + public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) { + for (Object o : (CopyOnWriteList) source) + writeItem(o, context, writer); + } + + @SuppressWarnings("unchecked") + public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { + // read the items from xml into a list + List items = new ArrayList(); + while (reader.hasMoreChildren()) { + reader.moveDown(); + try { + Object item = readItem(reader, context, items); + items.add(item); + } catch (CannotResolveClassException e) { + System.err.println("failed to locate class: "+e); + } + reader.moveUp(); + } + + return new CopyOnWriteList(items,true); + } + } } diff --git a/core/src/main/java/hudson/util/XStream2.java b/core/src/main/java/hudson/util/XStream2.java index 61340af31f..4c99c2cedf 100644 --- a/core/src/main/java/hudson/util/XStream2.java +++ b/core/src/main/java/hudson/util/XStream2.java @@ -5,6 +5,7 @@ import com.thoughtworks.xstream.converters.DataHolder; import com.thoughtworks.xstream.io.HierarchicalStreamDriver; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import hudson.model.Hudson; +import hudson.util.CopyOnWriteList.ConverterImpl; /** * {@link XStream} enhanced for retroweaver support. @@ -36,5 +37,6 @@ public class XStream2 extends XStream { registerConverter(new RobustCollectionConverter(getClassMapper()),10); registerConverter(new RetroweaverEnumConverter(),10); registerConverter(new RetrotranslatorEnumConverter(),10); + registerConverter(new ConverterImpl(getClassMapper()),10); } } diff --git a/core/src/main/resources/hudson/model/Hudson/configure.jelly b/core/src/main/resources/hudson/model/Hudson/configure.jelly index da497b07fa..625662565f 100644 --- a/core/src/main/resources/hudson/model/Hudson/configure.jelly +++ b/core/src/main/resources/hudson/model/Hudson/configure.jelly @@ -4,7 +4,7 @@ - + ${it.rootDir} @@ -108,40 +108,23 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/core/src/main/resources/hudson/model/Job/configure.jelly b/core/src/main/resources/hudson/model/Job/configure.jelly index 2d10201c17..89096ebbdf 100644 --- a/core/src/main/resources/hudson/model/Job/configure.jelly +++ b/core/src/main/resources/hudson/model/Job/configure.jelly @@ -21,6 +21,16 @@ + + + + + + + + + + -- GitLab