提交 31cd6033 编写于 作者: K Kohsuke Kawaguchi

Merge branch 'oss' of github.com:cloudbees/hudson into oss

......@@ -61,6 +61,10 @@ Upcoming changes</a>
<li class=bug>
PAM authentication fails to restore group membership information on "remember me" tokens.
(<a href="http://issues.jenkins-ci.org/browse/JENKINS-9094">issue 9094</a>)
<li class=rfe>
Added an extension point to allow adding transient actions to computers.
<li class=rfe>
Added an extension point to allow associating custom properties with views.
<li class=rfe>
Actions can now override their rendering in the parent model object.
</ul>
......
......@@ -4,7 +4,7 @@
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>cli</artifactId>
<name>Jenkins CLI</name>
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
......@@ -139,11 +139,28 @@ public /*transient*/ abstract class Computer extends Actionable implements Acces
private final WorkspaceList workspaceList = new WorkspaceList();
protected transient List<Action> transientActions;
public Computer(Node node) {
assert node.getNumExecutors()!=0 : "Computer created with 0 executors";
setNode(node);
}
/**
* Returns the transient {@link Action}s associated with the computer.
*/
public List<Action> getActions() {
List<Action> result = new ArrayList<Action>();
result.addAll(super.getActions());
synchronized (this) {
if (transientActions == null) {
transientActions = TransientComputerActionFactory.createAllFor(this);
}
result.addAll(transientActions);
}
return result;
}
/**
* This is where the log from the remote agent goes.
*/
......
......@@ -91,13 +91,6 @@ public class ListView extends View implements Saveable {
this.owner = owner;
}
public void save() throws IOException {
// persistence is a part of the owner.
// due to the initialization timing issue, it can be null when this method is called.
if (owner!=null)
owner.save();
}
private Object readResolve() {
if(includeRegex!=null)
includePattern = Pattern.compile(includeRegex);
......
/*
* The MIT License
*
* Copyright (c) 2004-2011, Sun Microsystems, Inc., Stephen Connolly.
*
* 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.model;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Extension point for inserting transient {@link hudson.model.Action}s to {@link hudson.model.Computer}s.
* <p>
* To register your implementation, put {@link hudson.Extension} on your subtype.
*
* @author Stephen Connolly
* @since 1.405
* @see hudson.model.Action
*/
public abstract class TransientComputerActionFactory implements ExtensionPoint {
/**
* Creates actions for the given computer.
*
* @param target
* The computer for which the action objects are requested. Never null.
* @return
* Can be empty but must not be null.
*/
public abstract Collection<? extends Action> createFor(Computer target);
/**
* Returns all the registered {@link TransientComputerActionFactory}s.
*/
public static ExtensionList<TransientComputerActionFactory> all() {
return Hudson.getInstance().getExtensionList(TransientComputerActionFactory.class);
}
/**
* Creates {@link Action)s for a node, using all registered {@link TransientComputerActionFactory }s.
*/
public static List<Action> createAllFor(Computer target) {
List<Action> result = new ArrayList<Action>();
for (TransientComputerActionFactory f: all()) {
result.addAll(f.createFor(target));
}
return result;
}
}
......@@ -148,10 +148,6 @@ public class TreeView extends View implements ViewGroup {
// noop
}
public void save() throws IOException {
owner.save();
}
public void doCreateView( StaplerRequest req, StaplerResponse rsp ) throws IOException, ServletException, FormException {
checkPermission(View.CREATE);
views.add(View.create(req,rsp,this));
......
......@@ -23,7 +23,6 @@
*/
package hudson.model;
import static hudson.model.Hudson.checkGoodName;
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.ExtensionPoint;
......@@ -37,10 +36,17 @@ import hudson.security.ACL;
import hudson.security.AccessControlled;
import hudson.security.Permission;
import hudson.security.PermissionGroup;
import hudson.util.DescribableList;
import hudson.util.DescriptorList;
import hudson.util.RunList;
import hudson.widgets.Widget;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
......@@ -54,12 +60,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.export.Exported;
import org.kohsuke.stapler.export.ExportedBean;
import static hudson.model.Hudson.*;
/**
* Encapsulates the rendering of the list of {@link TopLevelItem}s
......@@ -82,7 +83,7 @@ import org.kohsuke.stapler.export.ExportedBean;
* @see ViewGroup
*/
@ExportedBean
public abstract class View extends AbstractModelObject implements AccessControlled, Describable<View>, ExtensionPoint {
public abstract class View extends AbstractModelObject implements AccessControlled, Describable<View>, ExtensionPoint, Saveable {
/**
* Container of this view. Set right after the construction
* and never change thereafter.
......@@ -111,6 +112,12 @@ public abstract class View extends AbstractModelObject implements AccessControll
protected transient List<Action> transientActions;
/**
* List of {@link ViewProperty}s configured for this view.
* @since 1.406
*/
private volatile DescribableList<ViewProperty,ViewPropertyDescriptor> properties = new PropertyList();
protected View(String name) {
this.name = name;
}
......@@ -120,6 +127,13 @@ public abstract class View extends AbstractModelObject implements AccessControll
this.owner = owner;
}
private Object readResolve() {
if (properties == null) {
properties = new PropertyList();
}
return this;
}
/**
* Gets all the items in this collection in a read-only view.
*/
......@@ -183,6 +197,31 @@ public abstract class View extends AbstractModelObject implements AccessControll
return description;
}
/**
* Gets the view properties configured for this view.
* @since 1.406
*/
public DescribableList<ViewProperty,ViewPropertyDescriptor> getProperties() {
return properties;
}
public void save() throws IOException {
// persistence is a part of the owner
// due to initialization timing issue, it can be null when this method is called
if (owner != null) {
owner.save();
}
}
/**
* List of all {@link ViewProperty}s exposed primarily for the remoting API.
* @since 1.406
*/
@Exported(name="property",inline=true)
public List<ViewProperty> getAllProperties() {
return properties.toList();
}
public ViewDescriptor getDescriptor() {
return (ViewDescriptor)Hudson.getInstance().getDescriptorOrDie(getClass());
}
......@@ -559,7 +598,7 @@ public abstract class View extends AbstractModelObject implements AccessControll
checkPermission(CONFIGURE);
description = req.getParameter("description");
owner.save();
save();
rsp.sendRedirect("."); // go to the top page
}
......@@ -579,7 +618,29 @@ public abstract class View extends AbstractModelObject implements AccessControll
rename(req.getParameter("name"));
owner.save();
JSONObject json = req.getSubmittedForm();
List<ViewProperty> props = new ArrayList<ViewProperty>();
int i = 0;
for (ViewPropertyDescriptor d: ViewProperty.all()) {
ViewProperty p = properties.get(d.clazz);
JSONObject o = json.optJSONObject("viewProperty" + (i++));
if (o != null) {
if (p != null) {
p = p.reconfigure(req, o);
} else {
p = d.newInstance(req, o);
}
}
if (p != null) {
props.add(p);
}
}
properties.replaceBy(props);
save();
rsp.sendRedirect2("../"+name);
}
......@@ -703,4 +764,16 @@ public abstract class View extends AbstractModelObject implements AccessControll
return v;
}
private class PropertyList extends DescribableList<ViewProperty,ViewPropertyDescriptor> {
private PropertyList() {
super(View.this);
}
@Override
protected void onModified() throws IOException {
for (ViewProperty p : this)
p.setView(View.this);
}
}
}
/*
* The MIT License
*
* Copyright (c) 2011, CloudBees, Inc., Stephen Connolly
*
* 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.model;
import hudson.DescriptorExtensionList;
import hudson.ExtensionPoint;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.StaplerRequest;
/**
* Extensible property of {@link View}.
*
* <p>
* {@link hudson.Plugin}s can extend this to define custom properties for {@link View}s.
* {@link ViewProperty}s show up in the view configuration screen, and they are
* persisted with the view object.
*
* <p>
* Configuration screen should be defined in <code>config.jelly</code>.
* Within this page, the {@link ViewProperty} instance is available as
* the <code>instance</code> EL variable (while the <code>it</code> EL variable
* refers to the {@link View}.
*
* @author Stephen Connolly
* @since 1.406
*/
public class ViewProperty implements Describable<ViewProperty>, ExtensionPoint {
/**
* The view object that owns this property.
* This value will be set by the core code.
* Derived classes can expect this value to be always set.
*/
protected transient View view;
/*package*/ final void setView(View view) {
this.view = view;
}
public ViewPropertyDescriptor getDescriptor() {
return (ViewPropertyDescriptor)Hudson.getInstance().getDescriptorOrDie(getClass());
}
public static DescriptorExtensionList<ViewProperty,ViewPropertyDescriptor> all() {
return Hudson.getInstance().<ViewProperty,ViewPropertyDescriptor>getDescriptorList(ViewProperty.class);
}
public ViewProperty reconfigure(StaplerRequest req, JSONObject form) throws Descriptor.FormException {
return getDescriptor().newInstance(req, form);
}
}
/*
* The MIT License
*
* Copyright (c) 2011, CloudBees, Inc., Stephen Connolly
*
* 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.model;
/**
* {@link Descriptor} for {@link ViewProperty}
*
* @author Stephen Connolly
* @since 1.406
*/
public abstract class ViewPropertyDescriptor extends Descriptor<ViewProperty> {
protected ViewPropertyDescriptor(Class<? extends ViewProperty> clazz) {
super(clazz);
}
/**
* Infers the type of the corresponding {@link Describable} from the outer class.
* This version works when you follow the common convention, where a descriptor
* is written as the static nested class of the describable class.
*/
protected ViewPropertyDescriptor() {
}
/**
* Creates a default instance of {@link ViewProperty} to be associated
* with {@link View} object that wasn't created from a persisted XML data.
*
* <p>
* See {@link View} class javadoc for more details about the life cycle
* of {@link View} and when this method is invoked.
*
* @return null
* if the implementation choose not to add any property object for such view.
*/
public abstract ViewProperty newInstance(View view);
/**
* Whether or not the described property is enabled in the current context.
* Defaults to true. Over-ride in sub-classes as required.
*
* <p>
* Returning false from this method essentially has the same effect of
* making core behaves as if this {@link ViewPropertyDescriptor} is
* not a part of {@link ViewProperty#all()}.
*
* <p>
* This mechanism is useful if the availability of the property is
* contingent of some other settings.
*/
public boolean isEnabled() {
return true;
}
}
......@@ -37,6 +37,7 @@ THE SOFTWARE.
<l:task icon="images/24x24/monitor.gif" href="load-statistics" title="${%Load Statistics}" />
<l:task icon="images/24x24/terminal.gif" href="script" title="${%Script Console}" permission="${app.ADMINISTER}" />
<st:include page="sidepanel2.jelly" optional="true" /><!-- hook for derived class to add more items -->
<t:actions />
</l:tasks>
<t:executors computers="${h.singletonList(it)}" />
</l:side-panel>
......
......@@ -50,6 +50,22 @@ THE SOFTWARE.
<!-- subtypes can put entries here. -->
<st:include page="configure-entries.jelly" optional="true" />
<!-- view property configurations -->
<j:invokeStatic var="descriptors" className="hudson.model.ViewProperty" method="all" />
<j:set var="instances" value="${it.properties}" />
<j:forEach var="d" items="${descriptors}" varStatus="loop">
<j:if test="${d.enabled}">
<f:section title="${d.displayName}">
<j:set var="descriptor" value="${d}" />
<j:set var="instance" value="${instances[d]}" />
<f:rowSet name="viewProperty${loop.index}">
<st:include from="${d}" page="${d.configPage}"/>
</f:rowSet>
</f:section>
</j:if>
</j:forEach>
<f:block>
<f:submit value="OK" />
</f:block>
......
......@@ -27,7 +27,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
......@@ -27,7 +27,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>maven-plugin</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>maven3-agent</artifactId>
<name>Jenkins Maven3 CLI Agent</name>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>maven3-interceptor</artifactId>
<name>Jenkins Maven3 Interceptor</name>
......
......@@ -32,7 +32,7 @@ THE SOFTWARE.
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Jenkins main module</name>
......
......@@ -27,7 +27,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
......@@ -27,7 +27,7 @@ THE SOFTWARE.
<parent>
<artifactId>pom</artifactId>
<groupId>org.jenkins-ci.main</groupId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.jenkins-ci.main</groupId>
......
......@@ -28,7 +28,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
</parent>
<artifactId>ui-samples-plugin</artifactId>
......
......@@ -27,7 +27,7 @@ THE SOFTWARE.
<parent>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>pom</artifactId>
<version>1.400.0-SNAPSHOT</version>
<version>1.400-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册